乐趣区

关于unity:黑魂复刻游戏的玩家控制器降落落地检测Unity随手记

明天实现的内容:
退出起飞动画
起飞产生在跳跃之后,所以网络游戏角色起飞动画要紧接着跳跃动画播放,动画机如下。

这两条 Transition 都 has exit time,并且 jump 到 fall 的优先级高于 jump 到 ground,因为目前为止这两个转换都没有条件。

在图示地位调整优先级。

落地检测的实现及相干动画使用
要实现落地检测,须要应用 Physics.Overlap 里的货色,应用 Physics.Overlap 能够找到某个形态范畴内有重合的所有碰撞体。比方咱们要用到的 Physics.OverlapCapsule 就是在一个给定的胶囊体内失去所有与胶囊体有重合的特定 layer 的碰撞体,Overlap 只能失去有哪些碰撞体重合,而不晓得其它信息(先后,远近等等)。

咱们新建落地检测器脚本 OnGroundSensor,挂载到 PlayerController 游戏对象的子物体 sensor 下,sensor 对象将专门因为各种检测器的挂载。

OnGroundSensor 代码如下。通过 SendMessage 来通知 PlayerController 以后是否正在高空。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// 落地检测器
public class OnGroundSensor : MonoBehaviour
{
    // 用于援用 PlayerController 游戏对象上的 CapsuleCollider
    public CapsuleCollider capCol;

    // 用于绘制胶囊检测器的两个点
    private Vector3 point1;
    private Vector3 point2;
    // 用于绘制胶囊检测器的半径
    private float radius;


    void Awake()
    {radius = capCol.radius;}

    void FixedUpdate()
    {
        // 更新检测器的地位
        point1 = transform.position + transform.up * radius;
        point2 = transform.position + transform.up * (capCol.height - radius);
        // 检测高空碰撞
        Collider[] outputCols = 
            Physics.OverlapCapsule(point1, point2, radius, LayerMask.GetMask("Ground"));
        // 判断是否撞到高空 并向父物体发送对应音讯
        if(outputCols.Length != 0)
        {
            // 在高空
            SendMessageUpwards("IsGround");
        }
        else
        {
            // 不在高空
            SendMessageUpwards("IsNotGround");
        }
    }
}

接下来要做的就是,在 PlayerController 中实现音讯接管。

// 在高空时执行的办法 通过 OnGroundSensor 中的 SendMessage 调用
    public void IsGround()
    {m_anim.SetBool("isGround", true);
    }

    // 不在高空时执行的办法 通过 OnGroundSensor 中的 SendMessage 调用
    public void IsNotGround()
    {m_anim.SetBool("isGround", false);
    }

在动画机中增加新参数 isGround,用于 PlayerController 进行管制。

好的,当初调回先前的 jump 转换优先级,将 jump 到 ground 和 fall 到 ground 的转换条件设置为 isGround 为 true。


到目前为止,落地检测的实现及相干动画使用根本实现。

落地检测器优化
倡议改小检测器的半径以及略微将检测器向下挪动一点。来失去更好的检测后果。

    // 检测器偏移量
    public float offset = 0.1f;

    void Awake()
    {m_radius = capCol.radius * 0.6f;}

    void FixedUpdate()
    {
        // 更新检测器的地位
        m_point1 = transform.position + transform.up * (m_radius - offset);
        m_point2 = transform.position + transform.up * (capCol.height - m_radius - offset);
        
        // ...
    }

失足掉落
因为咱们的掉落动画只有在跳跃的前提下能力触发,所以特此退出失足掉落的设置。这样一来,只有来到高空就会播放,而不是来到高空仍旧和在高空没有两样(在没有跳起来来到高空的状况下)。是的,咱们在没有起跳的状况下来到高空和在高空没有区别,仍然能够失常操作。
首先是动画机的设置,间接拉一条 transition 从 ground 到 fall 就行,条件为 isGround 为 false。

接下来,在掉落时要和跳跃一样锁死操作。当初就当一次笨蛋,在进入 fall 状态时发送音讯给 PlayerController(更好的办法是在来到 ground 时发送音讯,这样还能够省掉进入跳跃时发送音讯这个操作)。

    // 进入掉落时执行的办法 通过 PlayerController 动画机中的 fall 节点上挂载的 FSMOnEnter 中的 SendMessage 调用
    public void OnFallEnter()
    {
        // 敞开输出并且锁定立体挪动
        DisableInput_LockPlanar();}

    // 敞开输出并且锁定立体挪动
    private void DisableInput_LockPlanar()
    {
        // 敞开输出模块
        pi.inputEnabled = false;
        // 锁死平台挪动计算
        m_lockPlanar = true;
    }

动画的优化及改良
除了 jump 到 fall,其它所有的 transition 都不要勾选 has exit time,这样能带来更晦涩的动画成果。

退出移动版