【问题标题】:Unity3d Select Object nearest to click no collidersUnity3d选择最接近点击没有碰撞器的对象
【发布时间】:2017-04-16 20:40:01
【问题描述】:

我有一个用于开发的 Mixamo 模型。该模型完全装配有骨架。我正在尝试创建一个函数,该函数允许我在没有对撞机的情况下选择骨架的一部分。

此当前脚本仅适用于对撞机,

public void RegisterSelectControls()
{
    if (Input.GetMouseButtonDown(0))
    {
        var hit = new RaycastHit();
        var ray = Camera.main.ScreenPointToRay(Input.mousePosition);

        if (Physics.Raycast(ray, out hit, 100.0f))
        {
            var objectHitName = hit.collider.transform.name;
            Debug.Log(objectHitName);
        }
    }
}

有没有办法检测骨架的哪一部分被点击,或者骨架中离点击最近的部分?

我不想手动将碰撞器添加到每个身体部位,这将过于多余和多余,如果我选择使用不同的模型,我将不得不修改盒子碰撞器,我想这样做而不指定盒子对撞机

编辑

我无法将碰撞器添加到模型中,将来我打算支持允许用户上传模型,在该模型中,它需要自然地选择要与之交互的脊椎部分,而无需用户设置边界脊柱的组成部分

【问题讨论】:

  • 不同身体部位的不同碰撞器。 answers.unity3d.com/questions/64678/…
  • 在谷歌上搜索“unity head shot”
  • 是的,我知道这适用于对撞机,但是骨骼太多,我不想为所有这些人手动添加对撞机,我只想通过单击来计算这个一个二维平面并找到离那里最近的骨头
  • 啊,我看到了你的问题。我会考虑的。也许是对撞机生成脚本?呵呵
  • 是的,根据引用的链接,您需要手动执行 Collier 和光线投射统一进行的所有计算。

标签: c# unity3d raycasting 3d-model


【解决方案1】:

对于其他寻找如何做到这一点的人来说,这实际上是半简单的。将此函数放入更新循环中,并使“SpineRoot”等于您要检查的所有对象的根节点。

public void RegisterSelectControls()
{
    if (Input.GetMouseButtonDown(0))
    {
        var clickLocation = Input.mousePosition;

        Transform closestBone = null;

        this.MinimumRecursiveBoneDistance(clickLocation, SpineRoot, out closestBone);

        if(null != closestBone)
        {
            Debug.Log(closestBone.gameObject.name);
        }
    }
}

public float MinimumRecursiveBoneDistance(Vector3 clickLocation, Transform root, out Transform closestBone)
{
    float minimumDistance = float.MaxValue;
    closestBone = null;
    foreach (Transform bone in root)
    {

        var boneScreenPoint = Camera.main.WorldToScreenPoint(bone.position);
        var distance = Math.Abs(Vector3.Distance(clickLocation, boneScreenPoint));

        if (distance < minimumDistance)
        {
            minimumDistance = distance;
            closestBone = bone;
        }

        if (bone.childCount > 0)
        {
            Transform closestChildBone;
            var minimumChildDistance = this.MinimumRecursiveBoneDistance(clickLocation, bone, out closestChildBone);
            if(minimumChildDistance < minimumDistance)
            {
                minimumDistance = minimumChildDistance;
                closestBone = closestChildBone;
            }
        }

    }

    return minimumDistance;
}

这段代码可以使用一些重构,这只是一个概念证明。这将适用于纯粹最近的。但是,这可能会产生一个潜在的错误,如果单击一个对象,并且该对象的中心距离单击另一个对象的中心更远,您将选择另一个对象。

【讨论】:

    猜你喜欢
    • 2022-08-20
    • 2023-01-29
    • 1970-01-01
    • 2018-12-11
    • 2013-11-08
    • 1970-01-01
    • 1970-01-01
    • 2017-09-25
    • 2022-01-21
    相关资源
    最近更新 更多