将函数调用转换为常量

时间:2019-03-14 18:41:47

标签: c# unity3d

我们有一个变量a,为了进行for循环,它是通过函数WhatIsA()计算出来的。 WhatIsA的值是已知的编译时。有什么我可以做的(也许是属性吗?)让编译器知道它可以擦除变量并在所有引用中放置常量?

for (int i = 0; i < 1343434; i++)
{
    int a = WhatIsA(); //retval of WhatIsA does not change after compilation, ever.
    DoSomethingWithVariableA(a);
    DooooSomethingWithVariableA(a);
    DoooooooSomethingWithVariableA(a);
}

最初的问题来自Unity的环境。

private void Update()
{
    LayerMask mask = LayerMask.GetMask("Terrarin");
    CollidesBottom = Raycast((Vector2)transform.position + colliderBottomLeftOffset, Vector2.right, colliderWidth, mask);
    CollidesTop = Raycast((Vector2)transform.position + colliderTopRightOffset, Vector2.left, colliderWidth, mask);
    CollidesRight = Raycast((Vector2)transform.position + colliderTopRightOffset, Vector2.down, colliderHeight, mask);
    CollidesLeft = Raycast((Vector2)transform.position + colliderBottomLeftOffset, Vector2.up, colliderHeight, mask);
}

GetMask是已知的或至少应该是编译时。编译器可能会或可能不会对其进行优化。我唯一能做的就是将掩码提升为字段变量,然后在Start函数中对其进行计算,但是它的作用域超出了需要。

2 个答案:

答案 0 :(得分:0)

aStart()内设置Awake()并引用变量。

答案 1 :(得分:0)

您可以查看this thread,以获取有关LayerMasks如何工作的更深入的解释。

简而言之:LayerMask基本上是一个int值。它代表一个二进制的32位标记系统,您可以在其中打开(1)和关闭(0)某些层索引。所以例如值

0000 0000 0000 0000 0000 0000 0000 0101
                                    | |
                                    | |layer1
                                    |
                                    |layer3

意味着应该启用layer1和layer3,并且十进制的值为5


因此,当然有一些选项可以使该图层掩码保持不变。最简单的方法是一次输出

LayerMask mask = LayerMask.GetMask("Terrarin");
Debug.Log(mask.value);

这将为您提供图层蒙版的十进制表示形式。而且比起您可以简单地使用

// 256 e.g. is the layer9
// the first entry after Unity's 8 default layers
LayerMask mask = 256;

或者如果您已经知道所需图层的索引,也可以简单地使用

LayerMask mask = 1 << 9;

或使用那些Binary -> Decimal converterDecimal -> Binary converter


当然,您也只能在Update中这样做,但是为什么要在每一帧都重新创建它呢?如果仍要对其进行硬编码,则也可以使用const或如其他答案中所述,只需在Awake中获得一次值即可。

我也不理解您对“范围”的担忧。只要它保持私有状态就没关系

..相反:您的Update解决方案一次又一次地分配和销毁mask-> GC的更多工作。


但是,我不推荐它!

这是一个非常糟糕的设计选择,原因有二:

  1. 后来的设计更改,您将不得不更改代码。您重命名必须更改代码的图层。您想在必须先重新计算值之后,再向蒙版添加一个图层。等等...

  2. 它使您的代码0%灵活且可重复使用!想象一下,您现在已经完成了Raycaster系统。现在,您希望场景中的另一个对象在不同的​​图层上进行光线投射...因此,您是希望复制整个脚本只是为了更改硬编码图层(我希望不是),还是希望使用相同的脚本并简单地更改图层值。

因此,实际上,我认为最好的解决方案是完全从不硬编码层名称/索引/掩码,而是让开发人员在检查器中对其进行调整。您仍然可以通过以下方式为它提供一个硬编码的默认值:

[SerializeField] private LayerMask mask = 256;

这在检查器中为您提供了一个字段,您可以在其中轻松选择图层。您甚至可以出于调试原因在运行时更改它们。