498 lines
14 KiB
Lua
498 lines
14 KiB
Lua
local CharacterFSMManager = require "app/module/character_fsm/character_fsm_manager"
|
|
local BaseObject = require "app/bf/unity/base_object"
|
|
local CharacterObject = class("CharacterObject", BaseObject)
|
|
|
|
local BF_CHARACTER_HELPER = GConst.TYPEOF_UNITY_CLASS.BF_CHARACTER_HELPER
|
|
local ANIMATOR = GConst.TYPEOF_UNITY_CLASS.ANIMATOR
|
|
local ANIMATION_FRAME_PER_SECOND = 30
|
|
|
|
local SUPPORT_SHADER = {
|
|
["BF/Models/Character Battle"] = true,
|
|
}
|
|
|
|
local hash = GFunc.hash
|
|
|
|
local HashName = {}
|
|
local function getHashName(str)
|
|
local intName = HashName[str]
|
|
if intName == nil then
|
|
intName = hash(str)
|
|
HashName[str] = intName
|
|
end
|
|
return intName
|
|
end
|
|
|
|
local CHILDMAP_METATABLE = {
|
|
__index = function(t, k)
|
|
if rawget(t, k) == nil then
|
|
local v = rawget(t, hash(k))
|
|
if v then
|
|
rawset(t, k, v)
|
|
end
|
|
return v
|
|
end
|
|
return rawget(t, k)
|
|
end
|
|
}
|
|
|
|
local Vector3 = BF.Vector3(0, 0, 0)
|
|
|
|
local abs = math.abs
|
|
|
|
function CharacterObject:ctor()
|
|
self.timeScale = 1
|
|
end
|
|
|
|
function CharacterObject:initWithPrefab(assetPath, prefab, modelId)
|
|
BaseObject.initWithPrefab(self, assetPath, prefab)
|
|
self.characterHelper = self:getComponent(BF_CHARACTER_HELPER)
|
|
if self.characterHelper == nil then
|
|
self.characterHelper = self:addComponent(BF_CHARACTER_HELPER)
|
|
end
|
|
self.mainModel = self.characterHelper:GetModelObject()
|
|
self.objectIndex = -1
|
|
self.modelId = modelId
|
|
self:_genAllBones()
|
|
end
|
|
|
|
function CharacterObject:initWithCharacterHelper(characterHelper, index, gameObject, name, admin)
|
|
self.characterHelper = characterHelper
|
|
self.objectIndex = index
|
|
self.gameObject = gameObject
|
|
self.name = name
|
|
self.admin = admin
|
|
end
|
|
|
|
function CharacterObject:_genAllBones()
|
|
local childMap = {}
|
|
if self.characterHelper then
|
|
local childNum = self.characterHelper:GetListCount()
|
|
for i = 0, childNum do
|
|
local gameObject = self.characterHelper:GetGameObjectByIndex(i)
|
|
local hashName = self.characterHelper:GetHashNameByIndex(i)
|
|
local child = CharacterObject:create()
|
|
child:initWithCharacterHelper(self.characterHelper, i, gameObject, hashName, self)
|
|
if childMap[hashName] == nil then
|
|
childMap[hashName] = child
|
|
end
|
|
table.insert(self.childList, child)
|
|
end
|
|
end
|
|
setmetatable(childMap, CHILDMAP_METATABLE)
|
|
self.childMap = childMap
|
|
end
|
|
|
|
function CharacterObject:getBoneByName(name)
|
|
return self.childMap[name]
|
|
end
|
|
|
|
function CharacterObject:fastGetPosition()
|
|
if self.characterHelper then
|
|
self.characterHelper:CachePosition(self.objectIndex)
|
|
return self.characterHelper.PositionX, self.characterHelper.PositionY, self.characterHelper.PositionZ
|
|
else
|
|
local position = self:getTransform().position
|
|
return position.x, position.y, position.z
|
|
end
|
|
end
|
|
|
|
function CharacterObject:getBonePositionByName(name)
|
|
return self.childMap[name]:fastGetPosition()
|
|
end
|
|
|
|
function CharacterObject:getHashCode()
|
|
local code = -1
|
|
if self.characterHelper then
|
|
code = self.characterHelper:GetModelHashCode()
|
|
end
|
|
return code
|
|
end
|
|
|
|
function CharacterObject:play(name, layer, normalizedTime)
|
|
layer = layer or -1
|
|
normalizedTime = normalizedTime or 0
|
|
|
|
if self.weaponObj and not self.weaponObj:isDestroyed() then
|
|
if self.weaponAniName then
|
|
-- local weaponAniName = self:getWeaponSpecialAni(name, self.weaponAniName, true)
|
|
-- if self.weaponObj:getStateTime(weaponAniName) > 0 then
|
|
-- self.weaponObj:play(weaponAniName, layer, normalizedTime)
|
|
-- end
|
|
|
|
local newName = self:getWeaponSpecialAni(name, self.weaponAniName) or name
|
|
if self:getStateTime(newName) > 0 then
|
|
name = newName
|
|
end
|
|
end
|
|
else
|
|
self:setWeaponInfo()
|
|
end
|
|
|
|
if self.mainAnimator == nil then
|
|
if self.mainModel then
|
|
self.mainAnimator = self.mainModel:GetComponent(ANIMATOR)
|
|
self.mainAnimator:Play(name, layer, normalizedTime)
|
|
end
|
|
else
|
|
self.mainAnimator:Play(name, layer, normalizedTime)
|
|
end
|
|
end
|
|
|
|
function CharacterObject:playHashName(hashName, layer, normalizedTime)
|
|
layer = layer or -1
|
|
normalizedTime = normalizedTime or 0
|
|
|
|
if self.weaponObj and not self.weaponObj:isDestroyed() then
|
|
if self.weaponAniName then
|
|
-- local weaponHashName = self:getWeaponSpecialAniHash(hashName, self.weaponAniName, true)
|
|
-- if self.weaponObj:getStateTimeHash(weaponHashName) > 0 then
|
|
-- self.weaponObj:playHashName(weaponHashName, layer, normalizedTime)
|
|
-- end
|
|
|
|
local newHashName = self:getWeaponSpecialAniHash(hashName, self.weaponAniName, true) or hashName
|
|
if self:getStateTimeHash(newHashName) > 0 then
|
|
hashName = newHashName
|
|
end
|
|
end
|
|
else
|
|
self:setWeaponInfo()
|
|
end
|
|
|
|
if self.mainAnimator == nil then
|
|
if self.mainModel then
|
|
self.mainAnimator = self.mainModel:GetComponent(ANIMATOR)
|
|
self.mainAnimator:Play(hashName, layer, normalizedTime)
|
|
end
|
|
else
|
|
self.mainAnimator:Play(hashName, layer, normalizedTime)
|
|
end
|
|
end
|
|
|
|
function CharacterObject:getWeaponSpecialAni(name, specialAniName, isWeapon)
|
|
if not self.weaponSpecialAniMap then
|
|
self.weaponSpecialAniMap = {}
|
|
end
|
|
|
|
if not self.weaponSpecialAniMap[name] then
|
|
self.weaponSpecialAniMap[name] = {}
|
|
end
|
|
|
|
if not self.weaponSpecialAniMap[name][specialAniName] then
|
|
self.weaponSpecialAniMap[name][specialAniName] = {}
|
|
end
|
|
|
|
if not isWeapon then
|
|
if not self.weaponSpecialAniMap[name][specialAniName].heroAniName then
|
|
self.weaponSpecialAniMap[name][specialAniName].heroAniName = name .. "_" .. specialAniName
|
|
end
|
|
return self.weaponSpecialAniMap[name][specialAniName].heroAniName
|
|
else
|
|
if not self.weaponSpecialAniMap[name][specialAniName].weaponAniName and self.modelId then
|
|
self.weaponSpecialAniMap[name][specialAniName].weaponAniName = self.modelId .. "_" .. name .. "_" .. specialAniName
|
|
end
|
|
return self.weaponSpecialAniMap[name][specialAniName].weaponAniName
|
|
end
|
|
end
|
|
|
|
function CharacterObject:getWeaponSpecialAniHash(hashName, specialAniName, isWeapon)
|
|
if not self.weaponSpecialAniHashMap then
|
|
self.weaponSpecialAniHashMap = {}
|
|
end
|
|
|
|
if not self.weaponSpecialAniHashMap[hashName] then
|
|
self.weaponSpecialAniHashMap[hashName] = {}
|
|
end
|
|
|
|
if not self.weaponSpecialAniHashMap[hashName][specialAniName] then
|
|
self.weaponSpecialAniHashMap[hashName][specialAniName] = {}
|
|
end
|
|
|
|
if not isWeapon then
|
|
if not self.weaponSpecialAniHashMap[hashName][specialAniName].heroAniName then
|
|
local name = GConst.HeroConst.HERO_ANI_HASH_MAP[hashName]
|
|
if name then
|
|
self.weaponSpecialAniHashMap[hashName][specialAniName].heroAniName = CS.UnityEngine.Animator.StringToHash(name .. "_" .. specialAniName)
|
|
end
|
|
end
|
|
return self.weaponSpecialAniHashMap[hashName][specialAniName].heroAniName
|
|
else
|
|
if not self.weaponSpecialAniHashMap[hashName][specialAniName].weaponAniName and self.modelId then
|
|
local name = GConst.HeroConst.HERO_ANI_HASH_MAP[hashName]
|
|
if name then
|
|
self.weaponSpecialAniHashMap[hashName][specialAniName].weaponAniName = CS.UnityEngine.Animator.StringToHash(self.modelId .. "_" .. name .. "_" .. specialAniName)
|
|
end
|
|
end
|
|
return self.weaponSpecialAniHashMap[hashName][specialAniName].weaponAniName
|
|
end
|
|
end
|
|
|
|
function CharacterObject:setWeaponInfo(weaponAniName, weaponObj)
|
|
if not weaponObj then
|
|
self.weaponAniName = nil
|
|
self.weaponObj = nil
|
|
end
|
|
self.weaponAniName = weaponAniName
|
|
self.weaponObj = weaponObj
|
|
end
|
|
|
|
function CharacterObject:setAnimatorBool(key, value)
|
|
if self.mainAnimator == nil then
|
|
if self.mainModel then
|
|
self.mainAnimator = self.mainModel:GetComponent(ANIMATOR)
|
|
self.mainAnimator:SetBool(key, value)
|
|
end
|
|
else
|
|
self.mainAnimator:SetBool(key, value)
|
|
end
|
|
end
|
|
|
|
function CharacterObject:getMainAnimator()
|
|
if self.mainAnimator == nil then
|
|
if self.mainModel then
|
|
self.mainAnimator = self.mainModel:GetComponent(ANIMATOR)
|
|
end
|
|
end
|
|
return self.mainAnimator
|
|
end
|
|
|
|
function CharacterObject:getMainModelTransform()
|
|
if self.mainModelTransform == nil then
|
|
self.mainModelTransform = self.mainModel and self.mainModel.transform or nil
|
|
end
|
|
return self.mainModelTransform
|
|
end
|
|
|
|
function CharacterObject:getMainModel()
|
|
return self.mainModel
|
|
end
|
|
|
|
function CharacterObject:getCurrentAnimationHash()
|
|
return CS.BF.Utils.GetCurrentAnimationHash(self:getMainAnimator())
|
|
end
|
|
|
|
function CharacterObject:setMainModelLocalScale(x, y, z)
|
|
local transform = self:getMainModelTransform()
|
|
if transform then
|
|
Vector3.x = x
|
|
Vector3.y = y
|
|
Vector3.z = z
|
|
transform.localScale = Vector3
|
|
end
|
|
end
|
|
|
|
function CharacterObject:setMainModelLocalPosition(x, y, z)
|
|
if self.characterHelper then
|
|
self.characterHelper:SetMainModelLocalPosition(x, y, z)
|
|
else
|
|
local transform = self:getMainModelTransform()
|
|
if transform then
|
|
Vector3.x = x
|
|
Vector3.y = y
|
|
Vector3.z = z
|
|
transform.localPosition = Vector3
|
|
end
|
|
end
|
|
end
|
|
|
|
function CharacterObject:getStateTime(name)
|
|
local hashName = getHashName(name)
|
|
return self.characterHelper:GetStateTime(hashName)
|
|
end
|
|
|
|
function CharacterObject:getStateTimeHash(hashName)
|
|
return self.characterHelper:GetStateTime(hashName)
|
|
end
|
|
|
|
function CharacterObject:getStateKeyTime(name, index)
|
|
local hashName = getHashName(name)
|
|
local keyTime = self.characterHelper:GetStateKeyFrame(hashName, index) or 0
|
|
return keyTime/ANIMATION_FRAME_PER_SECOND
|
|
end
|
|
|
|
function CharacterObject:containsState(name)
|
|
return self:getStateTime(name) > 0.00001
|
|
end
|
|
|
|
function CharacterObject:setTimeScale(timeScale)
|
|
if abs(self.timeScale - timeScale) < 0.00001 then
|
|
return
|
|
end
|
|
self.timeScale = timeScale
|
|
local mainAnimator = self:getMainAnimator()
|
|
mainAnimator.speed = timeScale*(self.timeScaleAddition or 1)
|
|
end
|
|
|
|
function CharacterObject:setTimeScaleAddition(addition)
|
|
self.timeScaleAddition = addition
|
|
local timeScale = self.timeScale*addition
|
|
local mainAnimator = self:getMainAnimator()
|
|
mainAnimator.speed = timeScale
|
|
end
|
|
|
|
function CharacterObject:setCullingMode(cullingMode)
|
|
local mainAnimator = self:getMainAnimator()
|
|
if mainAnimator then
|
|
mainAnimator.cullingMode = cullingMode
|
|
end
|
|
end
|
|
|
|
function CharacterObject:getCharacterMaterials()
|
|
if not self.characterMaterials then
|
|
self.characterMaterials = {}
|
|
for k, prefabObj in pairs(self.childMap) do
|
|
local render = prefabObj:getComponent(GConst.TYPEOF_UNITY_CLASS.SKINNED_MESH_RENDERER)
|
|
if not CS.BF.Utils.IsNull(render) and not CS.BF.Utils.IsNull(render.material) and SUPPORT_SHADER[render.material.shader.name] then
|
|
table.insert(self.characterMaterials, render.material)
|
|
end
|
|
end
|
|
end
|
|
return self.characterMaterials
|
|
end
|
|
|
|
function CharacterObject:getCharacterMeshRenderer()
|
|
if not self.characterMeshRenders then
|
|
self.characterMeshRenders = {}
|
|
for k, prefabObj in pairs(self.childMap) do
|
|
local render = prefabObj:getComponent(GConst.TYPEOF_UNITY_CLASS.SKINNED_MESH_RENDERER)
|
|
if not CS.BF.Utils.IsNull(render) and not CS.BF.Utils.IsNull(render.material) and SUPPORT_SHADER[render.material.shader.name] then
|
|
table.insert(self.characterMeshRenders, render)
|
|
end
|
|
end
|
|
end
|
|
return self.characterMeshRenders
|
|
end
|
|
|
|
function CharacterObject:getMaterialPropertyBlock()
|
|
if not self.mpb then
|
|
self.mpb = CS.UnityEngine.MaterialPropertyBlock()
|
|
end
|
|
return self.mpb
|
|
end
|
|
|
|
function CharacterObject:setCustomShadowEnable(enabled)
|
|
local materials = self:getCharacterMaterials()
|
|
for _, material in ipairs(materials) do
|
|
material:SetShaderPassEnabled("Always", enabled)
|
|
end
|
|
end
|
|
|
|
function CharacterObject:setCharacterFSM(fsm)
|
|
self.fsm = fsm
|
|
end
|
|
|
|
---- 默认
|
|
function CharacterObject:setDefault()
|
|
if self.fsm:getCurStateKey() == CharacterFSMManager.STATE_TYPE.DEFAULT then
|
|
return
|
|
end
|
|
self.fsm:changeState(CharacterFSMManager.STATE_TYPE.DEFAULT)
|
|
end
|
|
|
|
---- 石化
|
|
function CharacterObject:setStone(callback)
|
|
if self.fsm:getCurStateKey() == CharacterFSMManager.STATE_TYPE.STONE then
|
|
return
|
|
end
|
|
self.fsm:changeState(CharacterFSMManager.STATE_TYPE.STONE, {callback = callback})
|
|
end
|
|
|
|
---- 石化效果2
|
|
function CharacterObject:setStone2(callback)
|
|
if self.fsm:getCurStateKey() == CharacterFSMManager.STATE_TYPE.STONE_2 then
|
|
return
|
|
end
|
|
self.fsm:changeState(CharacterFSMManager.STATE_TYPE.STONE_2, {callback = callback})
|
|
end
|
|
|
|
---- 冰化
|
|
function CharacterObject:setIce()
|
|
if self.fsm:getCurStateKey() == CharacterFSMManager.STATE_TYPE.ICE then
|
|
return
|
|
end
|
|
self.fsm:changeState(CharacterFSMManager.STATE_TYPE.ICE)
|
|
end
|
|
|
|
---- 闪红
|
|
function CharacterObject:setGlow(time, callback)
|
|
local state = self.fsm:getCurStateKey()
|
|
if state == CharacterFSMManager.STATE_TYPE.DISSOLVE or state == CharacterFSMManager.STATE_TYPE.GLOW then
|
|
return
|
|
end
|
|
|
|
if state == CharacterFSMManager.STATE_TYPE.ICE then
|
|
self.fsm:changeState(CharacterFSMManager.STATE_TYPE.DEFAULT)
|
|
end
|
|
|
|
self.fsm:changeState(CharacterFSMManager.STATE_TYPE.GLOW, {time = time or 0.7, callback = function()
|
|
if callback then
|
|
callback()
|
|
end
|
|
self.fsm:changeState(state)
|
|
end})
|
|
end
|
|
|
|
---- 消融
|
|
function CharacterObject:setDissolve(time, callback, needCallback)
|
|
self.fsm:changeState(CharacterFSMManager.STATE_TYPE.DISSOLVE, {time = time,
|
|
callback = callback,
|
|
needCallback = needCallback})
|
|
end
|
|
|
|
function CharacterObject:setShadowColor(color)
|
|
local renderers = self:getCharacterMeshRenderer()
|
|
local mpBlock = self:getMaterialPropertyBlock()
|
|
for i, renderer in ipairs(renderers) do
|
|
renderer:GetPropertyBlock(mpBlock)
|
|
mpBlock:SetColor("_shadow_color", color)
|
|
renderer:SetPropertyBlock(mpBlock)
|
|
end
|
|
end
|
|
|
|
function CharacterObject:setLocalEulerAngles(x, y, z)
|
|
if self.characterHelper then
|
|
self.characterHelper:SetLocalEulerAngles(self.objectIndex, x, y, z)
|
|
else
|
|
BaseObject.setLocalEulerAngles(self, x, y, z)
|
|
end
|
|
end
|
|
|
|
function CharacterObject:setLocalPosition(x, y, z)
|
|
if self.characterHelper then
|
|
self.characterHelper:SetLocalPosition(self.objectIndex, x, y, z)
|
|
else
|
|
BaseObject.setLocalPosition(self, x, y, z)
|
|
end
|
|
end
|
|
|
|
function CharacterObject:setPosition(x, y, z)
|
|
if self.characterHelper then
|
|
self.characterHelper:SetPosition(self.objectIndex, x, y, z)
|
|
else
|
|
BaseObject.setPosition(self, x, y, z)
|
|
end
|
|
end
|
|
|
|
function CharacterObject:setLocalScale(x, y, z)
|
|
if self.characterHelper then
|
|
self.characterHelper:SetLocalScale(self.objectIndex, x, y, z)
|
|
else
|
|
BaseObject.setLocalScale(self, x, y, z)
|
|
end
|
|
end
|
|
|
|
function CharacterObject:onDestroy()
|
|
if self.fsm then
|
|
CharacterFSMManager:stopFSM(self.fsm)
|
|
self.fsm = nil
|
|
end
|
|
BaseObject.onDestroy(self)
|
|
self.characterHelper = nil
|
|
self.mainModel = nil
|
|
self.mainAnimator = nil
|
|
self.childMap = nil
|
|
self.characterMaterials = nil
|
|
self.characterMeshRenders = nil
|
|
self.mpb = nil
|
|
end
|
|
|
|
return CharacterObject |