找回密码
 立即注册
查看: 399|回复: 0

[笔记] unity游戏开发-行走

[复制链接]
发表于 2021-12-8 07:05 | 显示全部楼层 |阅读模式
行走是rpg游戏中十分基础的功能,但是小白在处理的时候却又很容易犯错误,这一节,我将梳理一些行走代码的细节,希望遇到问题的小伙伴可以有所收获。
<hr/> 在unity中,控制人物移动的大体上来说,有如下三种方法:

  • CharacterController组件移动物体
  • 通过Transform组件移动物体
  • 通过Rigibody组件移动物体
<hr/>CharacterController组件

这个组件需要注意的问题
       1.重力需要自己模拟,也就是y轴偏移需要自己计算,当然如果在平面上行走的话可以完全忽略这个值,直接设置为0即可
       2.处理纵坐标需要考虑x,z轴有没有偏移,如果没有偏移则不要计算,否则你会遇到脸朝下的尴尬局面,别问我怎么知道的,哈哈哈哈哈哈哈哈哈哈
组件截图如下:


组件的参数介绍如下:
    Slope Limit:坡度限制。该参数用于设置自所控制的游戏对象只能爬上角度小于或等于该参数值的斜坡。
    Step Offset:台阶高度。该参数用于设置所控制的游戏对象可以迈上的最高台阶的高度。
    Skin Width:皮肤厚度。该参数决定了两个碰撞体可以相互渗入的深度,较大的参数值会产生抖动的现象,较小的参数值会导致所控制的游戏对象被卡住,较为合理的设置是该参数值为Radius值的10%。
    Min Move Distance:最小移动距离。如果所控制的游戏对象的移动距离小于该值,则游戏对象将不会移动,这样可避免抖动,大多数情况下该值设为0。
    Center:中心。该参数决定了胶囊碰撞体所控制的游戏对象的相对位置,并不影响所控制的游戏对象的中心坐标。该坐标需要与对象实体下方对齐,否则会出现玩家飘在空中的情况
    Radius:半径。该参数用于设置胶囊碰撞体的半径。
    Height:高度。该参数用于设置胶囊碰撞体的高度。   简单实现的代码如下:
   // 计算在x,z轴上位置的偏移,相当于获取一个单位距离
    float h = Input.GetAxis("Horizontal");
    float v = Input.GetAxis("Vertical");

    // 模拟重力,计算y轴的偏移
    float grivaty = -9.8f;
    float moveY = grivaty * Time.deltaTime;
   
    // 每一次移动的时候,看向终点的位置,假装是一个正常的人物。。。
    transform.LookAt(new Vector3(h, 0, v) + transform.position);
   
    // 控制玩家的移动,
    m_Charactor.Move(new Vector3(h, moveY, v) * forwardspeed * Time.deltaTime);
    /*
    SimpleMove:正如它的名字一样,简单移动,不需要过多的计算,只需要传入速度向量即可,重力会自动计算
    */
<hr/>Transform组件

        这个组件其实就是物体位置改变的根本原因,这里我们强调直接调用这个组件的函数实现物体位置的变化
函数介绍:
    Translate (translation : Vector3, relativeTo : Space = Space.Self)
: void
    物体以relativeTo为参照系,沿着translation运动
    这里需要注意一个事情,参照系的选取一定要弄清楚,一般采用世界坐标系Space.World,函数默认
以控制的玩家对象为坐标系

代码如下:
    void FixedUpdate ()
    {
        // 存储坐标系的偏移
        float h = Input.GetAxis("Horizontal");
        float v = Input.GetAxis("Vertical");

        // 移动玩家
        Move (h, v);
    }

    void Move (float h, float v)
    {
        this.transform.Translate (new Vector3 (h, 0, v) * speed * Time.deltaTime, Space.World);
    }
<hr/>Rigibody组件

<hr/>       从我几个简单的demo来看,个人感觉,rigibody的用户体验更好,而且Constraints这个选项对于做一些跟随鼠标旋转什么的操作更加的方便
组件截图如下:


参数详情:
Mass 质量,单位为Kg,建议不要让对象之间的质量差达到100倍以上
Drag 空气阻力,为0表示没有阻力,infinity表示立即停止移动
Angular Drag 扭力的阻力,数值意义同上
Use Gravity 是否受重力影响
Is Kinematic 是否为Kinematic刚体,如果启用该参数,则对象不会被物理所控制,只能通过直接设置
位置、旋转和缩放来操作它,一般用来实现移动平台,或者带有HingeJoint的动画刚体
Interpolate 如果你的刚体运动时有抖动,尝试一下修改这个参数,None表示没有插值,Interpolate
表示根据上一帧的位置来做平滑插值,Extrapolate表示根据预测的下一桢的位置来做平滑插值
Freeze Rotation 如果选中了该选项,那么刚体将不会因为外力或者扭力而发生旋转,你只能通过脚本
的旋转函数来进行操作
Collision Detection 碰撞检测算法,用于防止刚体因快速移动而穿过其他对象
Constraints 刚体运动的约束,包括位置约束和旋转约束,勾选表示在该坐标上不允许进行此类操作代码如下:
    public float speed = 6f;            // 速度
    Vector3 movement;                   // 存储玩家移动的方向的向量
    Rigidbody playerRigidbody;          // 玩家的 rigidbody.

    void Awake ()
    {
        // 绑定刚体
        playerRigidbody = GetComponent <Rigidbody> ();
    }

    void FixedUpdate ()
    {
        // 存储坐标系的偏移
        float h = Input.GetAxis("Horizontal");
        float v = Input.GetAxis("Vertical");

        // 移动玩家
        Move (h, v);
    }

    void Move (float h, float v)
    {
        // 设置方向向量
        movement.Set (h, 0f, v);
            
        // 计算每秒的偏移量
        movement = movement.normalized * speed * Time.deltaTime;

        // 移动玩家
        playerRigidbody.MovePosition (transform.position + movement);
    }<hr/>    每一个组件下还有一些其他的函数,想要了解的可以自行查找资料学习。
    开发中具体选择哪一种组件进行操作,视情况而定,其实我感觉都可以试试,哈哈哈哈哈哈哈哈哈,CharacterControl更适合一些复杂的场景,Rigibody更适合处理碰撞,各有各的优势吧,其他的我也没有具体深入了解,嘻嘻。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-5-10 14:31 , Processed in 0.342751 second(s), 27 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表