如何比较预制件和GameObject?

Ben*_*mil 1 c# unity-game-engine

prefab = (GameObject)EditorGUILayout.ObjectField("Prefab", prefab, typeof(GameObject), false);

        GUI.enabled = false;
        var selection = Selection.objects.OfType<GameObject>().ToList();
        for (var i = selection.Count - 1; i >= 0; --i)
        {
            selectedObject = selection[i];
            if (prefab != null && selection.Count > 0
                && prefab != selectedObject)
                GUI.enabled = true;
        }
        if (GUILayout.Button("Replace"))
        {
            selection = Selection.objects.OfType<GameObject>().ToList();

            if (prefab != null && selection.Count > 0)
            {
                for (var i = selection.Count - 1; i >= 0; --i)
                {
                    var selected = selection[i];
                    SceneManager.SetActiveScene(SceneManager.GetSceneByName(selected.scene.name));

                    var prefabType = PrefabUtility.GetPrefabType(prefab);
                    GameObject newObject;

                    if (prefabType == PrefabType.Prefab)
                    {
                        newObject = (GameObject)PrefabUtility.InstantiatePrefab(prefab);
                    }
                    else
                    {
                        newObject = Instantiate(prefab);
                        newObject.name = prefab.name;
                    }

                    if (newObject == null)
                    {
                        Debug.LogError("Error instantiating prefab");
                        break;
                    }

                    Undo.RegisterCreatedObjectUndo(newObject, "Replace With Prefabs");
                    newObject.transform.parent = selected.transform.parent;
                    newObject.transform.localPosition = selected.transform.localPosition;
                    newObject.transform.localRotation = selected.transform.localRotation;
                    newObject.transform.localScale = selected.transform.localScale;
                    newObject.transform.SetSiblingIndex(selected.transform.GetSiblingIndex());
                    Undo.DestroyObjectImmediate(selected);
                }
            }
        }
Run Code Online (Sandbox Code Playgroud)

我希望只有当预制件与所选对象不同时,该按钮才会启用.

我第一次选择一个或多个对象,然后单击"立即替换",用预制件替换所选对象.但是如果我再次选择被替换的对象,它仍然会启用按钮.但它们应该与预制件相同,而不是启用按钮.

这是我正在尝试的比较:

prefab != selectedObject
Run Code Online (Sandbox Code Playgroud)

AnL*_*Log 7

它们不相同,因为!=在两个没有相等运算符重载的引用类型之间使用的C#将进行引用比较.这意味着它将检查变量是否引用相同的底层对象实例.因此,如果prefab和selectedObject是完全相同的对象实例(iirc检查对象ID是否相等),prefab != selectedObject评估为false.

就我收集而言,您希望它评估为false,因此当且仅当所选对象不是预制件的克隆时才激活该按钮.幸运的是,Unity3D有一种方法可以告诉GameObject是否从特定的预制件中实例化.它被称为PrefabUtility .GetCorrespondingObjectFromSource.所以这可能符合您的要求:

改变这一部分:

for (var i = selection.Count - 1; i >= 0; --i)
{
    selectedObject = selection[i];
    if (prefab != null && selection.Count > 0
        && prefab != selectedObject)
        GUI.enabled = true;
}
Run Code Online (Sandbox Code Playgroud)

对此:

for (var i = selection.Count - 1; i >= 0; --i)
{
    var selectedObject = selection[i];
    if (prefab != null && selection.Count > 0
        && prefab != PrefabUtility
        .GetCorrespondingObjectFromSource(selectedObject))
        GUI.enabled = true;
}
Run Code Online (Sandbox Code Playgroud)

  • 是的,我的道歉.似乎直接调用OnGUI是Unity3D不喜欢的东西.它只对我有用,因为我没有调用GUILayout方法.尝试用``Repaint()``替换``OnSelectionChange()``中的``OnGUI()``调用. (2认同)