Unity骰子开发问题:点击反向移动但Y轴高度未变化,求解决
骰子翻滚功能修复方案
问题背景
开发游戏时需要实现骰子功能:点击骰子某一面,骰子向点击的反方向移动(比如点击背面则向前移动),同时要模拟真实的重力翻滚效果(Y轴高度随翻滚变化)。但当前代码仅改变X、Z轴位置,Y轴高度无变化,无法实现真实的翻滚效果。

当前使用的代码:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class MoveCube : MonoBehaviour { Vector3 movePosition; public float time = 0.02f; [HideInInspector] public bool blockClick = false; private void Start() { movePosition = transform.position; } private void Update() { blockClick = false; if (Input.GetMouseButtonDown(0)) { Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit raycastHit; if (Physics.Raycast(ray, out raycastHit)) { string hitName = raycastHit.transform.name; if (hitName == "MoveCube") { move(raycastHit); blockClick = true; } } } transform.position = Vector3.Lerp( transform.position, movePosition, time); } public void move(RaycastHit raycastHit) { Vector3 incomingVec = raycastHit.normal - Vector3.up; // South if (incomingVec == new Vector3(0, -1, -1)) { movePosition = movePosition + new Vector3(0, 0, 1); return; } // North if (incomingVec == new Vector3(0, -1, 1)) { movePosition = movePosition + new Vector3(0, 0, -1); return; } // West if (incomingVec == new Vector3(-1, -1, 0)) { movePosition = movePosition + new Vector3(1, 0, 0); return; } // East if (incomingVec == new Vector3(1, -1, 0)) { movePosition = movePosition + new Vector3(-1, 0, 0); return; } } }

问题分析
当前代码仅修改了movePosition的X、Z轴坐标,没有处理骰子翻滚时的Y轴高度变化,同时只是平移位置而非模拟真实的翻滚旋转,导致无法呈现重力作用下的骰子滚动效果。
修复方案
要实现真实的骰子翻滚,需要同时处理位置偏移和旋转角度,并且在翻滚过程中让Y轴高度随旋转自然变化。以下是修改后的代码:
using System.Collections; using UnityEngine; public class MoveCube : MonoBehaviour { public float rollDuration = 0.5f; // 翻滚一次的时长 private bool isRolling = false; // 是否正在翻滚,防止重复点击 private void Update() { if (isRolling) return; if (Input.GetMouseButtonDown(0)) { Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); if (Physics.Raycast(ray, out RaycastHit hit) && hit.transform.name == "MoveCube") { StartCoroutine(RollDice(hit.normal)); } } } private IEnumerator RollDice(Vector3 hitNormal) { isRolling = true; Vector3 rollAxis; Vector3 targetPosition = transform.position; Quaternion targetRotation = transform.rotation; // 根据点击的面确定翻滚轴和目标位置、旋转 if (hitNormal == Vector3.forward) // 点击前面,向后翻滚 { rollAxis = Vector3.right; targetPosition += Vector3.back; targetRotation *= Quaternion.Euler(-90, 0, 0); } else if (hitNormal == Vector3.back) // 点击后面,向前翻滚 { rollAxis = Vector3.right; targetPosition += Vector3.forward; targetRotation *= Quaternion.Euler(90, 0, 0); } else if (hitNormal == Vector3.left) // 点击左面,向右翻滚 { rollAxis = Vector3.forward; targetPosition += Vector3.right; targetRotation *= Quaternion.Euler(0, 0, 90); } else if (hitNormal == Vector3.right) // 点击右面,向左翻滚 { rollAxis = Vector3.forward; targetPosition += Vector3.left; targetRotation *= Quaternion.Euler(0, 0, -90); } else if (hitNormal == Vector3.up) // 点击上面,向下翻滚(可选) { rollAxis = Vector3.right; targetPosition += Vector3.down; targetRotation *= Quaternion.Euler(180, 0, 0); } else if (hitNormal == Vector3.down) // 点击下面,向上翻滚(可选) { rollAxis = Vector3.right; targetPosition += Vector3.up; targetRotation *= Quaternion.Euler(-180, 0, 0); } else { isRolling = false; yield break; } float elapsedTime = 0f; Vector3 startPosition = transform.position; Quaternion startRotation = transform.rotation; // 平滑执行翻滚动画 while (elapsedTime < rollDuration) { elapsedTime += Time.deltaTime; float t = elapsedTime / rollDuration; // 使用SmoothStep让动画更自然 t = Mathf.SmoothStep(0, 1, t); transform.position = Vector3.Lerp(startPosition, targetPosition, t); transform.rotation = Quaternion.Lerp(startRotation, targetRotation, t); yield return null; } // 确保最终位置和旋转精确到位 transform.position = targetPosition; transform.rotation = targetRotation; isRolling = false; } }
关键修改点
- 使用协程实现平滑的翻滚动画,避免直接瞬间移动/旋转导致的生硬效果
- 同时处理位置偏移和旋转角度,让Y轴高度随翻滚自然变化(比如向前翻滚时,骰子会先抬起再落下,Y轴先升后降)
- 添加
isRolling状态锁,防止在翻滚过程中重复点击 - 使用
Quaternion处理旋转,确保骰子翻滚的角度正确 - 基于点击面的法线方向(
hitNormal)直接判断翻滚方向,比原代码的incomingVec更直观可靠
额外注意事项
- 确保骰子对象添加了Collider组件(比如
BoxCollider),否则射线检测无法生效 - 如果骰子是标准立方体,边长为1的话,位置偏移量设置为1即可匹配翻滚后的位置;如果边长不同,需要调整偏移量为对应长度
- 可以调整
rollDuration参数来控制翻滚的快慢,数值越小翻滚越快
内容的提问来源于stack exchange,提问作者olios
相关产品推荐
相关产品推荐

