前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Unity Rigidbody实现爬坡功能

Unity Rigidbody实现爬坡功能

作者头像
CoderZ
发布2022-12-26 21:02:52
8550
发布2022-12-26 21:02:52
举报

🎈 简介

人物爬坡

人物移动功能的实现或许用到Character Controller组件或许用到Rigidbody刚体组件,前者可以直接实现在某些高地不平的地面上移动,而后者想要在具有一定角度的坡面上进行移动则需要通过代码实现。本篇内容介绍如何通过Rigidbody刚体组件实现人物爬坡功能;

🎈 实现原理

Move Direction

实现人物爬坡功能前,通过获取用户HorizontalVertical轴输入形成了一个移动方向Move Direction,该方向平行于地面,驱动Rigidbody沿该方向移动,代码如下:

代码语言:javascript
复制
//根据输入获取方向
protected Vector3 GetInputDirection()
{
    //前方
    Vector3 forward = Vector3.ProjectOnPlane(mainCamera.forward, Vector3.up).normalized;
    //右方
    Vector3 right = Vector3.ProjectOnPlane(mainCamera.right, Vector3.up).normalized;
    //输入值
    input = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
    //返回值
    return input.x * right + input.y * forward;
}
代码语言:javascript
复制
protected override void Update()
{
    base.Update();
    //计算当前的移动速度
    speed = walkThreshold + ((sprintThreshold - walkThreshold) * sprintFactor);
    //获取方向
    Vector3 direction = GetInputDirection();
    //驱动刚体
    rb.velocity += direction * speed * Time.deltaTime;
    //目标旋转值
    Quaternion targetRot = Quaternion.Euler(new Vector3(0f, Vector3.SignedAngle(transform.forward, direction, Vector3.up), 0f)) * transform.rotation;
    //插值方式进行旋转
    transform.rotation = Quaternion.Lerp(transform.rotation, targetRot, Time.deltaTime * rotateSpeed);
}

如下图所示,我们只需要在上述基础上,从脚底向下发射一条射线(红色线),射线检测碰撞的法线(黄色线)会与向量Vector3.Up形成一个角度a,角度a与坡度b(绿色线与蓝色线夹角)相等,因此求得角度a的值便知坡面的坡度。

坡度

得知坡度后,只需要根据坡度调整Rigidbody刚体的移动方向Move Direction即可。

实现原理

🎈 实现代码

代码语言:javascript
复制
protected override void Update()
{
    base.Update();
    //计算当前的移动速度
    speed = walkThreshold + ((sprintThreshold - walkThreshold) * sprintFactor);
    //获取方向
    Vector3 direction = GetInputDirection();
    //判断是否在坡面上
    if (IsOnSlope(out Vector3 hitNormal))
    {
        direction = Vector3.ProjectOnPlane(direction, hitNormal).normalized;
    }
    //驱动刚体
    rb.velocity += direction * speed * Time.deltaTime;
    //目标旋转值
    Quaternion targetRot = Quaternion.Euler(new Vector3(0f, Vector3.SignedAngle(transform.forward, direction, Vector3.up), 0f)) * transform.rotation;
    //插值方式进行旋转
    transform.rotation = Quaternion.Lerp(transform.rotation, targetRot, Time.deltaTime * rotateSpeed);
}

//是否在斜坡上
private bool IsOnSlope(out Vector3 hitNormal)
{
    Ray ray = new Ray(transform.position + Vector3.up * .1f, Vector3.down);
    if (Physics.Raycast(ray, out RaycastHit slopeHit, 1f))
    {
        hitNormal = slopeHit.normal;
        float slopeAngle = Vector3.Angle(hitNormal, Vector3.up);
        if (slopeAngle < maxSlopeAngle)
        {
            return true;
        }
    }
    hitNormal = Vector3.zero;
    return false;
}

maxSlopeAngle用于限制人物可以爬坡的最大角度,当实际坡度大于该值时,人物不可以向上爬坡。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-10-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 当代野生程序猿 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 🎈 简介
  • 🎈 实现原理
  • 🎈 实现代码
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档