Version: 6000.3
语言: 中文
参考类型管理
优化阵列

使用具有可重用内存的编码模式

避免在托管堆上进行不必要的分配的一种方法是采用允许您重用部分内存分配的编码模式。以下示例概述了有助于提高应用程序性能的方法。

使用可重用对象池

在很多情况下,您可以减少应用程序创建和销毁对象的次数,以避免生成垃圾。游戏中有某些类型的对象,例如射弹,即使同时只有少数物体在游戏中,它们也可能会一遍又一遍地出现。在这种情况下,您可以重用这些对象,而不是销毁旧的对象并用新对象替换它们。

例如,从预制件:一种资产类型,允许您存储包含组件和属性的游戏对象。预制件充当模板,你可以从中在场景中创建新的对象实例。更多信息
请参阅术语表
每次被解雇时。相反,你可以计算游戏过程中可能同时存在的最大射弹数量,并在游戏首次进入游戏时实例化正确大小的对象数组场景场景包含游戏的环境和菜单。将每个唯一的场景文件视为一个独特的关卡。在每个场景中,你放置你的环境、障碍物和装饰品,基本上是将你的游戏设计和构建成碎片。更多信息
请参阅术语表
.为此,请执行以下作:

  1. 从所有射弹开始游戏对象Unity 场景中的基本对象,可以表示角色、道具、风景、相机、航路点等。游戏对象的功能由附加到它的组件定义。更多信息
    请参阅术语表
    设置为 inactive。
  2. 发射射弹时,搜索数组以找到数组中的第一个非活动射弹,将其移动到所需位置并将游戏对象设置为活动。
  3. 当射弹被销毁时,再次将游戏对象设置为非活动状态。

ObjectPoolclass 提供了这种可重用对象池技术的实现,这是在应用程序中实现对象池的最简单方法。

但是,如果您使用的 Unity 版本不包含ObjectPoolAPI,或者你想了解如何实现自定义对象池,以下代码显示了基于堆栈的对象池的简单实现:

using System.Collections.Generic;
using UnityEngine;

public class ExampleObjectPool : MonoBehaviour {

   public GameObject PrefabToPool;
   public int MaxPoolSize = 10;
  
   private Stack<GameObject> inactiveObjects = new Stack<GameObject>();
  
   void Start() {
       if (PrefabToPool != null) {
           for (int i = 0; i < MaxPoolSize; ++i) {
               var newObj = Instantiate(PrefabToPool);
               newObj.SetActive(false);
               inactiveObjects.Push(newObj);
           }
       }
   }

   public GameObject GetObjectFromPool() {
       while (inactiveObjects.Count > 0) {
           var obj = inactiveObjects.Pop();
          
           if (obj != null) {
               obj.SetActive(true);
               return obj;
           }
           else {
               Debug.LogWarning("Found a null object in the pool. Has some code outside the pool destroyed it?");
           }
       }
      
       Debug.LogError("All pooled objects are already in use or have been destroyed");
       return null;
   }
  
   public void ReturnObjectToPool(GameObject objectToDeactivate) {
       if (objectToDeactivate != null) {
           objectToDeactivate.SetActive(false);
           inactiveObjects.Push(objectToDeactivate);
       }
   }
}

重用 System.Collection 中的数组和类

当您使用System.Collection命名空间(例如,Lists 或 Dictionaries),重用或池化分配的集合或数组是有效的。集合类公开Clear方法,该方法删除集合的值,但不会释放分配给集合的内存。

如果要为复杂计算分配临时帮助程序集合,这将非常有用。以下代码示例演示了这一点:

// Bad C# script example. This Update method allocates a new `List` every frame.
void Update() {

    List<float> nearestNeighbors = new List<float>();

    findDistancesToNearestNeighbors(nearestNeighbors);

    nearestNeighbors.Sort();

    // … use the sorted list somehow …
}

此示例代码分配了nearestNeighbors List每帧一次,以收集一组数据点。

你可以举起这个List出方法并进入包含类,这样您的代码就不需要分配一个新的List每架:

// Good C# script example. This method re-uses the same List every frame.
List<float> m_NearestNeighbors = new List<float>();

void Update() {

    m_NearestNeighbors.Clear();

    findDistancesToNearestNeighbors(NearestNeighbors);

    m_NearestNeighbors.Sort();

    // … use the sorted list somehow …
}

此示例代码保留并重用List实例跨多个帧的内存。代码仅在List需要扩展。

其他资源

参考类型管理
优化阵列