加载中...

【Unity系列】角色控制器该用Rigidbody还是CharacterController?

  • 2025-09-26
  • 游戏开发
  • unity教程 游戏开发
  • --

我一张开眼,发现自己正站在一片奇怪的地方。脚下不是草地,也不是石板,而是一张张灰白色的网格,像是开发者随手搭出来的地面。四周空荡荡,空气里弥漫着“半成品”的气息。没错,这是一个刚刚开工的游戏世界。

我试着抬起脚,却纹丝不动。原来,我还没有获得“移动”的能力。作为游戏里的角色,我的命运取决于开发者的选择。他要给我装配什么组件,我就会以什么方式存在。

穿上CharacterController

第一次,我被赋予了一副新的外壳——CharacterController。

瞬间,我能动了!

我踩在地上,走得干干净净,玩家按方向键,我就精准迈步。前方有坡道?我能顺畅地爬上去。想要跳?我也能干脆利落地跃起。其实这背后,是开发者调用了这样的代码:

public class PlayerMove : MonoBehaviour
{
    public CharacterController controller;
    public float speed = 6f;
    public float gravity = 0f;
    public float jumpHeight = 1.5f;
    private Vector3 velocity;
    // Start is called before the first frame update
    void Start()
    {
        // 自动获取CharacterController组件
        if (controller == null)
        {
            controller = GetComponent<CharacterController>();
            if (controller == null)
            {
                // 如果没有CharacterController组件,自动添加一个
                controller = gameObject.AddComponent<CharacterController>();
                Debug.Log("已自动添加CharacterController组件到 " + gameObject.name);
            }
        }
    }
    // Update is called once per frame
    void Update()
    {
        // 确保controller不为空
        if (controller == null) return;
        float x = Input.GetAxis("Horizontal");
        float z = Input.GetAxis("Vertical");
        Vector3 move = transform.right * x + transform.forward * z;
        controller.Move(move * speed * Time.deltaTime);
        if (controller.isGrounded && velocity.y < 0)
            velocity.y = -2f;
        if (Input.GetButtonDown("Jump") && controller.isGrounded)
            velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
        velocity.y += gravity * Time.deltaTime;
        controller.Move(velocity * Time.deltaTime);
    }
}

在玩家眼里,我只是稳稳前行,但其实是 controller.Move() 在推动我的身体。

我的特性很明显:

  • 稳定,不受外界物理影响。
  • 不会被推开,不会乱飞。
  • 碰撞检测可靠,专为角色移动设计。

但我也有遗憾:

  • 我没有质量。子弹打中我?我连抖都不抖。
  • 我不会被撞翻,也不会被炸飞。我更像一个精密的木偶,被牢牢掌控,却少了一点真实感。

注入Rigidbody

后来,开发者拆掉了我的控制器,换上了Rigidbody。

那一刻,我突然感受到了重量!脚下的大地在拉扯我,仿佛提醒我:你不再是虚假的影子,而是物理世界的居民。这时我的代码长这样:

public class PlayerPhysics : MonoBehaviour{
    public Rigidbody rb;
    public float moveForce = 5f; 
    public float jumpForce = 5f;
    void Update()    {
        if (Input.GetKey(KeyCode.W))
            rb.AddForce(Vector3.forward * moveForce);
        if (Input.GetKey(KeyCode.A))
            rb.AddForce(Vector3.left * moveForce);
        if (Input.GetKey(KeyCode.D))
            rb.AddForce(Vector3.right * moveForce);
        if (Input.GetKey(KeyCode.S))
            rb.AddForce(Vector3.back * moveForce);        
        if (Input.GetKeyDown(KeyCode.Space))
            rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
    }}

这里,开发者不再直接摆弄我的位置,而是用 AddForce() 给我一个推力,让我慢慢加速。

我的特性:

  • 有质量,有重力,会被撞飞。
  • 能与物理世界自然互动:被推、被压、滚落斜坡。
  • 更加真实,适合需要物理表现的对象。

我的缺点:

  • 不够精确,控制起来容易“发飘”。
  • 稍不注意,我就会卡住、抖动,甚至乱飞。我终于成了物理世界的一部分,但也因此变得难以驯服。

两种控制器的对照

现在,我能看清楚这两种控制器的差别了:

CharacterController:我是一个稳定的英雄,步伐干净利落,但缺少重量,缺乏与世界的互动。

Rigidbody:我是一个真实的存在,能体验重力与碰撞,但我的动作往往不够精确,难以完全掌控。

我在想,能不能两全其美:平时走路时使用 CharacterController 的稳定,遇到爆炸时切换到 Rigidbody,让我飞一回。许多游戏里,开发者确实会这么做,把两者混合使用,让我既稳重又灵活。

我的命运,由你决定你可以让我成为始终稳定的英雄,用 CharacterController 把我牢牢掌握。

你也可以让我成为活生生的物理小子,用 Rigidbody 让我与世界真实碰撞。最终,我的命运掌握在你的手中,开发者。你想让我走哪条路?

Maple
Maple
© 2025 by Maplezz 本文基于 CC BY-NC-SA 4.0 许可 CC 协议 必须注明创作者 仅允许将作品用于非商业用途 改编作品必须遵循相同条款进行共享 最后更新:2025/9/27