首页 > 解决方案 > 在 C# (Unity) 中使用静态临时变量有什么好处吗?

问题描述

我知道本地声明的变量被编译成与此处的 StackOverflow 答案基本相同的代码。但是,它不包括创建和使用静态对象,尤其是 Unity 对象。我对 C# 的了解是来自 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;
                bool rayHit = Physics.Raycast(originationPoint, offset, 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();
            }
        }
    }
}

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

标签: c#unity3d

解决方案


最大的问题不是性能——而是正确性。以这种方式使用静态字段会改变含义,并可能导致以下任一方面的大问题:

  • 多个线程访问相同的静态值并在进程中相互踩踏
    • 作为一种特殊情况,这不仅会导致意外的值,还会导致“撕裂”值,因为您提到过大的结构,例如Vector3
  • 任何引起重入的事物;调用堆栈中的每个方法都将踩踏该值,而不考虑任何预期的行为

基本上:除非你有很好的理由,否则不要这样做(即不要滥用临时本地人的静态字段);改用常规的局部变量。


性能上有什么区别吗

速度方面,几乎可以肯定不是,但你必须用 benchmarkdotnet 之类的东西来衡量它

特别是在我看来内存分配和垃圾收集

通过将值放入静态字段,您可以使该值可以访问任何对象:可达。如果您从不清除该字段,它可能会使任意大的对象图不必要地保持活动状态。


推荐阅读