C# 销毁游戏对象,但也将其保存在变量中供以后使用

C# 销毁游戏对象,但也将其保存在变量中供以后使用,c#,unity3d,C#,Unity3d,我正在创建一个程序生成的游戏,它将永远生成新的“地形”,为此,我的游戏开始延迟,因此我尝试卸载一些块,稍后我希望再次加载(如果玩家再次回到特定位置) 这是我的卸货代码: GameObject _tmp = MapGeneration.Map[Mathf.Abs(y)][x]; DestroyImmediate(MapGeneration.Map[Mathf.Abs(y)][x].gameObject); MapGeneration.Map[Mathf.Abs(y)][x] = _tmp; 稍后

我正在创建一个程序生成的游戏,它将永远生成新的“地形”,为此,我的游戏开始延迟,因此我尝试卸载一些块,稍后我希望再次加载(如果玩家再次回到特定位置)

这是我的卸货代码:

GameObject _tmp = MapGeneration.Map[Mathf.Abs(y)][x];
DestroyImmediate(MapGeneration.Map[Mathf.Abs(y)][x].gameObject);
MapGeneration.Map[Mathf.Abs(y)][x] = _tmp;
稍后,当我再次尝试实例化该块时:

Instantiate(MapGeneration.Map[Mathf.Abs(y)][x].gameObject, new Vector3(x, y, 0), Quaternion.identity);
我得到这个错误:

MissingReferenceException:类型为“GameObject”的对象已被销毁,但您仍在尝试访问它。 您的脚本应该检查它是否为null,或者不应该销毁对象。 UnityEngine.Object.Internal_实例化单(UnityEngine.Object数据,向量3位置,四元数) UnityEngine.Object.Instantiate(UnityEngine.Object原始、矢量3位置、四元数旋转) Update()(位于Assets/Scripts/MapGeneration.cs:53)


您不希望销毁对象,而是希望禁用它,这样它就不会占用处理资源。使用
Destroy()

请查看
SetActive()


它本质上相当于inspector面板中对象/组件左上角的小勾选框的代码。处于非活动状态时,引擎将“跳过”它,但这也包括
Find()
GetComponent()
等功能,因此在将游戏对象设置为非活动状态之前,请确保已存储对其的引用,否则您将无法再次“发现”它。

您不想破坏该对象,您希望禁用它,以便它不会占用处理资源。使用
Destroy()

请查看
SetActive()


它本质上相当于inspector面板中对象/组件左上角的小勾选框的代码。当游戏对象处于非活动状态时,引擎将“跳过”它,但这也包括
Find()
GetComponent()
等功能,因此在将其设置为非活动状态之前,请确保已存储对该游戏对象的引用,否则您将无法再次“发现”它。

销毁任何游戏对象后,您将无法访问该游戏对象

要解决此问题,必须为对象创建预制件,以下步骤说明如何使用预制件创建和销毁一个对象:

1-为您的一个对象创建一个预置。(例如“terrain1”对象) 2-在脚本(类级别)中,定义以下变量,如下所示:

public GameObject terrain1Prefab;
GameObject terrain1Instance;
terrain1Instance = Instantiate(terrain1Prefab, new Vector3(x, y, 0), Quaternion.identity);
Destroy(terrain1Instance);
3-将公共变量“terrain1prefable”链接到您创建的预置

4-在您的函数中,创建“TerraIn1Prefact”的实例,并按如下方式存储其实例:

public GameObject terrain1Prefab;
GameObject terrain1Instance;
terrain1Instance = Instantiate(terrain1Prefab, new Vector3(x, y, 0), Quaternion.identity);
Destroy(terrain1Instance);
5-现在,您可以按如下方式销毁实例:

public GameObject terrain1Prefab;
GameObject terrain1Instance;
terrain1Instance = Instantiate(terrain1Prefab, new Vector3(x, y, 0), Quaternion.identity);
Destroy(terrain1Instance);

销毁任何游戏对象后,您无法访问它

要解决此问题,必须为对象创建预制件,以下步骤说明如何使用预制件创建和销毁一个对象:

1-为您的一个对象创建一个预置。(例如“terrain1”对象) 2-在脚本(类级别)中,定义以下变量,如下所示:

public GameObject terrain1Prefab;
GameObject terrain1Instance;
terrain1Instance = Instantiate(terrain1Prefab, new Vector3(x, y, 0), Quaternion.identity);
Destroy(terrain1Instance);
3-将公共变量“terrain1prefable”链接到您创建的预置

4-在您的函数中,创建“TerraIn1Prefact”的实例,并按如下方式存储其实例:

public GameObject terrain1Prefab;
GameObject terrain1Instance;
terrain1Instance = Instantiate(terrain1Prefab, new Vector3(x, y, 0), Quaternion.identity);
Destroy(terrain1Instance);
5-现在,您可以按如下方式销毁实例:

public GameObject terrain1Prefab;
GameObject terrain1Instance;
terrain1Instance = Instantiate(terrain1Prefab, new Vector3(x, y, 0), Quaternion.identity);
Destroy(terrain1Instance);

等待什么?你知道C#是通过引用传递的是吗?所以,如果你将一个对象的实例传递给一个变量,然后销毁该实例,那么这个变量也将指向空?这就是你们的错误是的,我知道,这就是为什么我来找你们寻求建议。等等。。什么?你知道C#是通过引用传递的是吗?所以,如果你将一个对象的实例传递给一个变量,然后销毁该实例,那么这个变量也将指向空?因此你的错误是的,我知道,这就是为什么我来找你们寻求建议。当加载的非活动块数量达到一个很高的数字时,你仍然会遇到延迟问题。。。如果您试图创建无限地形,则此方法将导致跟踪过程中出现问题。。。我会在需要的时候从文件中保存和加载我的块,我的地形可以永远保持下去:)@Savlon Cool,我必须尝试一下!当加载的非活动块的数量达到一个很高的数字时,您仍然会遇到延迟问题。。。如果您试图创建无限地形,则此方法将导致跟踪过程中出现问题。。。我会在需要的时候从文件中保存和加载我的块,我的地形可以永远保持下去:)@Savlon Cool,我必须尝试一下!