实例化对象后,Unity 自定义编辑器 Raycast 无法正常工作

Unity Custom Editor Raycast Not Working Right After When Instantiate Objects

  1. 我创建了 Test.cs 和 TestEditor.cs(测试 class 是一个简单的 class。)
  2. Test.cs 是空的,这里是 TestEditor.cs:
using UnityEngine;
using UnityEditor;

[CustomEditor(typeof(Test))]
public class TestEditor : Editor
{
    Test test;
    GameObject cube;
    GameObject sphere;

    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();

        test = (Test)target;

        if (GUILayout.Button("Create"))
        {
            Create();
            RayCastTest();
        }

        if (GUILayout.Button("RayCast Test"))
        {
            RayCastTest();
        }
    }

    void Create()
    {
        cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
        cube.transform.position = test.transform.position;
        sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
        sphere.transform.position = test.transform.position + Vector3.right * 5f;
    }

    void RayCastTest()
    {
        Ray ray;
        RaycastHit hit;
        ray = new Ray(test.transform.position, Vector3.right);
        if (Physics.Raycast(ray, out hit, 1000f))
        {
            GameObject target = hit.collider.gameObject;
            target.transform.localScale *= 2f;
        }
    }
}
  1. 如果我在 Unity 中按下“创建”按钮,则会创建对象,但 RayCastTest() 函数不起作用。但是,如果我先按“创建”按钮,然后按“RayCast 测试”按钮,该功能就可以使用。

那么,我怎样才能让 RayCastTest() 函数在第一部分工作?

光线投射来自 Physics 引擎。 Afaik 它仅在一次 Physics 更新后起作用,因为在此之前 Collider 可能尚未重新计算 -> Physics 还“不知道” Collider

您可以尝试在 Create

之后使用 Physics.Simulate 强制执行它
if (GUILayout.Button("Create"))
{
    Create();
    Physics.Simulate(Time.fixedDeltaTime);
    RayCastTest();
}

此外,您 可能 必须禁用 Physics.autoSimulation .. 不幸的是 API 对此不是很清楚。如果是这样的话,你可以这样做

     Physics.autoSimulation = false;
     Physics.Simulate(Time.fixedDeltaTime);
     Physics.autoSimulation = true;

另外 Physics.SyncTransforms 可能会有帮助

When a Transform component changes, any Rigidbody or Collider on that Transform or its children may need to be repositioned, rotated or scaled depending on the change to the Transform. Use this function to flush those changes to the Physics engine manually.

由于您要移动创建的对象,因此您可能还必须在模拟之前调用它(同样 可能 需要与 Physics.autoSyncTransforms 一起使用),例如

if (GUILayout.Button("Create"))
{
    Create();
    
    Physics.SyncTransforms();

    Physics.autoSimulation = false;
    Physics.Simulate(Time.fixedDeltaTime);
    Physics.autoSimulation = true;

    RayCastTest();
}