Unity3D:如何让漫游车(立方体)贴合不规则月球表面移动并固定?
不规则月球地形漫游车贴合控制解决方案
问题背景
正在开发太空题材校园项目,以立方体模拟月球漫游车,需实现始终贴合不规则月球表面移动的控制逻辑,参考Sebastian Lague《Geographical Adventures》的地面载具模式(移除上下移动,底面固定贴地)。现有代码已实现引力吸引与底面朝向月球中心,但存在以下问题:
- 无法稳定贴合不规则地形,出现浮空/穿模
- 漫游车会自行漂移回赤道区域
- 移动控制未适配球面地形的切线坐标系
现有代码问题分析
- 直接修改
rb.position会破坏刚体物理状态,导致地形贴合不稳定 - 移动逻辑使用世界坐标系X/Z轴,未基于当前位置的地表切线方向,非赤道区域移动时会产生朝向偏差,最终漂移回赤道
- 引力受力与强制位置修改冲突,刚体持续受引力作用后会脱离地表约束
修正后的代码
using UnityEngine; public class RoverController : MonoBehaviour { public Transform moonCenter; public float moveSpeed = 8f; public float groundCheckDistance = 2f; public float rotationSmoothness = 12f; private Rigidbody rb; private Vector3 localUp; private Vector3 localForward; private Vector3 localRight; void Start() { rb = GetComponent<Rigidbody>(); rb.useGravity = false; rb.freezeRotation = true; rb.interpolation = RigidbodyInterpolation.Interpolate; } void FixedUpdate() { // 计算当前位置的引力方向(指向月球中心) localUp = (moonCenter.position - transform.position).normalized; // 计算地表切线坐标系的前/右方向 localForward = Vector3.Cross(transform.right, localUp).normalized; localRight = Vector3.Cross(localUp, localForward).normalized; // 地表贴合逻辑:射线检测获取地表高度 RaycastHit hit; if (Physics.Raycast(transform.position, localUp, out hit, groundCheckDistance)) { // 计算目标位置:保持底面与地表接触 float targetHeight = hit.distance - (transform.localScale.y * 0.5f); Vector3 targetPosition = transform.position + localUp * targetHeight; // 使用MovePosition平滑移动刚体,避免物理冲突 rb.MovePosition(targetPosition); // 冻结垂直于地表方向的速度,防止浮空 rb.velocity = Vector3.ProjectOnPlane(rb.velocity, localUp); } // 旋转逻辑:保持底面朝向月球中心,前向沿地表切线 Quaternion targetRotation = Quaternion.LookRotation(localForward, localUp); rb.MoveRotation(Quaternion.Lerp(transform.rotation, targetRotation, Time.fixedDeltaTime * rotationSmoothness)); } void Update() { // 获取输入 float horizontal = Input.GetAxis("Horizontal"); float vertical = Input.GetAxis("Vertical"); // 基于地表切线坐标系计算移动方向 Vector3 moveDir = (localForward * vertical + localRight * horizontal).normalized; // 设置刚体速度,仅沿地表平面移动 rb.velocity = moveDir * moveSpeed; } }
关键改动说明
- 地表贴合优化:使用
rb.MovePosition替代直接修改位置,配合Vector3.ProjectOnPlane冻结垂直地表的速度,确保刚体始终贴地,同时保留物理稳定性 - 球面坐标系适配:基于当前位置的引力方向(
localUp)计算地表切线的前/右方向,移动输入完全适配球面地形,解决赤道漂移问题 - 旋转逻辑简化:使用
Quaternion.LookRotation直接计算目标旋转,配合rb.MoveRotation实现平滑且准确的贴地朝向 - 移除冗余引力:取消主动添加引力的逻辑,通过地表贴合的位置约束替代,避免物理冲突
内容的提问来源于stack exchange,提问作者fay__zul
相关产品推荐
相关产品推荐

