实例化对象后,Unity 自定义编辑器 Raycast 无法正常工作
Unity Custom Editor Raycast Not Working Right After When Instantiate Objects
- 我创建了 Test.cs 和 TestEditor.cs(测试 class 是一个简单的 class。)
- 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;
}
}
}
- 如果我在 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();
}
- 我创建了 Test.cs 和 TestEditor.cs(测试 class 是一个简单的 class。)
- 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; } } }
- 如果我在 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, anyRigidbody
orCollider
on thatTransform
or its children may need to be repositioned, rotated or scaled depending on the change to theTransform
. Use this function to flush those changes to thePhysics
engine manually.
由于您要移动创建的对象,因此您可能还必须在模拟之前调用它(同样 可能 需要与 Physics.autoSyncTransforms
一起使用),例如
if (GUILayout.Button("Create"))
{
Create();
Physics.SyncTransforms();
Physics.autoSimulation = false;
Physics.Simulate(Time.fixedDeltaTime);
Physics.autoSimulation = true;
RayCastTest();
}