[RPG战斗系统] 10&14.角色急停

提供角色由奔跑到待机状态的急停动画过渡。可以在单独给出来一个急停状态进行过渡,但没必要,急停状态只包含一个动画,将移动状态逻辑上细分为两个子状态即可,子状态没有Exit逻辑,通过属性的get方法实现状态进入播放动画,Update正常检测切换状态

    private enum MoveChildState
    {
        Move,
        Stop
    }
    private MoveChildState moveState;
    private MoveChildState MoveState
    {
        get { return moveState; }
        set
        {
            moveState = value;
            //状态进入
            switch (value)
            {
                case MoveChildState.Move:
                    player.PlayAnimation("Move");
                    break;
                case MoveChildState.Stop:
                    player.PlayAnimation("RunStop");
                    break;
            }

        }
    }

通过MoveState属性Set值时播放对应的动画,相当于子状态的Enter,下一步,考虑何时更新MoveState值。

    public override void Enter()
    {
        MoveState = MoveChildState.Move;
        player.PlayerModel.SetRootMotionAction(OnRootMotion);
    }

在进入Move状态时,默认是奔跑的动画。

    public override void Update()
    {

        //检测玩家跳跃
        if (Input.GetKeyDown(KeyCode.Space))
        {
            player.ChangeState(PlayerState.Jump);
            return;
        }
        switch(moveState)
        {
            case MoveChildState.Move:
                MoveOnUpdate();
                break;
            case MoveChildState.Stop:
                StopOnUpdate();
                break;

        }
    }

在状态更新的每一帧,判断当前状态,如果是Move状态,那需要检测输入和玩家走跑的过渡进度来决定是否需要进入Stop状态急停。

    void MoveOnUpdate()
    {
        // h和v用来做实际的移动位置参考
        float h = Input.GetAxis("Horizontal");
        float v = Input.GetAxis("Vertical");

        // rawH和rawV用来判断是否待机,急停
        float rawH = Input.GetAxisRaw("Horizontal");
        float rawV = Input.GetAxisRaw("Vertical");

        if(rawH == 0 && rawV == 0) //玩家松开按键
        {
            if(walk2RunTranstion > 0.4f)
            {
                //进入急停
                MoveState=MoveChildState.Stop;
                return;
            }
            //停止运动回到Idle
            player.ChangeState(PlayerState.Idle);
            return;
        }
        else
        {
            //走到跑的过渡
            if (Input.GetKey(KeyCode.LeftShift))
            {
                walk2RunTranstion = Mathf.Clamp(walk2RunTranstion + Time.deltaTime * player.walk2Transition, 0, 1);
            }
            else
            {
                walk2RunTranstion = Mathf.Clamp(walk2RunTranstion - Time.deltaTime * player.walk2Transition, 0, 1);
            }
            player.PlayerModel.Animator.SetFloat("Move", walk2RunTranstion);
            //影响动画播放速度,来影响rootmotion位移速度
            player.PlayerModel.Animator.speed = Mathf.Lerp(player.walkSpeed, player.runSpeed, walk2RunTranstion);

            //角色旋转
            Vector3 input = new Vector3(h, 0, v);
            //获取相机的旋转值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);
        }
    }

为了让急停能够及时反应,使用GetAxisRaw(-1/0/1)来无缓冲的监测玩家是否停止移动输入,如果玩家停止了移动,且跑步动画到走路动画的过渡量>40%,那有必要进行急停,否则直接回到Idle状态(注意判断里有return,所以省去了else)。注意,一旦状态切换到Stop,则OnMoveUpdate就不再执行,子状态的Update是有条件的执行的,动画只会播放一次。

alt

    private void StopOnUpdate()
    {
        if(CheckAnimatorStateName("RunStop",out float animationTime))
        {
            if (animationTime >= 1) player.ChangeState(PlayerState.Idle);
        }
    }

如果当前是急停状态,则播放完急停动画切换到Idle状态,为了方面获取当前动画的播放进度,在PlayerStateBase封装个功能方法检查并获取当前指定名称动画的播放进度。

    protected virtual bool CheckAnimatorStateName(string stateName,out float normalizedTime)
    {
        AnimatorStateInfo info = player.PlayerModel.Animator.GetCurrentAnimatorStateInfo(0);
        normalizedTime = info.normalizedTime;
        return info.IsName(stateName);
    }

alt

最后为急停动画帧添加对应的动画事件。

最终效果如,角色奔跑时送卡按键,则急停,再待机。

alt

Unity战斗系统 文章被收录于专栏

Unity战斗系统实现笔记

全部评论

相关推荐

2024-11-13 19:59
中南大学 自动化
Noob1024:一笔传三代,人走笔还在
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务