【问题标题】:How does C# handle variables in memory when their method is called multiple times?多次调用其方法时,C#如何处理内存中的变量?
【发布时间】:2020-06-27 06:32:26
【问题描述】:

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

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

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

【问题讨论】:

    标签: c# unity3d variables memory garbage-collection


    【解决方案1】:

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

    当你这样做时:

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

    先前的值与 private newMoon 成员解除关联,如果它不与代码中的另一个变量相关联,则垃圾收集器会拾取它。

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

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

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

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

    【讨论】:

    • 谢谢,我看看这个链接。所以简而言之,只要从现有脚本实例调用相同的方法(实例化脚本只有一个实例),总会有一个“newMoon”变量,并且在函数结束后它不再存在说过。在那种情况下,我想我可以保留第 1 版,它读起来更流畅一些。抱歉,因为我是新用户,所以无法为您的答案投票;)
    • 澄清一下,在 c# 中是的,这是真的。在 Unity 中,所有通过 new 或实例化创建的 Unity 对象都将被其对象管理器引用,让 GC 拾取它的唯一方法是调用 destroy,因此 Unity 的对象管理器知道您已完成它,并将停止引用以便 GC 将其拾取。
    • 听起来很合乎逻辑。所以我对星系的破坏是安全的。但是实例化“新月”对象呢?该方法返回对象并将其存储在稍后将被销毁的变量中。 newMoon 是对象管理器的一部分,还是这纯粹是脚本中的 c# 东西,而 objectmanager 不关心这个对象?。
    • 当你调用它时,是的,但是,当你调用它的第二次破坏时,Unity 并不关心你是否存储了一个引用,它的 GC 仍然会拾取它。
    • @Starman001 这是一个深入了解 Unity GC docs.unity3d.com/Manual/… 的链接
    猜你喜欢
    • 1970-01-01
    • 2014-12-03
    • 1970-01-01
    • 2021-01-03
    • 2019-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多