diff options
Diffstat (limited to 'Erika/Assets/Scripts/Unit/Components')
7 files changed, 239 insertions, 18 deletions
diff --git a/Erika/Assets/Scripts/Unit/Components/UnitAnimation/UnitMotion.cs b/Erika/Assets/Scripts/Unit/Components/UnitAnimation/UnitMotion.cs index a19512ec..f2a10e76 100644 --- a/Erika/Assets/Scripts/Unit/Components/UnitAnimation/UnitMotion.cs +++ b/Erika/Assets/Scripts/Unit/Components/UnitAnimation/UnitMotion.cs @@ -10,6 +10,8 @@ using UnityEditor; //https://docs.unity3d.com/ScriptReference/AnimatorOverrideController.html //https://docs.unity3d.com/ScriptReference/AnimatorOverrideController.ApplyOverrides.html +//Animator不能自动跳转动作,一切都应该以脚本控制,保证所有状态判断的有效性和准确性 + /// <summary> /// 角色动画管理 /// http://unitylore.org/wiki/doku.php?id=l3y0gj @@ -32,6 +34,7 @@ public class UnitMotion : UnitComponent // 角色的所有动作数据,包括(动画、事件、RM) public UnitMotionData m_MotionData; + // 动画帧事件 private TimelineEventProxy m_TimelineEventProxy; #region 动作状态 @@ -55,6 +58,9 @@ public class UnitMotion : UnitComponent private bool m_Dirty = true; + /// <summary> + /// Animator是否处于过渡状态 + /// </summary> public bool isInTransition { get @@ -97,8 +103,25 @@ public class UnitMotion : UnitComponent } } + public float playbackNormalizedTime + { + get + { + AnimatorStateInfo state = stateInfo; + return state.normalizedTime; + } + } + + public float playbackTimeInSeconds + { + get + { + return playbackNormalizedTime * animationClip.length; + } + } + // 归一化的动画播放时间 - public float playbackClampedNormalizedTime + public float playbackClampedNormalizedTime { get { @@ -119,6 +142,9 @@ public class UnitMotion : UnitComponent } } + /// <summary> + /// 当前动作的AnimatorState + /// </summary> public AnimatorStateInfo stateInfo { get @@ -156,6 +182,17 @@ public class UnitMotion : UnitComponent } /// <summary> + /// 当前动作是否是循环动画 + /// </summary> + public bool isCurrentLooping + { + get + { + return animationClip.isLooping; + } + } + + /// <summary> /// 当前动作是否是motionId /// </summary> /// <param name="motionId"></param> @@ -167,6 +204,24 @@ public class UnitMotion : UnitComponent return m_currentMotionIDID == motionId; } + /// <summary> + /// 是否播放结束,对于looping动作,默认不会结束 + /// </summary> + /// <param name="bCheckLoop">对于循环动画,是否检查结束</param> + /// <returns></returns> + public bool IsReachEnd(bool bCheckLoop = false) + { + bool playbackEnd = playbackNormalizedTime >= 1f; + if (isCurrentLooping) + { + return playbackEnd && bCheckLoop; + } + else + { + return playbackEnd; + } + } + #endregion public override void OnUpdate() @@ -176,21 +231,49 @@ public class UnitMotion : UnitComponent m_TimelineEventProxy.ExecuteAnimationEvents(animationData, playbackClampedTimeInSeconds * TimelineEventProxy.FPS); // 播放速度控制 - if (/*applySpeedCurve && */animationData != null && animationData.speedCurve != null) - { - playbackSpeed = animationData.speedCurve.Evaluate(playbackClampedNormalizedTime); - } - } + if(animationData != null) + { + if(!animationData.actionSettings.disableTimeCurve) + { + if (/*applySpeedCurve && */animationData.speedCurve != null) + { + playbackSpeed = animationData.speedCurve.Evaluate(playbackClampedNormalizedTime); + } + } + else + { + playbackSpeed = animationData.actionSettings.defaultPlaySpeed; + } + } + } public bool IsToggleOpen(EAnimationToogle toggle) { return animationData.IsToggleOpen(toggle, playbackClampedNormalizedTime); } - //public override void Initialize() - //{ - // base.Initialize(); - //} + public bool HasToogle(EAnimationToogle toggle) + { + return animationData.HasToggle(toggle); + } + + public bool CanComboLink() + { + return !owner.unitStatemachine.IsInState(EUnitState.Skill) + || IsToggleOpen(EAnimationToogle.ComboLink); + } + + public bool IsChangeAble() + { + return !owner.unitStatemachine.IsInState(EUnitState.Skill) + || IsToggleOpen(EAnimationToogle.ChangeAble) + || !HasToogle(EAnimationToogle.ChangeAble); + } + + //public override void Initialize() + //{ + // base.Initialize(); + //} public override void Initialize(object obj) { diff --git a/Erika/Assets/Scripts/Unit/Components/UnitCollider.cs b/Erika/Assets/Scripts/Unit/Components/UnitCollider.cs index b0910c0c..54bf7dab 100644 --- a/Erika/Assets/Scripts/Unit/Components/UnitCollider.cs +++ b/Erika/Assets/Scripts/Unit/Components/UnitCollider.cs @@ -138,7 +138,7 @@ public class UnitCollider : UnitComponent Vector3 unitPos = m_Owner.transform.position; - OnDrawColliders(ColliderBox.EColliderType.HurtBox, Color.green); + //OnDrawColliders(ColliderBox.EColliderType.HurtBox, Color.green); OnDrawColliders(ColliderBox.EColliderType.HitBox, Color.red); OnDrawColliders(ColliderBox.EColliderType.BlockBox, Color.yellow); OnDrawColliders(ColliderBox.EColliderType.DefendBox, Color.magenta); diff --git a/Erika/Assets/Scripts/Unit/Components/UnitSkill.cs b/Erika/Assets/Scripts/Unit/Components/UnitSkill.cs index c8f31f31..485a49fb 100644 --- a/Erika/Assets/Scripts/Unit/Components/UnitSkill.cs +++ b/Erika/Assets/Scripts/Unit/Components/UnitSkill.cs @@ -10,10 +10,8 @@ public class UnitSkill : UnitComponent public List<SkillData> skills; public List<ComboData> combos; } - //角色所有技能数据 protected List<SkillData> m_AllSkills; - //所有连击数据 protected List<ComboData> m_AllCombos; @@ -33,6 +31,14 @@ public class UnitSkill : UnitComponent } } + #region 技能状态 + // 连击池 + private int m_CurrentCombo = 0; + private int m_CurrentComboIndex = 0; + private List<int> m_AttackPool = new List<int>(); + + #endregion + public override void Initialize(object obj = null) { base.Initialize(obj); @@ -40,10 +46,40 @@ public class UnitSkill : UnitComponent Param param = (Param)obj; m_AllSkills = param.skills; m_AllCombos = param.combos; + } + public override void OnUpdate() + { + base.OnUpdate(); + + if (m_AttackPool.Count != 0 && owner.unitMotion.IsChangeAble()) + { + int skillId = m_AttackPool[0]; + m_AttackPool.RemoveAt(0); + + CastSkill(skillId); + } + if (!owner.unitStatemachine.IsSkill()) + { + ClearCombo(); + } + } + + #region 数据访问 + + public ComboData GetComboById(int comboId) + { + return m_AllCombos.Find(combo => combo.uid == comboId); } + public SkillData GetSkillById(int skillId) + { + return m_AllSkills.Find(skill => skill.uid == skillId); + } + + #endregion + #region 技能状态判定 /// <summary> @@ -65,6 +101,54 @@ public class UnitSkill : UnitComponent return false; } + #endregion + + #region 技能释放 + + public void CastCombo(int comboId) + { + ComboData combo = GetComboById(comboId); + + if (m_CurrentCombo != comboId) + { + m_CurrentCombo = comboId; + m_CurrentComboIndex = 0; + + int skillId = combo.skills[0]; + m_AttackPool.Add(skillId); + } + else + { + if (++m_CurrentComboIndex < combo.skills.Count) + { + int skillId = combo.skills[m_CurrentComboIndex]; + if (skillId != 0) + { + m_AttackPool.Add(skillId); + } + } + } + } + + /// <summary> + /// 释放技能,状态机切换 + /// </summary> + /// <param name="skillId"></param> + public void CastSkill(int skillId) + { + UnitStates.Common.SkillState.SkillParam param = new UnitStates.Common.SkillState.SkillParam(); + param.skillId = skillId; + + owner.unitStatemachine.ChangeState(EUnitState.Skill, param); + } + + public void ClearCombo() + { + m_CurrentCombo = 0; + m_CurrentComboIndex = 0; + m_AttackPool.Clear(); + } + #endregion } diff --git a/Erika/Assets/Scripts/Unit/Components/UnitStatemachine/Common/MoveState.cs b/Erika/Assets/Scripts/Unit/Components/UnitStatemachine/Common/MoveState.cs index 439d5c80..c372c452 100644 --- a/Erika/Assets/Scripts/Unit/Components/UnitStatemachine/Common/MoveState.cs +++ b/Erika/Assets/Scripts/Unit/Components/UnitStatemachine/Common/MoveState.cs @@ -8,7 +8,7 @@ namespace UnitStates.Common public class MoveState : UnitStateBase { - public struct IdleParam : IStateParam + public struct Param : IStateParam { } diff --git a/Erika/Assets/Scripts/Unit/Components/UnitStatemachine/Common/SkillState.cs b/Erika/Assets/Scripts/Unit/Components/UnitStatemachine/Common/SkillState.cs index 061a607c..421d0c48 100644 --- a/Erika/Assets/Scripts/Unit/Components/UnitStatemachine/Common/SkillState.cs +++ b/Erika/Assets/Scripts/Unit/Components/UnitStatemachine/Common/SkillState.cs @@ -9,15 +9,26 @@ namespace UnitStates.Common { public struct SkillParam : IStateParam { + public int skillId; + public EUnitDirection direction; // 攻击方向 } + private int m_SkillId; + private int m_MotionId; + public override void ModifyNextState(EUnitState state, UnitStateBase nextState) { } public override void OnEnter(IStateParam param) { - m_Motion.Trigger(EAnimationType.Idle); + SkillParam skillParam = (SkillParam)param; + m_SkillId = skillParam.skillId; + + SkillData skill = m_Owner.unitSkill.GetSkillById(m_SkillId); + m_MotionId = skill.motionId; + + m_Owner.unitMotion.Trigger(m_MotionId); } public override void OnExit() @@ -30,6 +41,13 @@ namespace UnitStates.Common public override void OnUpdate() { + //if (m_Owner.unitMotion.IsReachEnd()) + // m_Owner.unitStatemachine.ChangeState(EUnitState.Idle, null); + + if (unitMotion.IsCurrent(m_MotionId) && unitMotion.IsReachEnd()) + { + fsm.ChangeState(EUnitState.Idle); + } } } } diff --git a/Erika/Assets/Scripts/Unit/Components/UnitStatemachine/UnitStateBase.cs b/Erika/Assets/Scripts/Unit/Components/UnitStatemachine/UnitStateBase.cs index f7396555..472a8850 100644 --- a/Erika/Assets/Scripts/Unit/Components/UnitStatemachine/UnitStateBase.cs +++ b/Erika/Assets/Scripts/Unit/Components/UnitStatemachine/UnitStateBase.cs @@ -15,6 +15,14 @@ public abstract class UnitStateBase protected UnitStatemachine m_Statemachine; protected UnitMotion m_Motion; + + protected UnitMotion unitMotion => m_Owner.unitMotion; + + + #region shortcut + protected UnitStatemachine fsm => m_Statemachine; + #endregion + public void Set(UnitController owner, UnitStatemachine statemachine) { m_Owner = owner; diff --git a/Erika/Assets/Scripts/Unit/Components/UnitStatemachine/UnitStatemachine.cs b/Erika/Assets/Scripts/Unit/Components/UnitStatemachine/UnitStatemachine.cs index e6c820d3..ef70beaa 100644 --- a/Erika/Assets/Scripts/Unit/Components/UnitStatemachine/UnitStatemachine.cs +++ b/Erika/Assets/Scripts/Unit/Components/UnitStatemachine/UnitStatemachine.cs @@ -113,14 +113,28 @@ public sealed class UnitStatemachine : UnitComponent return null; } + private bool IsChange(EUnitState cur, EUnitState next, bool bForce = false) + { + if (bForce) + return true; + + // skill, hit能够自身跳转 + if(!IsSkill() + && !IsHitted() + && cur == next ) + return false; + + return true; + } + /// <summary> /// 切换到目标状态 /// </summary> /// <param name="state"></param> - public bool ChangeState(EUnitState state, UnitStateBase.IStateParam param, bool bForce = false) + public bool ChangeState(EUnitState state, UnitStateBase.IStateParam param = null, bool bForce = false) { - if (!bForce && m_CurrentState == state) - return true; + if(!IsChange(m_CurrentState, state, bForce)) + return false; UnitStateBase currentState = GetState(m_CurrentState); UnitStateBase nextState = GetState(state); @@ -166,4 +180,18 @@ public sealed class UnitStatemachine : UnitComponent return m_AllStates.ContainsKey(state); } + #region 状态判定 + + public bool IsSkill() + { + return m_CurrentState == EUnitState.Skill; + } + + public bool IsHitted() + { + return m_CurrentState == EUnitState.HitAir; + } + + #endregion + } |