如何实现第三人称游戏中角色围绕摄像机环绕移动?
实现角色围绕摄像机的环绕移动效果
嘿,我完全懂你想要的那种环绕移动效果——就是按住左右方向键时,角色围着摄像机转圈的感觉对吧?看了你贴的代码,咱们来一步步调整,把这个效果做出来~
一、调整Movement脚本
你的现有代码里CalculateForward()是空的,这正是实现环绕效果的关键入口。我们要基于摄像机的Y轴旋转来构建环绕的参考方向,再重写左右输入时的移动逻辑:
public int speed = 10; public int rotationSpeed = 10; public CharacterController cc; Vector2 input; Vector3 moveDir; Vector3 lookDir; Vector3 forward; Transform camTransform; public Transform model; void Start () { cc = GetComponent<CharacterController>(); camTransform = Camera.main.transform; } void GetInput() { input.x = Input.GetAxisRaw("Horizontal"); input.y = Input.GetAxisRaw("Vertical"); } // 新增:计算基于摄像机Y轴的水平前向方向(忽略摄像机上下俯仰) void CalculateForward() { Vector3 camForward = camTransform.forward; camForward.y = 0; // 只保留水平方向的前向 forward = camForward.normalized; } void Move() { CalculateForward(); // 核心环绕逻辑:左右输入时,让角色绕摄像机Y轴旋转移动 if (input.x != 0) { // 计算单次帧的旋转角度 Quaternion frameRotation = Quaternion.Euler(0, input.x * rotationSpeed * Time.deltaTime, 0); // 获取角色相对于摄像机的水平位置 Vector3 relativeToCam = transform.position - camTransform.position; relativeToCam.y = 0; // 保持水平高度一致 // 旋转相对位置,得到新的角色位置 relativeToCam = frameRotation * relativeToCam; transform.position = camTransform.position + relativeToCam; // 如果同时有前后输入,保持向前/向后移动 if (input.y != 0) { cc.Move(forward * input.y * speed * Time.deltaTime); } } else { // 无左右输入时,保留原有的相对摄像机移动逻辑 moveDir.x = input.x; moveDir.z = input.y; if(moveDir.magnitude > 1) { moveDir.Normalize(); } Vector3 rotatedDir = camTransform.TransformDirection(moveDir); rotatedDir.y = 0; rotatedDir = rotatedDir.normalized * moveDir.magnitude; cc.Move(rotatedDir * speed * Time.deltaTime); } } void ApplyGravity() { // 补全重力逻辑(示例) if (!cc.isGrounded) { cc.Move(Vector3.down * 9.8f * Time.deltaTime); } } void FaceDir() { if (input.x != 0 || input.y != 0) { Vector3 targetDir; if (input.x != 0) { // 环绕时让角色朝向远离摄像机的方向(也可以改成朝向移动切线方向,按需调整) targetDir = (transform.position - camTransform.position).normalized; } else { // 前后移动时保持朝向摄像机前向 targetDir = forward * input.y; } targetDir.y = 0; if (targetDir != Vector3.zero) { transform.rotation = Quaternion.Slerp( transform.rotation, Quaternion.LookRotation(targetDir), Time.deltaTime * rotationSpeed ); } } } private void FixedUpdate() { GetInput(); ApplyGravity(); Move(); FaceDir(); }
二、优化Camera脚本
为了让环绕效果更稳定,相机需要避免跟随角色旋转时出现不必要的晃动,调整目标位置的计算逻辑:
[SerializeField] private float distanceAway; [SerializeField] private float distanceUp; [SerializeField] private float smooth; [SerializeField] private Transform follow; private Vector3 targetPosition; private void Start() { follow = GameObject.FindWithTag("Player").transform; } private void LateUpdate() { // 构建相机偏移:保持高度,水平偏移基于相机当前Y轴旋转 Vector3 heightOffset = follow.up * distanceUp; Vector3 horizontalOffset = -follow.forward * distanceAway; horizontalOffset.y = 0; // 让水平偏移跟随相机Y轴旋转,避免角色环绕时相机乱晃 horizontalOffset = Quaternion.Euler(0, transform.eulerAngles.y, 0) * horizontalOffset; targetPosition = follow.position + heightOffset + horizontalOffset; transform.position = Vector3.Lerp(transform.position, targetPosition, Time.deltaTime * smooth); transform.LookAt(follow.position + Vector3.up * 1.5f); // 看向角色上半身,更自然 }
三、关键逻辑说明
- 环绕核心:当有左右输入时,我们通过计算角色相对于摄像机的水平位置,绕摄像机Y轴旋转这个位置来更新角色坐标,实现“围着摄像机转”的效果。
- 朝向控制:调整了
FaceDir方法,让角色在环绕时朝向远离摄像机的方向,你也可以改成朝向移动的切线方向,根据手感调整。 - 相机稳定:修改了相机偏移的计算逻辑,确保高度不变,水平偏移跟随相机自身的Y轴旋转,避免角色环绕时相机出现上下或左右的抖动。
你可以先测试这套修改后的代码,再根据实际手感调整speed、rotationSpeed以及相机的参数,直到达到你想要的效果~
内容的提问来源于stack exchange,提问作者Shin The Dev
相关产品推荐
相关产品推荐

