You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 07:31:34