Unity3D VR场景中计算控制器碰撞目标的精度实现问询
计算Oculus VR控制器击中物体的精度
我正在使用Unity3D 2022.3.10f开发Oculus VR游戏,需要计算玩家用控制器击中物体的精度。为便于测试,设置两个带碰撞器的球体:静态球体1位于(0,1,1),球体2位于(0,1,0),沿Z轴相距1单位。当给球体2施加朝向球体1的速度触发碰撞时,希望得到碰撞精度百分比——通过投射球体2的运动路径,计算其中心接近球体1中心的程度,正面对撞为100%,擦边则接近0%。
尝试多种方法未果,现寻求可行代码。
补充说明
双球体仅为测试装置,实际项目中已为每个手柄控制器挂载AverageDirectionCalculator脚本,可实时获取Average Velocity(整数)和Average Direction(Vector3),存储在单例中供随时调用,希望借此计算碰撞精度。脚本代码如下:
public class AverageDirectionCalculator : MonoBehaviour { private Vector3[] recentPositions = new Vector3[10]; private int currentIndex = 0; void Update() { // Store the current position in the array recentPositions[currentIndex] = transform.position; // Increment the index and wrap around if necessary currentIndex = (currentIndex + 1) % recentPositions.Length; } public Vector3 GetAverageDirection() { Vector3 averageDirection = Vector3.zero; // Calculate the average direction based on the stored positions for (int i = 0; i < recentPositions.Length - 1; i++) { averageDirection += (recentPositions[i + 1] - recentPositions[i]).normalized; } // Normalize the result to get the average direction averageDirection.Normalize(); return averageDirection; } public int GetVelocity() { // Calculate the velocity based on the magnitude of the most recent position change int previousIndex = (currentIndex - 1 + recentPositions.Length) % recentPositions.Length; float velocity = (recentPositions[currentIndex] - recentPositions[previousIndex]).magnitude / Time.deltaTime; float maxPossibleVelocity = 100f; float scaledVelocity = (velocity / maxPossibleVelocity) * 100f; // Cast the scaled velocity to an integer int scaledVelocityInt = Mathf.RoundToInt(scaledVelocity); return scaledVelocityInt; } }
可行解决方案
在derHugo帮助下找到可行方案,步骤如下:
- 碰撞触发时,通过AverageDirection脚本获取控制器的运动轨迹;
- 计算步长(如控制器方向向量的1/250);
- 沿轨迹逐步移动,计算每个位置到目标的距离;
- 找到最小距离,以此判断轨迹接近目标的程度。
测试代码如下:
float _distanceToTarget = 0f; float _minDistanceFound = 1000f; Vector3 _stepAmount = Vector3.zero; Vector3 _refPoint = Vector3.zero; private void OnTriggerEnter(Collider collider) { _distanceToTarget = Vector3.Distance(collider.transform.position, transform.position); _minDistanceFound = _distanceToTarget; _stepAmount = controllerDirection / StepDiv; _refPoint = transform.position; var target = collider.transform.position; while (_distanceToTarget <= _minDistanceFound) { _refPoint = _refPoint + _stepAmount; _distanceToTarget = Vector3.Distance(target, _refPoint); if (_distanceToTarget < _minDistanceFound) { _minDistanceFound = _distanceToTarget; } GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere); sphere.transform.position = _refPoint; sphere.transform.localScale = new Vector3(0.06f, 0.06f, 0.06f); } }
虽有数学方法可替代分步计算,但该方案已能满足需求。
内容的提问来源于stack exchange,提问作者Rowie
相关产品推荐
相关产品推荐

