美文网首页
从零开始的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