美文网首页
从零开始的RPG制作(3.3跳跃-落地-空中姿态-修复多余跳跃动

从零开始的RPG制作(3.3跳跃-落地-空中姿态-修复多余跳跃动

作者: 小蜻蜓队长 | 来源:发表于2019-04-28 17:16 被阅读0次

    上一篇文章中我们我们提到了一个关于空中姿态的问题,我们在本章节完善它。
    首先我们不妨思考一下,什么时候切换成空中姿态,什么时候切回来,是跳起的时候吗?
    这个我们很容易就能想到,不可能只有跳起的时候拥有空中姿态,人物双脚离地就应该切换成空中姿态,那样势必是需要一个关于人物是否双脚离地的判断的。

    这里,我们使用了一个unity提供的API,Physics.OverlapCapsule(双交球)这个API可以帮助我们检测小姐姐落地与否。
    我们首先将地图中看到的cube和plane设置一个层级


    地面或者站立平台

    接着开始写我们的PlayerTestView的码子

        float radius;
        public void init() {
            rig = GetComponent<Rigidbody>();
            pad = new PlayerAnimaId();
            player = transform;
            playerAnimatorInit();
            capsuleCollider = GetComponent<CapsuleCollider>();
            radius = capsuleCollider.radius - 0.05f;//获取player身上碰撞器的半径,稍微缩短半径
        }
        public void colliderTesting() {//判断是否接触地面
            Vector3 point0 = player.position + (player.up * (radius - 0.1f));//将下方的相交球往下拉一点,使其在CapsuleCollider的下方。
            Vector3 point1 = player.position + player.up * capsuleCollider.height - player.up * radius;
            Collider[] groundCollider = Physics.OverlapCapsule(point0, point1, radius, LayerMask.GetMask("IsGround")); //如果接触地面
            if (groundCollider.Length > 0) {
                isGround(true);
            } else {
                moveDirection.y = 0;
                isGround(false);
            }
        }
    
        public void isGround(bool c) {
        //这里面应该写点什么?
       }
    

    接着在PlayerTestMediator的码子里的fixupdate添加上我们的检测。

        public override void OnRegister() {//绑定成功之后会调用这个API
            Debug.Log("OnRegister");
            playerView.init();
            UpdateManges.add_playerEventList_(keyController);
            UpdateManges.add_playerEventList_(playerAction);     
      UpdateManges.add_playerEventList_Fix(accurateDetection);//新添加的函数,需要精确检测的都应该放在这里,比如落地检测,实时重力之类。
        }
    
        public override void OnRemove() {//接触绑定之后调用这个API
            Debug.Log("OnRemove");
            UpdateManges.sub_playerEventList_(keyController);
            UpdateManges.sub_playerEventList_(playerAction);
            UpdateManges.sub_playerEventList_(accurateDetection);
        }
    
        void accurateDetection() {
            playerView.colliderTesting();
       }
    

    处理完这这里,我们就要回过头去想PlayerTestView 中的isGround应该写点什么。就现在而言那就是空中的姿态,那我们就去这里找一个动作把,经过一番查找,我们找到了一个叫做,Fall的动作。如图。

    fall
    我们把动作切换成humanoid,然后放入道我们的动画控制器内部。
    接着我们思考一下,那些状态可以切换道这里。经过一番思考。
    跳->可以
    走->可以
    跑->可以
    静止->可以。
    于是我们就这样做。
    配置1
    配置2 配置3

    做完着这些配置,我们有需要去写一点代码实现了。
    PlayerTestView_Anim:

        struct PlayerAnimaId {
            public int Idle;//禁止状态行为切换控制。
            public int baseAniam;
            public int jump;
            public int isGround;//新增
        };
    
        private void playerAnimatorInit() {
            animator = GetComponent<Animator>();
            pad.baseAniam = Animator.StringToHash("walk");
            pad.jump = Animator.StringToHash("Jump");
            pad.isGround = Animator.StringToHash("IsGround");//新增
            pad.Idle = Animator.StringToHash("Idle");
        }
      
        private void animator_PlayaisGround(bool isGround) {
            animator.SetBool(pad.isGround, isGround);
        }
    

    PlayerTestView:

        bool lockOperation ;//用于锁死玩家操作。
        public void isGround(bool c) {
            lockOperation = !c;
            animator_PlayaisGround(c);
        }
    
        public void baseWalkRun(float right, float forward, bool run) {
            if (LockOperation)
                return;
            animaBlendAction(right, forward, run);
        }
    
        public void playerMove() {
            if (!lockOperation) {//如果出于半空中,玩家所控制的位移信息全部跳过,不做任何处理。
              rig.velocity = new Vector3(moveDirection.x, moveDirection.y+ rig.velocity.y, moveDirection.z);
            }
        }
    

    在PlayerTestMediator进行更改。

        void playerAction() {//加入update不断跟新
            playerView.baseWalkRun(right, up, run);
            playerView.startJump(jump);
            playerView.playerMove();
        }
    

    一切做完,我们来看看效果。


    效果

    看着还行,但是这里有个问题,如果小姐姐在空中的时候我们再一次按一下跳跃,小姐姐落地之后还会跳一次,这是为什么?
    我们的逻辑应该是正确的,这里就要提到一个unity动画机的一个信号冗余问题。我这里这么做。
    创建一个FSMClearSignals 脚本,让挂在jump这个跳跃动作上。

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class FSMClearSignals : StateMachineBehaviour {
    
        public string[] clearAtenter;
        public string[] clearAtexit;
    
        public override void OnStateEnter(Animator animator, AnimatorStateInfo animatorStateInfo, int layerIndex) {
            foreach (var signal in clearAtenter) {
                animator.ResetTrigger(signal);//清除信号
            }
        }
    
        public override void OnStateExit(Animator animator, AnimatorStateInfo animatorStateInfo, int layerIndex) {
            foreach (var signal in clearAtexit) {
                animator.ResetTrigger(signal);//清除信号
            }
        }
    }
    
    配置
    做到这里,小姐姐终于有模有样了,但是在我们制作的时候,我们发现了一个问题,有些线条(比如Physics.OverlapCapsule 无法显示)。所有我们下一节将制作一个辅助线控制器,用于那些我们看不见的线条。
    上一节
    下一节

    相关文章

      网友评论

          本文标题:从零开始的RPG制作(3.3跳跃-落地-空中姿态-修复多余跳跃动

          本文链接:https://www.haomeiwen.com/subject/zfqjnqtx.html