跳跃状态检测与RootMotion跳跃

添加跳跃状态。
    
    
public enum PlayerState { Idle , Move , Jump }
添加跳跃的转换逻辑。
    
    
//PlayerController public void ChangeState ( PlayerState playerState ) { switch ( playerState ) { case PlayerState . Idle : stateMachine . ChangeState < PlayerIdleState > ( ) ; break ; case PlayerState . Move : stateMachine . ChangeState < PlayerMoveState > ( ) ; break ; case PlayerState . Jump : stateMachine . ChangeState < PlayerJumpState > ( ) ; break ; default : break ; } }
创建PlayerJumpState。
    
    
public class PlayerJumpState : PlayerStateBase { public override void Enter ( ) { player . PlayAnimation ( "Jump" ) ; player . PlayerModel . SetRootMotionAction ( OnRootMotion ) ; } public override void Update ( ) { //第一次执行Update时,也许当前动画还不是Jump //确定当前是播放Jump动画 AnimatorStateInfo stateInfo = player . PlayerModel . Animator . GetCurrentAnimatorStateInfo ( 0 ) ; if ( stateInfo . IsName ( "Jump" ) ) { //获取动画的进度 float animationTime = stateInfo . normalizedTime ; if ( animationTime > 0.1f && animationTime < 0.6f ) { } else if ( animationTime >= 0.9f ) { player . ChangeState ( PlayerState . Idle ) ; return ; } } } public override void Exit ( ) { player . PlayerModel . ClearRootMotion ( ) ; } public void OnRootMotion ( Vector3 deltaPosition , Quaternion deltaRotation ) { player . CharacterController . Move ( deltaPosition ) ; } }
  • 在进入跳跃状态时播放跳跃状态,并将跳跃的RootMotion逻辑(和移动是一样的)传递给PlayerModel的RootMotionAction执行。
  • 在跳跃动画播放进度10%~60%时允许移动等其他逻辑,注意判断当前动画是否为跳跃动画,进入跳跃状态后,还有可能处于动画切换的过程。
  • 在跳跃动画播放进度超过90%时,切换回Idle状态。
  • 退出时清空RootMotionAction。
    
    
//检测玩家跳跃 if ( Input . GetKeyDown ( KeyCode . Space ) ) { player . ChangeState ( PlayerState . Jump ) ; return ; }
分别给PlayerMoveState,和PlayerIdleState添加跳跃状态的检测。

空中位移和旋转

首先设置空中跳跃的高度,给RootMotion位移乘一个系数。
    
    
public void OnRootMotion ( Vector3 deltaPosition , Quaternion deltaRotation ) { deltaPosition . y *= player . jumpForce ; player . CharacterController . Move ( deltaPosition ) ; }
对应添加跳跃力和空中位移速度的配置量。
    
    
//PlayerController [ Header ( "配置信息" ) ] public float gravity = - 9.8f ; public float rotateSpeed = 8f ; public float walk2Transition = 1f ; public float walkSpeed = 1f ; public float runSpeed = 1f ; public float jumpForce = 2f ; public float moveSpeedForJump ; public AudioClip [ ] footStepAudioClips ;
给跳跃进度10%~60%之前添加位移旋转逻辑,类似移动控制,并由配置量控制位移速度。
    
    
public override void Update ( ) { //第一次执行Update时,也许当前动画还不是Jump //确定当前是播放Jump动画 AnimatorStateInfo stateInfo = player . PlayerModel . Animator . GetCurrentAnimatorStateInfo ( 0 ) ; if ( stateInfo . IsName ( "Jump" ) ) { //获取动画的进度 float animationTime = stateInfo . normalizedTime ; if ( animationTime > 0.1f && animationTime < 0.6f ) { //处理空中位移 float h = Input . GetAxis ( "Horizontal" ) ; float v = Input . GetAxis ( "Vertical" ) ; Vector3 input = new Vector3 ( h , 0 , v ) ; if ( h != 0 || v != 0 ) { //处理旋转 //获取相机的旋转值y float y = Camera . main . transform . rotation . eulerAngles . y ; //让四元数和向量相乘,表示这个向量按照这个四元数所表达的角度进行旋转后得到的向量 Vector3 targetDir = Quaternion . Euler ( 0 , y , 0 ) * input ; //Slerp插值 player . PlayerModel . transform . rotation = Quaternion . Slerp ( player . PlayerModel . transform . rotation , Quaternion . LookRotation ( targetDir ) , Time . deltaTime * player . rotateSpeed ) ; } Vector3 dir = Camera . main . transform . TransformDirection ( input ) ; //Vector3 dir2 = Quaternion.Euler(0, Camera.main.transform.rotation.eulerAngles.y, 0) * new Vector3(h, 0, v); //player.CharacterController.Move(); player . CharacterController . Move ( player . moveSpeedForJump * Time . deltaTime * dir ) ; } else if ( animationTime >= 0.9f ) { player . ChangeState ( PlayerState . Idle ) ; return ; } } }
最终效果如下,实现跳跃,位移以及空中转向。
Logo

分享前沿Unity技术干货和开发经验,精彩的Unity活动和社区相关信息

更多推荐