using System.Collections; using System.Collections.Generic; using UnityEngine; public struct JumpAbilityConfig { public PhysicsBody body; public PhysicsPrimitive collider; public Animator animator; public float neutralJumpSpeedY; // 垂直跳跃的基础速度 public float fowardJumpSpeedX; // 向前跳跃的水平速度 public float backwardJumpSpeedX; // 向后跳跃的水平速度(一般来说是负值) public int animJump; public int animNU; public int animFU; public int animBU; public int animND; public int animFD; public int animBD; public int animJumpEnd; public bool skipStart; //没有准备动作 } public class JumpAbility : AbilityBase { public enum Direction { None, Neutral, Forward, Backward } public enum State { None, Ready, Up, Down, End, } Direction m_Dir; PhysicsBody m_Body; PhysicsPrimitive m_Collider; Animator m_Animator; public float m_NeutralJumpSpeedY; // 垂直跳跃的基础速度 public float m_FowardJumpSpeedX; // 向前跳跃的水平速度 public float m_BackwardJumpSpeedX; // 向后跳跃的水平速度(一般来说是负值) // jump motions int m_AnimJumpStart; // on ground int m_AnimJumpNeutralUpwards; int m_AnimJumpNeutralDownwards; int m_AnimJumpFwdUpwards; int m_AnimJumpFwdDownwards; int m_AnimJumpBackUpwards; int m_AnimJumpBackDownwards; int m_AnimJumpEnd; // on ground again int m_CurAnim; State m_CurState; int m_CurUpMotion; int m_CurDownMotion; Vector3 m_CurInitVelocity; public State CurState { get { return m_CurState; } } public Direction CurDirection { get { return m_Dir; } } private List m_Triggers = new List(); bool m_SkipStart; public JumpAbility(JumpAbilityConfig config) { m_Body = config.body; m_Collider = config.collider; m_Animator = config.animator; m_NeutralJumpSpeedY = config.neutralJumpSpeedY; m_FowardJumpSpeedX = config.fowardJumpSpeedX; m_BackwardJumpSpeedX = config.backwardJumpSpeedX; m_AnimJumpStart = config.animJump; m_AnimJumpNeutralUpwards = config.animNU; m_AnimJumpNeutralDownwards = config.animND; m_AnimJumpFwdUpwards = config.animFU; m_AnimJumpFwdDownwards = config.animFD; m_AnimJumpBackUpwards = config.animBU; m_AnimJumpBackDownwards = config.animBD; m_AnimJumpEnd = config.animJumpEnd; // on ground again m_SkipStart = config.skipStart; } public void SetDir(Direction dir) { m_Dir = dir; } public override void OnEnter() { base.OnEnter(); m_CurAnim = 0; switch(m_Dir) { case Direction.Neutral: m_CurUpMotion = m_AnimJumpNeutralUpwards; m_CurDownMotion = m_AnimJumpNeutralDownwards; m_CurInitVelocity = new Vector3(0, m_NeutralJumpSpeedY, 0); break; case Direction.Forward: m_CurUpMotion = m_AnimJumpFwdUpwards; m_CurDownMotion = m_AnimJumpFwdDownwards; m_CurInitVelocity = new Vector3(m_FowardJumpSpeedX, m_NeutralJumpSpeedY, 0); break; case Direction.Backward: m_CurUpMotion = m_AnimJumpBackUpwards; m_CurDownMotion = m_AnimJumpBackDownwards; m_CurInitVelocity = new Vector3(m_BackwardJumpSpeedX, m_NeutralJumpSpeedY, 0); break; } bool isOnGround = m_Collider.IsOnGround; bool isUp = m_Body.Velocity.y > 0; bool isDown = m_Body.Velocity.y < 0; bool isFreeFall = Mathf.Approximately(m_Body.Velocity.y, 0); if (isOnGround && !m_SkipStart) m_CurState = State.Ready; else if (isUp || isOnGround && m_SkipStart) m_CurState = State.Up; else if (isDown || isFreeFall) m_CurState = State.Down; } public override void OnUpdate() { foreach (var abilityTrigger in m_Triggers) { if (abilityTrigger.Update() && abilityTrigger.Swallow) return; } AnimatorStateInfo motionInfo = m_Animator.GetCurrentAnimatorStateInfo(0); switch (m_CurState) { case State.Ready: if(m_CurAnim != m_AnimJumpStart) { m_Animator.CrossFade(m_AnimJumpStart, 0.2f); m_CurAnim = m_AnimJumpStart; } if(motionInfo.shortNameHash == m_AnimJumpStart && motionInfo.normalizedTime >= 1f) { m_CurState = State.Up; } break; case State.Up: if(m_CurAnim != m_CurUpMotion) { m_Body.LocalVelocity = m_CurInitVelocity; m_Animator.CrossFade(m_CurUpMotion, 0.2f); m_CurAnim = m_CurUpMotion; } if(m_Body.Velocity.y < 0) { m_CurState = State.Down; } break; case State.Down: if(m_CurAnim != m_CurDownMotion) { m_Animator.CrossFade(m_CurDownMotion, 0.5f); m_CurAnim = m_CurDownMotion; } if(m_Collider.IsOnGround) { m_CurState = State.End; } break; case State.End: if(m_CurAnim != m_AnimJumpEnd) { m_Animator.CrossFade(m_AnimJumpEnd, 0.2f); m_CurAnim = m_AnimJumpEnd; } break; } } public override void OnLateUpdate() { base.OnLateUpdate(); } /// /// 跳跃准备动作已经完毕 /// /// public bool IsJumpReady() { if (m_CurAnim != m_AnimJumpStart) return false; AnimatorStateInfo state = m_Animator.GetCurrentAnimatorStateInfo(0); if (state.shortNameHash == m_CurAnim && state.normalizedTime >= 1f) return true; return false; } /// /// 结束 /// /// public bool IsJumpDone(float t = 1f) { if (m_CurState == State.End) { AnimatorStateInfo state = m_Animator.GetCurrentAnimatorStateInfo(0); return state.shortNameHash == m_AnimJumpEnd && state.normalizedTime >= t; } return false; } /// /// 着地 /// /// public bool IsJumpGround() { return m_CurState == State.End && m_Collider.IsOnGround; } public void AddTrigger(Trigger trigger) { if (trigger == null || m_Triggers.Contains(trigger)) return; m_Triggers.Add(trigger); } }