在回收价值类型统一是否有一点
我发现文章说回收和重用变量是团结的好习惯。 所以我采纳了它。 但有一点不清楚:这是否适用于值类型变量(整数,向量)?
有没有一点我使用这个:
int x; Vector3 v; void functionCalledVeryOften(){ x=SomeCalculation(); v=SomeCalc(); //do something with x and v }
而不是这个:
void functionCalledVeryOften(){ int x=SomeCalculation(); Vector3 v=SomeCalc(); //do something with x and v }
这完全取决于您希望对此对象执行的操作。
让我们拿你的第一个例子,说我们想要从第二个函数functionCalledEveryOnceSoOften()
访问变量x和v这个函数不需要任何重载来传递变量,并且可以直接访问类实例中的变量。
在第二个例子中,如果我们想做同样的事情。 我们必须调用functionCalledEveryOnceSoOften(int, vector3)
因为函数不能直接访问变量。
在统一中,通常情况是函数需要使用与另一个函数相同的值,尽管它们可能并不总是在链中被调用。 为了适应你的第二个例子,我们必须在我们的函数中添加if
语句来过滤掉它。
但是,在您的第一个示例中,我们可以毫无问题地使用这些变量。 这是通常建议这样做的原因之一。
根据性能,在第二个示例中,变量存储在堆栈中而不是堆中,因为它是在方法的范围内定义的,一旦方法结束执行,该方法将被销毁。 因此变量的内存使用量并不是真正的问题。 重复创建和销毁的开销可能很小,但这应该是微不足道的。
在第一个示例中,您将变量存储在堆上,因为它是在类的范围内定义的,它只会与类一起销毁,并在其实例化时创建。 这意味着内存可能会在更长的时间内使用,但创建/销毁变量不会产生任何开销。 这通常也是微不足道的。
总之,除非您实例化数千个这些对象,快速连续访问变量,否则您很可能不会注意到性能上的很多差异。
最大的区别很可能是编写代码的方式。 不论结果好坏。
回收价值类型是否统一有一点
是的,有些数据类型并非全部。
这适用于值类型变量(整数,向量)吗?
不 。
它取决于变量类型。
这不适用于int
, double
, float
, bool
, Vector3
和Vector2
以及其他类似的数据类型。 它甚至不适用于string
因为已经, string
不能在C#中重用。 strings
是不可变的。
事实上,从局部变量中使用int
,假设在while
循环中比使用声明为global的int
更快。
*何时应声明变量并重复使用或用您自己的话说,在Unity *中回收或重复使用变量的示例。
数组 :
如果函数包含数组并且通常调用该函数。
void functionCalledVeryOften() { float[] playerLives = new float[5]; //This is bad because it allocates memory each time it is called for (int i = 0; i < playerLives.Length; i++) { playerLives[i] = UnityEngine.Random.Range(0f,5f); } }
这每次都会分配内存,可以通过使数组全局并在函数外部初始化一次来解决。 您可以创建一个简单的函数,将数组中的数据重置为0。
float[] playerLives = new float[5]; void functionCalledVeryOften() { for (int i = 0; i < playerLives.Length; i++) { playerLives[i] = UnityEngine.Random.Range(0f,5f); } }
创建新对象 :
创建新对象会占用资源,并可能导致移动设备出现问题。 这取决于您执行此操作的频率。
下面的代码创建了一个GameObject(子弹)然后将Rigidbody
连接到它然后射击它。这种情况发生在每一帧,而空格键被按下并最终在10
秒后摧毁子弹。
void functionCalledVeryOften() { if (Input.GetKey(KeyCode.Space)) { //Create new Bullet each time GameObject myObject = new GameObject("bullet"); Rigidbody bullet = myObject.AddComponent() as Rigidbody; //Shoot Bullet bullet.velocity = transform.forward * 50; Destroy(myObject); } }
上面的代码很糟糕,因为每次创建新的GameObject时都会分配内存,当GameObject被销毁时,它也会触发垃圾收集器。 这可能会减慢并导致游戏中的打嗝。
上述代码的解决方案是对象池。 您可以在此处了解更多信息: Unity的对象池教程
使用全局变量对此进行简单修复的示例 :
List reUsableBullets; int toUseIndex = 0; void Start() { intitOnce(); } //Call this function once to create bullets void intitOnce() { reUsableBullets = new List (); //Create 20 bullets then store the reference to a global variable for re-usal for (int i = 0; i < 20; i++) { reUsableBullets[i] = new GameObject("bullet"); reUsableBullets[i].AddComponent(); reUsableBullets[i].SetActive(false); } } void functionCalledVeryOften() { if (Input.GetKey(KeyCode.Space)) { //Re-use old bullet reUsableBullets[toUseIndex].SetActive(true); Rigidbody tempRgb = reUsableBullets[toUseIndex].GetComponent (); tempRgb.velocity = transform.forward * 50; toUseIndex++; //reset counter if (toUseIndex == reUsableBullets.Count - 1) { toUseIndex = 0; } } }
所以基本上,你在游戏开始之前在函数内创建一个Object,然后将引用存储在一个全局变量中。 然后,您将重新使用在函数中创建的对象,因为它的引用保存在全局变量中。
实例化 :
Instantiate函数用于创建预制件的副本。 下面的代码将实例化一颗子弹,然后每按一次射击它,同时按住空格键,最后在10
秒后将其摧毁。
public GameObject bulletPrefab; void functionCalledVeryOften() { if (Input.GetKey(KeyCode.Space)) { //Create new Bullet each time Rigidbody bullet = Instantiate(bulletPrefab, new Vector3(0, 0, 0), Quaternion.identity) as Rigidbody; //Shoot Bullet bullet.velocity = transform.forward * 50; Destroy(myObject,10f); } }
上面的代码很糟糕,因为它根据子弹预制件附加的组件数量以及游戏对象下面的子游戏数量来分配内存。 解决方案也使用对象池 。 在函数中实例化GameObject,将引用存储在全局变量中,然后重用它们。 解决方案与上述解决方案相同。
总之,您问题中的示例代码不适用于此 。
您可以在此处了解有关Unity中内存管理的更多信息。