You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity中如何将Character Controller转为Rigidbody移动并复用现有脚本?

3D横版平台角色踩移动平台不跟随问题:CharacterController转Rigidbody适配方案

问题背景

我正在制作一款3D横版平台游戏,角色踩在移动平台上时无法随平台一同移动。打算将Character Controller替换为Rigidbody解决该问题,需要把现有Character Controller脚本适配到Rigidbody上,原代码如下:

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

public class PlayerController : MonoBehaviour
{
    public CharacterController controller;
    private Vector3 direction;
    public float speed = 8;

    public float jumpForce = 30;
    public float gravity = -20;
    public Transform groundCheck;
    public LayerMask groundLayer;

    public bool ableToMakeADoubleJump = true;

    public Animator animator;
    public Transform model;

    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        if (PlayerManager.gameOver)
        {
            //play death animation
            animator.SetTrigger("die");

            //disable the script    
            this.enabled = false;
        }

        float hInput = Input.GetAxis("Horizontal");
        direction.x = hInput * speed;

        animator.SetFloat("speed", Mathf.Abs(hInput));
        bool isGrounded = Physics.CheckSphere(groundCheck.position, 0.15f, groundLayer);
        animator.SetBool("isGrounded", isGrounded);
        if (isGrounded)
        {
            //Jump Codes
            ableToMakeADoubleJump = true;
            if (Input.GetButtonDown("Jump"))
            {
                Jump();
            }
        }
        else
        {
            direction.y += gravity * Time.deltaTime;
            if (ableToMakeADoubleJump & Input.GetButtonDown("Jump"))
            {
                DoubleJump();
            }
        }
        if (hInput != 0)
        { 
            Quaternion newRoattion = Quaternion.LookRotation(new Vector3(hInput, 0, 0));
            model.rotation = newRoattion;
        } 

        //Move the player using the character controller
        controller.Move(direction * Time.deltaTime);
    }

    private void DoubleJump()
    {
        //Double Jump Codes
        animator.SetTrigger("doubleJump");
        direction.y = jumpForce;
        ableToMakeADoubleJump = false;
    }
    private void Jump()
    {
        direction.y = jumpForce;
    }
}

适配后的Rigidbody版本代码

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

public class PlayerController : MonoBehaviour
{
    private Rigidbody rb;
    private float horizontalInput;
    public float speed = 8;

    public float jumpForce = 30;
    public float gravity = -20;
    public Transform groundCheck;
    public LayerMask groundLayer;

    public bool ableToMakeADoubleJump = true;

    public Animator animator;
    public Transform model;

    void Start()
    {
        // 获取Rigidbody组件并初始化设置
        rb = GetComponent<Rigidbody>();
        rb.useGravity = false; // 关闭内置重力,用自定义逻辑模拟
        rb.freezeRotation = true; // 锁定旋转,防止角色物理倾倒
    }

    void Update()
    {
        if (PlayerManager.gameOver)
        {
            animator.SetTrigger("die");
            this.enabled = false;
            return;
        }

        horizontalInput = Input.GetAxis("Horizontal");
        animator.SetFloat("speed", Mathf.Abs(horizontalInput));

        bool isGrounded = Physics.CheckSphere(groundCheck.position, 0.15f, groundLayer);
        animator.SetBool("isGrounded", isGrounded);

        // 输入响应逻辑保留在Update,保证操作及时反馈
        if (isGrounded)
        {
            ableToMakeADoubleJump = true;
            if (Input.GetButtonDown("Jump"))
            {
                Jump();
            }
        }
        else
        {
            if (ableToMakeADoubleJump && Input.GetButtonDown("Jump"))
            {
                DoubleJump();
            }
        }

        // 角色转向逻辑
        if (horizontalInput != 0)
        { 
            Quaternion newRotation = Quaternion.LookRotation(new Vector3(horizontalInput, 0, 0));
            model.rotation = newRotation;
        } 
    }

    // 物理相关逻辑移到FixedUpdate,保证物理计算稳定性
    void FixedUpdate()
    {
        bool isGrounded = Physics.CheckSphere(groundCheck.position, 0.15f, groundLayer);

        // 处理水平移动
        Vector3 currentVelocity = rb.velocity;
        currentVelocity.x = horizontalInput * speed;

        // 手动模拟重力
        if (!isGrounded)
        {
            currentVelocity.y += gravity * Time.fixedDeltaTime;
        }
        else
        {
            // 地面状态下保持轻微向下的速度,避免角色浮空或陷入地面
            currentVelocity.y = -0.5f;
        }

        rb.velocity = currentVelocity;
    }

    private void DoubleJump()
    {
        animator.SetTrigger("doubleJump");
        rb.velocity = new Vector3(rb.velocity.x, jumpForce, rb.velocity.z);
        ableToMakeADoubleJump = false;
    }

    private void Jump()
    {
        rb.velocity = new Vector3(rb.velocity.x, jumpForce, rb.velocity.z);
    }
}

关键改动说明

  • 组件替换:移除CharacterController,给角色添加Rigidbody组件,关闭内置重力并锁定旋转,避免物理行为异常
  • 逻辑拆分:输入检测和动画控制保留在Update,物理移动逻辑移到FixedUpdate,符合Unity物理更新的最佳实践
  • 移动控制:直接修改Rigidbody的velocity属性控制水平移动,替代原controller.Move()方法
  • 重力与跳跃:手动模拟重力叠加,跳跃时直接设置y轴速度,保持原有的跳跃和二段跳手感
  • 平台跟随:只要移动平台设置了Rigidbody并设为Kinematic(或通过MovePosition移动),Rigidbody角色会自动和平台产生物理交互,实现跟随效果

内容的提问来源于stack exchange,提问作者Lightning21Cheetah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 23:01:23