当多次调用其方法时,C#如何处理内存中的变量?

How does C# handle variables in memory when their method is called multiple times?

第一次在这里问。我的经验只是“高级初学者”。问题是由于 Unity 中的对象实例化而导致内存中的变量存储。
需要稍微解释一下设置:

在我的场景中,我实例化了整个 starsystem。该脚本最多可以创建 8 个行星,每个行星最多有 3 个卫星和 4 个锚点(空 gameObjects)。我不改变场景,我只销毁 starsystem 并实例化新场景,因此我需要确保所有旧引用都从内存中消失。我想确保我不会通过用永远不会被删除的 gameObjects 填充内存来造成内存泄漏。

下面是我的脚本实例化卫星的部分,可以在单个系统实例化中多次调用。月亮 gameObject 将在实例化后“返回”给调用者,并添加到调用者中创建的另一个变量中,这是它的官方变量 planetXMoonY,每个系统只能存在一次,并且将是 nulled 在新系统实例化之前。

在版本 1 中,我在方法中创建临时变量,在版本 2 中,我在外部创建它们并在实例化之前先重置它们。

这是如何在内存中处理的?我认为在一段时间后的版本 1 中内存中可能有数十个或更多 newMoon GameObjects 是正确的吗?同名,但当然有单独的实例ID,我会填满内存。

当对象 planetXMoonY 被销毁时会发生什么?当我理解正确时,newMoon 变量不再有连接,但 planetXMoonY 引用将被 GC() 及时删除。但是 newMoon 变量是否会在没有直接调用将其设置为 null 的情况下从内存中删除?

所以我想也许版本 2 是一个改进。首先将其重置为 null 以确保 garbageCollector 及时删除所有 newMoons 是否有帮助,因为在返回 gameObject 后不需要它们,这里仅用于实例化目的。但是我仍然以这种方式创建几十个,还是一个?

我希望问题足够清楚。我似乎在这里错过了对内存使用的一些基本理解。我想我在这里遗漏了一个关于如何正确安全地创建变量的非常重要的知识片段,我想确保我未来的工作流程得到改进。预先感谢您的帮助。

B/R 星人

版本 1:

private GameObject InstantiateMoon(GameObject moon, GameObject planetSphere, float moonSphereRadius, float moonOrbit, float MoonOrbit_Y)
    {
    GameObject newMoon = Instantiate(moon, planetSphere.transform.position, Quaternion.identity, spheresContainer.transform) as GameObject;
    GameObject newMoonSphere = newMoon.transform.Find("MoonSphere").gameObject;
    newMoonSphere.transform.localScale = new Vector3(moonSphereRadius, moonSphereRadius, moonSphereRadius);
    newMoonSphere.transform.localPosition = new Vector3(0,0,moonOrbit);
    newMoon.transform.localRotation = Quaternion.AngleAxis(MoonOrbit_Y, Vector3.up);
    DrawCircle orbitLine = newMoon.transform.Find("OrbitLine").gameObject.GetComponent<DrawCircle>();
    orbitLine.InitializeLine(moonOrbit);
    newMoon.transform.SetParent(planetSphere.transform);
    return newMoon;
    }

版本 2

private GameObject newMoon;
private GameObject newMoonSphere;
private DrawCircle orbitLine;

private GameObject InstantiateMoon2(GameObject moon, GameObject planetSphere, float moonSphereRadius, float moonOrbit, float MoonOrbit_Y)
    {
    newMoon = null;
    newMoonSphere = null;
    orbitLine = null;

    newMoon = Instantiate(moon, planetSphere.transform.position, Quaternion.identity, spheresContainer.transform) as GameObject;
    newMoonSphere = newMoon.transform.Find("MoonSphere").gameObject;
    newMoonSphere.transform.localScale = new Vector3(moonSphereRadius, moonSphereRadius, moonSphereRadius);
    newMoonSphere.transform.localPosition = new Vector3(0,0,moonOrbit);
    newMoon.transform.localRotation = Quaternion.AngleAxis(MoonOrbit_Y, Vector3.up);
    orbitLine = newMoon.transform.Find("OrbitLine").gameObject.GetComponent<DrawCircle>();
    orbitLine.InitializeLine(moonOrbit);
    newMoon.transform.SetParent(planetSphere.transform);
    return newMoon;
    }

长话短说,第二个功能不是改进。

当你这样做时:

newMoon = Instantiate(moon, planetSphere.transform.position, Quaternion.identity, spheresContainer.transform) as GameObject;

先前的值已从 private newMoon 成员中删除,如果它未与您代码中的另一个变量相关联,它将被垃圾收集器拾取。

GC 会在没有使用记录器时选择一个对象。如果对象没有分配给变量,那么它被认为是未使用的。

第一个函数中的变量本身在函数结束时不再存在。它 returns 对象的引用,如果没有在任何地方分配,对象本身也将被 GC 拾取以进行处理。

这主要取决于您在函数之外做了什么,而不是函数内部发生了什么。

如果您担心内存使用问题,请查看众所周知的 GoF 蝇量级模式 https://en.m.wikipedia.org/wiki/Flyweight_pattern,我认为这对您的情况会有所帮助。