如何设置Unity第一人称角色控制器基于Rigidbody Velocity的移动功能
第一人称Rigidbody角色控制器修复方案
原代码核心问题
- 物理属性(Rigidbody.velocity)赋值放在
Update中执行,和Unity物理更新周期不同步,导致移动卡顿、表现不稳定 - 每帧重复调用
GameObject.Find、GetComponent接口,无对象缓存,性能损耗极高 - 胶囊体朝向逻辑错误:调用
LookAt对准相机位置,导致胶囊体前向完全和预期相反,移动方向匹配错误 - 无输入时未清空velocity,角色松开按键后会继续滑行
- 输入判断逻辑重复冗余,多处重复计算输入向量的模长,可读性差
前置Inspector设置
首先需要给玩家胶囊体的Rigidbody组件勾选「Freeze Rotation」下的X、Y、Z三个选项,避免物理碰撞导致胶囊体倾倒。
修复后完整代码
using UnityEngine; public class characterController : MonoBehaviour { [Header("移动参数")] public float moveSpeed = 5f; public Vector3 cameraOffset = new Vector3(0, 1.8f, 0); // 相机高度偏移,适配正常第一人称视角高度 [Header("状态标记")] public bool reteleporing = false; public bool walking = false; // 缓存引用,避免每帧查找 private Rigidbody _rb; private Camera _mainCam; private Transform _spawnPos; private Vector2 _moveInput; void Start () { // 一次性缓存所有需要的引用 _rb = GetComponent<Rigidbody>(); _mainCam = Camera.main; _spawnPos = GameObject.Find("spawnpos").transform; } // 输入检测、逻辑更新放Update void Update (){ // 收集输入 _moveInput = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical")); walking = _moveInput.magnitude > 0.01f; // 掉落传送逻辑 if (transform.position.y < -100) { reteleporing = true; } if (reteleporing) { transform.position = _spawnPos.position; if (transform.position.y > 2.4f) { reteleporing = false; } } // 相机位置同步 _mainCam.transform.position = transform.position + cameraOffset; } // 物理相关操作统一放FixedUpdate private void FixedUpdate() { if (reteleporing) return; // 胶囊体Y轴旋转和相机保持一致,保证前向匹配视角方向 transform.rotation = Quaternion.Euler(0, _mainCam.transform.eulerAngles.y, 0); if (walking) { // 计算水平方向的移动向量,跟随相机视角 Vector3 camForward = Vector3.Scale(_mainCam.transform.forward, new Vector3(1, 0, 1)).normalized; Vector3 moveDir = camForward * _moveInput.y + _mainCam.transform.right * _moveInput.x; // 直接赋值velocity,保留Y轴重力 _rb.velocity = new Vector3(moveDir.x * moveSpeed, _rb.velocity.y, moveDir.z * moveSpeed); } else { // 无输入时清空水平方向速度,避免滑行 _rb.velocity = new Vector3(0, _rb.velocity.y, 0); } } }
关键修改说明
- 所有Rigidbody相关操作移至
FixedUpdate执行,匹配Unity物理更新周期,移动稳定性大幅提升 - 新增引用缓存逻辑,所有频繁调用的对象仅在Start中查找一次,性能优化明显
- 修正朝向逻辑:胶囊体Y轴旋转直接同步相机的Y轴旋转,保证移动方向完全匹配玩家视角
- 保留velocity直接赋值的实现方式,Y轴速度保留原有重力值,无需额外处理重力逻辑
- 新增无输入时水平速度归零逻辑,解决松开按键后角色滑行的问题
- 优化重复代码,输入仅每帧收集一次,状态判断逻辑简化
内容的提问来源于stack exchange,提问作者user15177920
相关产品推荐
相关产品推荐

