c# - 在 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();
}
}
}
}
这两种方法在性能方面有什么区别,特别是在我看来内存分配和垃圾收集?
解决方案
最大的问题不是性能——而是正确性。以这种方式使用静态字段会改变含义,并可能导致以下任一方面的大问题:
- 多个线程访问相同的静态值并在进程中相互踩踏
- 作为一种特殊情况,这不仅会导致意外的值,还会导致“撕裂”值,因为您提到过大的结构,例如
Vector3
- 作为一种特殊情况,这不仅会导致意外的值,还会导致“撕裂”值,因为您提到过大的结构,例如
- 任何引起重入的事物;调用堆栈中的每个方法都将踩踏该值,而不考虑任何预期的行为
基本上:除非你有很好的理由,否则不要这样做(即不要滥用临时本地人的静态字段);改用常规的局部变量。
性能上有什么区别吗
速度方面,几乎可以肯定不是,但你必须用 benchmarkdotnet 之类的东西来衡量它
特别是在我看来内存分配和垃圾收集
通过将值放入静态字段,您可以使该值可以访问任何对象:可达。如果您从不清除该字段,它可能会使任意大的对象图不必要地保持活动状态。
推荐阅读
- git - git vscode 太多无法显示
- reactjs - antd:元素类型无效:需要一个字符串(对于内置组件)或一个类/函数(对于复合组件)但得到:对象
- tensorflow - Colab TPU 错误 - InvalidArgumentError:TPU 不支持的数据类型:字符串,由输出 cond_8/Identity_1:0 引起
- python - 看不到游戏车图像
- c++ - 将 gcc 参数隐藏到 CMake 文件
- javascript - ReferenceError:未定义 serverTest
- python - 如何处理 f2py 模块中的偶尔分段错误
- vba - 将查询从 MS Access 导出到 CSV,带有换行符的冗长文本的列被截断
- java - 将字符串重新复制到新字符串对重新复制数组的性能影响更大吗?
- android - 拥有“发布”apk 后,我应该在 firebase 中删除 SHA1 调试密钥吗?