首页 > 解决方案 > 为什么在销毁原始对象时临时新对象为空?

问题描述

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.SceneManagement;

public class PrefabReplace : EditorWindow
{
    [SerializeField] private GameObject prefab;
    GameObject newobj;

    [MenuItem("Tools/Prefab Replace")]
    static void CreateReplaceWithPrefab()
    {
        EditorWindow.GetWindow<PrefabReplace>();
    }

    private void OnGUI()
    {
        prefab = (GameObject)EditorGUILayout.ObjectField("Prefab", prefab, typeof(GameObject), false);

        if (GUILayout.Button("Replace"))
        {
            var selection = Selection.gameObjects.ToList();

            if (prefab != null && selection.Count > 0)
            {
                for (var i = selection.Count - 1; i >= 0; --i)
                {
                    var selected = selection[i];
                    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);
                }
            }
        }

        if (GUILayout.Button("Write settings"))
        {
            var selection = Selection.gameObjects.ToList();

            if (selection.Count > 0)
            {
                for (int i = selection.Count - 1; i >= 0; --i)
                {
                    var selected = selection[i].transform;
                    string toWrite = $"{selected.parent}:{selected.localPosition}:{selected.localRotation}:{selected.localScale}";
                    WriteDataToFile(toWrite);
                }
            }
        }

        if (GUILayout.Button("Read settings"))
        {
            var obj = GetObjectFromFile("Assets/Resources/test.txt");
            Instantiate(obj);
            DestroyImmediate(newobj);
        }

        GUI.enabled = false;
        EditorGUILayout.LabelField("Selection count: " + Selection.objects.Length);
    }

    private void OnInspectorUpdate()
    {
        Repaint();
    }

    private void WriteDataToFile(string line)
    {
        string path = "Assets/Resources/test.txt";

        StreamWriter writer = new StreamWriter(path, true);
        writer.WriteLine(line);
        writer.Close();
    }

    private GameObject GetObjectFromFile(string path)
    {
        newobj = new GameObject();
        string[] text = new string[3];
        if (File.Exists(path))
        {
            text = File.ReadAllLines(path);
            foreach (string s in text)
            {
                text = s.Split(':');
                break;
            }
            var parent = text[0].Substring(0, text[0].IndexOf(" ("));

            var localPosition = StringToVector3(text[1]);
            var localRotation = StringToQuaternion(text[2]);
            var localScale = StringToVector3(text[3]);

            if (parent != null)
            {
                GameObject toparent = GameObject.Find(parent);
                newobj.transform.parent = toparent.transform;
            }
            newobj.transform.localPosition = localPosition;
            newobj.transform.localRotation = localRotation;
            newobj.transform.localScale = localScale;
        }

        return newobj;
    }

    public static Vector3 StringToVector3(string sVector)
    {
        // Remove the parentheses
        if (sVector.StartsWith("(") && sVector.EndsWith(")"))
        {
            sVector = sVector.Substring(1, sVector.Length - 2);
        }

        // split the items
        string[] sArray = sVector.Split(',');

        // store as a Vector3
        Vector3 result = new Vector3(
            float.Parse(sArray[0]),
            float.Parse(sArray[1]),
            float.Parse(sArray[2]));

        return result;
    }

    public static Quaternion StringToQuaternion(string sQuaternion)
    {
        // Remove the parentheses
        if (sQuaternion.StartsWith("(") && sQuaternion.EndsWith(")"))
        {
            sQuaternion = sQuaternion.Substring(1, sQuaternion.Length - 2);
        }

        // split the items
        string[] sArray = sQuaternion.Split(',');

        // store as a Vector3
        Quaternion result = new Quaternion(
            float.Parse(sArray[0]),
            float.Parse(sArray[1]),
            float.Parse(sArray[2]),
            float.Parse(sArray[3]));

        return result;
    }
}

当我在行上放一个断点时:

DestroyImmediate(newobj); 

我看到变量 obj 很好,而且不为空。但是当我看到变量 obj 为空时单击继续。我正在销毁 newobj 那么为什么它不记得 obj 中的值?我不想为 obj 创建新实例,因为它会将新的 GameObject 添加到层次结构中。我只想将值分配给新的游戏对象。

标签: c#unity3d

解决方案


如果要分配具有相同数据的新对象,请使用以下结构:

var newobj = new Type(oldObj); 这将复制内容并为您留下 2 个单独的对象。

例如var obj = new ObjectClass(GetObjectFromFile("Assets/Resources/test.txt"));


推荐阅读