在 C# (Unity) 中使用静态临时变量有什么好处吗?

我想在我的下一个项目中使用更好的实践,其中可读性显然很有价值,但性能更重要。所以考虑这两段代码......


在静态温度...


public class Shot : MonoBehaviour {

    static Actor tempActor;

    static Vector3 tempVec;

    static float tempFloat;

    static HitResult hitResult;


    public float damage;

    public float unblockable;

    public Vector3 originationPoint;


    private void OnTriggerEnter(Collider collision) {

        if (collision.gameObject.layer == 11) {

            tempActor = collision.gameObject.GetComponent<Actor>();

            if (tempActor != null) {

                tempVec = collision.transform.position - originationPoint;

                // cast ray

                originatorActor.RayDisableColliders();

                bool rayHit = Physics.Raycast(originationPoint, tempVec, out hitResult, range, 1<<11, QueryTriggerInteraction.Ignore);

                if (rayHit) {

                    if (hitResult.collider.gameObject.CompareTag("Hero") || hitResult.collider.gameObject.CompareTag("Villain")) {

                        tempActor = hitResult.collider.gameObject.GetComponent<Actor>();

                        tempActor.HitByShot(class_utilities.GetAngle(hitResult.transform, originationPoint), damage, unblockable);

                    }

                }

                originatorActor.RayEnableColliders();

            }

        }

    }

}

当地宣布的临时工


public class Shot : MonoBehaviour {

    public float damage;

    public float unblockable;

    public Vector3 originationPoint;


    private void OnTriggerEnter(Collider collision) {

        if (collision.gameObject.layer == 11) {

            Actor tempActor = collision.gameObject.GetComponent<Actor>();

            if (tempActor != null) {

                Vector3 offset = collision.transform.position - originationPoint;

                // cast ray

                originatorActor.RayDisableColliders();

                HitResult hitResult;


两种方法之间在性能方面有什么区别,特别是在我看来内存分配和垃圾收集?


一只名叫tom的猫
浏览 178回答 2
2回答

喵喵时光机

最大的问题不是性能 - 而是正确性。以这种方式使用静态字段会改变含义,并可能导致以下任一方面的大问题:多个线程访问相同的静态值并在进程中互相踩踏作为一种特殊情况,这不仅可能导致意外的值,而且还可能导致“撕裂”值,因为您提到了过大的结构,例如Vector3任何需要重入的东西;调用堆栈中的每个方法都会忽略该值,而不考虑任何预期的行为基本上:除非你有很好的理由,否则不要这样做(即不要滥用临时本地变量的静态字段);请改用常规局部变量。性能上有什么区别吗就速度而言,几乎肯定不是,但你必须使用 benchmarkdotnet 之类的东西来衡量它在我看来,尤其是内存分配和垃圾收集通过将值放入静态字段,您可以通过该值使任何对象可达:可达。如果您从不清除该字段,它可能会不必要地使任意大的对象图保持活动状态。

Smart猫小萌

我倾向于同意 Marc Gravell 的主要概念,但我认为他的答案更多地与 C# 相关,而不是与 Unity 相关。是的。我同意 C# 明智地将静态值与线程混合可能会产生问题......但在您的特定情况下,OnTriggerEnter可以仅在主线程上运行(例如许多其他与统一相关的方法),因此您没有这样的风险(除非您开始在方法之外使用这些字段OnTriggerEnter)。无论如何,情况是这样的:速度性能参考文献类型无论如何,参考值都会存在于堆中。从速度方面来说,最好将它们保持静态,否则它们将继续从堆中分配/取消分配。价值类型对于值类型则是另一回事了。如果它们是静态的,您将把它们永久存储在堆上(几乎在所有情况下),而本地值类型将存在于堆栈中(寿命相当短......)如果您将它们作为静态放在堆上,我预计,一般来说,您将需要更多时间来访问它们如果将它们分配在堆栈中(作为本地值),速度会快得多内存性能对于值类型,最好将它们分配在堆栈中(以及本地值)。内存方面,引用类型也应该比本地值更好。您可以根据需要将它们保留在内存中。正如马克所解释的,使用静态字段,您可以将它们无限期地保留在内存中。值类型肯定比本地值更好。引用类型在速度方面比静态的性能更高,但在内存方面比本地的性能更高。一般来说,在您的具体情况下,即使是大量呼叫,我也没有看到任何大的变化。您仍然可以尝试使用Unity 基准测试工具对其进行基准测试(因为BenchmarkDotNet不适用于开箱即用的 Unity)。就我而言...我会使用本地值,更具可读性。
打开App,查看更多内容
随时随地看视频慕课网APP