using Snxxz.UI; using UnityEngine; using UnityEngine.Events; public abstract class GActorFight : GActor { public UnityAction OnDie; public UnityAction OnSkillCompelete; private Vector3 m_PrevPos; public Vector3 PrevPos { get { return m_PrevPos; } set { if (m_PrevPos == value) { return; } m_PrevPos = value; } } /// /// 被动选择的对象 /// 主角自动选怪目标, /// 其他玩家确定主攻击目标 /// private GActor selectTarget; public virtual GActor SelectTarget { get { return selectTarget; } set { selectTarget = value; } } /// /// 如果有,杀死这个npc的角色服务器实例ID /// private uint m_KillServerInstID; public uint KillerServerInstID { get { return m_KillServerInstID; } set { m_KillServerInstID = value; } } /// /// 如果有,杀死这个npc使用的死亡飞行配置 /// public int DeadFlyID { get; set; } public Vector3 KillerPos { get; set; } /// /// 被击死亡的时候攻击者的位置 /// public Vector3 KillPosWhenKilled { get; set; } protected AudioSource m_AudioSource = null; protected SkinnedMeshRenderer m_SMRenderer; protected Material m_Material; protected SkillManager m_SkillManager; public SkillManager SkillMgr { get { return m_SkillManager; } set { throw new System.NotImplementedException(); } } protected override void OnInit(GameNetPackBasic package) { ActorInfo.OnHpChange += RefreshLifeBar; m_SkillManager = new SkillManager(ServerInstID); // 创建音源 GameObject _audioSourceNode = Object.Instantiate(Resources.Load("Prefabs/AudioSource3D")) as GameObject; #if UNITY_EDITOR _audioSourceNode.name = "AudioSource"; #endif _audioSourceNode.transform.SetParent(m_Root); _audioSourceNode.transform.localPosition = new Vector3(0, 0.5f, 0); m_AudioSource = _audioSourceNode.GetComponent(); m_AudioSource.playOnAwake = false; m_AudioSource.spatialBlend = 1; } protected override void OnUnit() { m_StartedFlash = false; m_FlashLastTime = 0; SelectTarget = null; if (m_Material) { m_Material.SetFloat(m_FlashWhiteParamID, 0); } if (m_AudioSource) { Object.Destroy(m_AudioSource.gameObject); m_AudioSource = null; } selectTarget = null; ActorInfo.OnHpChange -= RefreshLifeBar; m_SkillManager = null; m_Material = null; m_SMRenderer = null; m_BeatCurve = null; OnDie = null; OnSkillCompelete = null; // 这里在npc卸载的时候对当前选中对象进行清除逻辑 GA_Hero _hero = PlayerDatas.Instance.hero; if (_hero != null) { if (_hero.LockTarget == this) { _hero.LockTarget = null; } if (_hero.SelectTarget == this) { _hero.SelectTarget = null; } } } public abstract override void Destroy(); /// /// 初始化出生点坐标 /// /// 服务端坐标X /// 服务端坐标Y public void InitBornPos(ushort sPosX, ushort sPosY) { AdjustPos(sPosX, sPosY); PrevPos = Pos; } protected override void OnUpdate() { if (m_SkillManager != null) { m_SkillManager.Update(); } } protected override void OnFixedUpdate() { UpdateFlashWhite(); UpdateFlashRed(); UpdateBeatBack(); } public abstract bool CanPushedBack(); public abstract bool CanHurted(); public abstract bool CanDieFly(); public abstract bool CanAtked(); public abstract bool CanAtkedRotate(); public abstract void RefreshLifeBar(uint value); public void Die(uint killerServerInstID, int configID = 0) { KillerServerInstID = killerServerInstID; DeadFlyID = configID; Die(); } #region 击退 private float m_BeatTime; private AnimationCurve m_BeatCurve; private Vector3 m_StartBeatPos; private float m_Factor; private float m_BeatStartTime; protected bool m_Beating; private Vector3 m_BeatDirection; public void StartBeatBack(int configID, Vector3 direction) { SoBodyControl _config = ScriptableObjectLoader.LoadSoBodyControl(configID); if (_config == null || _config.curve == null) { return; } m_BeatDirection = direction; m_BeatCurve = _config.curve; m_BeatTime = _config.duration; m_Factor = m_BeatCurve.keys[m_BeatCurve.length - 1].time; m_Factor = m_Factor / m_BeatTime; if (ActorType == GameObjType.gotNPC) { GActorNpcFight _npcBase = this as GActorNpcFight; if (_npcBase != null) { if (_npcBase.NpcConfig.weight != 0) { m_Factor = m_Factor / _npcBase.NpcConfig.weight; } } } m_StartBeatPos = Pos; m_BeatStartTime = Time.time; m_Beating = true; needSyncGroundHeight = false; } private void UpdateBeatBack() { if (!m_Beating) { return; } if (NextAction == GAStaticDefine.Act_Dead || m_BeatCurve == null) { m_Beating = false; return; } float _delta = (Time.time - m_BeatStartTime) * m_Factor; Vector3 _h = m_BeatDirection * _delta; Vector3 _v = new Vector3(0, m_BeatCurve.Evaluate(_delta), 0); Vector3 _pos = m_StartBeatPos + _h + _v; Vector3 _end = _pos; Vector3 _position = m_StartBeatPos; _position.y = 0; _end.y = 0; UnityEngine.AI.NavMeshHit _hit; if (UnityEngine.AI.NavMesh.Raycast(_position, _end, out _hit, -1)) { _end = _hit.position; } if (this is GActorNpcFight) { TryGetValidPos(_end, ref _end); } PrevPos = Pos = new Vector3(_end.x, _pos.y, _end.z); if (Time.time - m_BeatStartTime > m_BeatTime) { needSyncGroundHeight = true; m_Beating = false; } } #endregion #region 闪白, 闪红 private int m_FlashWhiteParamID = Shader.PropertyToID("_Hit"); private int m_FlashRedParamID = Shader.PropertyToID("_BaTi"); private bool m_StartedRed = false; private float m_FlashRedCurTime = 0; private float m_FlashRedTotablTime = 0; private bool m_StartedFlash = false; private float m_FlashLastTime; private float m_FlashLimitTime = 0.3f; public void DoFlashRed(float remainTime, float duration) { if (m_StartedRed) { return; } if (GetMaterial()) { GetMaterial().SetFloat(m_FlashRedParamID, 6); } m_FlashRedCurTime = duration - remainTime; m_FlashRedTotablTime = duration; m_StartedRed = true; } private void UpdateFlashRed() { if (m_StartedRed) { if (GetMaterial()) { m_FlashRedCurTime += Time.deltaTime; if (m_FlashRedCurTime > m_FlashRedTotablTime) { GetMaterial().SetFloat(m_FlashRedParamID, 0); m_StartedRed = false; } } else { m_StartedRed = false; } } } public void DoFlashWhite() { if (ServerInstID == PlayerDatas.Instance.PlayerId) { return; } m_StartedFlash = true; m_FlashLastTime = 0; } private void UpdateFlashWhite() { if (m_StartedFlash) { m_FlashLastTime += Time.deltaTime; float _flashValue = Constants.hurtAniCurve.animationCurve.Evaluate(2 * m_FlashLastTime); if (GetMaterial()) { GetMaterial().SetFloat(m_FlashWhiteParamID, _flashValue); } if (m_FlashLastTime > m_FlashLimitTime) { m_StartedFlash = false; GetMaterial().SetFloat(m_FlashWhiteParamID, 0); } } } #endregion protected Material GetMaterial() { return m_Material; } public SkinnedMeshRenderer GetSMRenderer() { return m_SMRenderer; } public void PlaySkillAudio(int id) { if (m_AudioSource) { SoundPlayer.Instance.PlayAudio(m_AudioSource, id); if (this is GA_Hero) { SoundUtility.PlayFightRoar(m_AudioSource, PlayerDatas.Instance.baseData.Job); } } } public virtual void PlayHurtAudio(GActorFight attacker) { SoundUtility.PlayHitAudio(attacker.m_AudioSource); } }