U3d插件——Swarm Object Manager分析(三)SwarmItemManager(未完)

SwarmItemManager 才是重中之重   前面和后面的东西都是小菜一碟 -,-

public class SwarmItemManager : MonoBehaviour
{

  //首先,他通过这个列表类
    protected class PrefabItemLists
    {
        public LinkedList<SwarmItem> activeItems;
       
        public Stack<SwarmItem> inactiveItems;
       
        public int itemCount; 
       
        public float inactivePruneTimeLeft;   栈中存在的时间
       
        public PrefabItemLists ()
        {
            activeItems = new LinkedList<SwarmItem>();
            inactiveItems = new Stack<SwarmItem>();
        }
    }
   
    [Serializable]
    public class PrefabItem
    {
        public GameObject prefab;
       
        public int maxItemCount = 0;  //最大的个数
       
        public float inactiveThreshold = 1.0f;   //门槛? 无效的项目数,如果超过这一比例,则定时器立刻触发,默认是1.0,则所有都用完才会修剪  范围是0-1

        public float inactivePruneTimer = 0.0f;    //在垃圾栈中的板凳时间    还没被删除的存在时间

        public float inactivePrunePercentage = 0.0f; //垃圾栈中所占的项目百分比
    }
    

    private SwarmItem _item;
    private GameObject _go;
    private Transform _transform;
    private Transform _activeParentTransform;
    private Transform _inactiveParentTransform;


    private int _itemCount;

    protected PrefabItemLists [] _prefabItemLists;、、//拿到每一个list的数量
   
    public bool debugEvents;
   
    public PrefabItem [] itemPrefabs;
   
    public virtual void Initialize()
    {
        if (itemPrefabs.Length == 0)  //必须要有list的项目
        {
            Debug.Log("WARNING! No Item Prefabs exists for " + gameObject.name + " -- Errors will occur.");
        }

        foreach (PrefabItem itemPrefab in itemPrefabs)
        {
            itemPrefab.inactiveThreshold = Mathf.Clamp01(itemPrefab.inactiveThreshold);
            itemPrefab.inactivePrunePercentage = Mathf.Clamp01(itemPrefab.inactivePrunePercentage);
        }
       
        _prefabItemLists = new PrefabItemLists[itemPrefabs.Length];
        for (int i=0; i<_prefabItemLists.Length; i++)
        {
            _prefabItemLists[i] = new PrefabItemLists();
            _prefabItemLists[i].itemCount = 0;
            _prefabItemLists[i].inactivePruneTimeLeft = 0;
        }
       
        _go = new GameObject("Active Items");
        _activeParentTransform = _go.transform;
        _activeParentTransform.parent = this.transform;
        _activeParentTransform.localPosition = Vector3.zero;
        _activeParentTransform.localRotation = Quaternion.identity;
        _activeParentTransform.localScale = Vector3.one;

        _go = new GameObject("Inactive Items");
        _inactiveParentTransform = _go.transform;
        _inactiveParentTransform.parent = this.transform;
        _inactiveParentTransform.localPosition = Vector3.zero;
        _inactiveParentTransform.localRotation = Quaternion.identity;
        _inactiveParentTransform.localScale = Vector3.one;
    }
   
    //生成一个新活动项目
    public virtual SwarmItem ActivateItem()
    {
        return ActivateItem(0);
    }

    ///生成一个新活动项目,总的来说较为复杂orz
    public virtual SwarmItem ActivateItem(int itemPrefabIndex)
    {
        if (_prefabItemLists[itemPrefabIndex].activeItems.Count == itemPrefabs[itemPrefabIndex].maxItemCount && itemPrefabs[itemPrefabIndex].maxItemCount > 0)
        {
            if (debugEvents)
                Debug.Log("Could not activate item because the count [" + _prefabItemLists[itemPrefabIndex].activeItems.Count + "] is at the maximum number for this item type at frame: " + Time.frameCount);
            return null;
        }
        
        if (_prefabItemLists[itemPrefabIndex].inactiveItems.Count > 0)
        {
            // there is an inactive item so we recycle it
            // pop off the inactive stack
            _item = _prefabItemLists[itemPrefabIndex].inactiveItems.Pop();
            
            // queue to the end of the active list
            _prefabItemLists[itemPrefabIndex].activeItems.AddLast(_item);
            
            if (debugEvents)
                Debug.Log("Recycled item " + _item.name + " at frame: " + Time.frameCount);
        }
        else
        {
            // no inactive item availble, so create a new one
            
            // instantiate item
            _item = InstantiateItem(itemPrefabIndex);
            
            // queue to the end of the active list
            _prefabItemLists[itemPrefabIndex].activeItems.AddLast(_item);
            
            if (debugEvents)
                Debug.Log("Instantiated a new item " + _go.name + " at frame: " + Time.frameCount);
        }
        
        // move the item to active parent transform.
        // this is mainly just for visual reference in the editor
        SetItemParentTransform(_item, _activeParentTransform);
        
        // set the state to active
        _item.State = SwarmItem.STATE.Active;
        
        // if the prune timer is runnning
        if (_prefabItemLists[itemPrefabIndex].inactivePruneTimeLeft > 0)
        {        
            // if the inactive item count dropped below the threshold
            if (((float)_prefabItemLists[itemPrefabIndex].inactiveItems.Count / (float)_prefabItemLists[itemPrefabIndex].itemCount) < itemPrefabs[itemPrefabIndex].inactiveThreshold)
            {
                if (debugEvents)
                    Debug.Log("Dropped below inactive threshold [" + (itemPrefabs[itemPrefabIndex].inactiveThreshold * 100) + "%] for " + itemPrefabs[itemPrefabIndex].prefab.name + " list before timer expired. Stopping prune timer at frame: " + Time.frameCount);
                
                // turn the prune timer off
                _prefabItemLists[itemPrefabIndex].inactivePruneTimeLeft = 0;
            }
        }
        
        return _item;
    }
   
    /// 把一个 SwarmItem从 激活列表转移到不激活的列表,并改变父对象,超时和超门槛百分比都会白消掉
    public virtual void DeactiveItem(SwarmItem item)
    {
        // remove from the active linked list
        _prefabItemLists[item.PrefabIndex].activeItems.Remove(item);
        // push onto the inactive stack
        _prefabItemLists[item.PrefabIndex].inactiveItems.Push(item);
       
        SetItemParentTransform(item, _inactiveParentTransform);
        
        if (debugEvents)
            Debug.Log("Deactivated " + item.name + " at frame: " + Time.frameCount);

        if (_prefabItemLists[item.PrefabIndex].inactivePruneTimeLeft == 0 && itemPrefabs[item.PrefabIndex].inactivePrunePercentage > 0)
        {
            // if the inactive item count exceeds the threshold
            if (((float)(_prefabItemLists[item.PrefabIndex].inactiveItems.Count) / (float)_prefabItemLists[item.PrefabIndex].itemCount) >= itemPrefabs[item.PrefabIndex].inactiveThreshold)
            {
                if (debugEvents)
                    Debug.Log("Inactive threshold [" + (itemPrefabs[item.PrefabIndex].inactiveThreshold * 100) + "%] reached for " + itemPrefabs[item.PrefabIndex].prefab.name + " list. Starting prune timer [" + itemPrefabs[item.PrefabIndex].inactivePruneTimer + " seconds] at frame: " + Time.frameCount);
                
                // if the prune timer is set to expire immediately
                if (itemPrefabs[item.PrefabIndex].inactivePruneTimer == 0)
                {
                    // don't wait for a countdown, just prune immediately
                    PruneList(item.PrefabIndex, itemPrefabs[item.PrefabIndex].inactivePrunePercentage);
                }
                else
                {
                    // turn the prune timer on
                    _prefabItemLists[item.PrefabIndex].inactivePruneTimeLeft = itemPrefabs[item.PrefabIndex].inactivePruneTimer;
                }
            }
        }
    }
   
   //实例化一个项目
    protected virtual SwarmItem InstantiateItem(int itemPrefabIndex)
    {
        SwarmItem item;
        
        // instantiate
        _go = (GameObject)Instantiate(itemPrefabs[itemPrefabIndex].prefab);
        // change the name of the gameobject with an index and take off the 'Clone' postfix
        _go.name = "[" + _itemCount.ToString("0000") + "] " + _go.name.Replace("(Clone)", "");
        
        // get the SwarmItem component from the gameobject
        item = (SwarmItem)_go.GetComponent(typeof(SwarmItem));
        // initialize the SwarmItem
        item.Initialize(this, itemPrefabIndex, debugEvents);
        
        // increase the item count for this prefab
        _prefabItemLists[itemPrefabIndex].itemCount++;
        
        // increment the total item count for this manager
        _itemCount++;
        
        return item;
    }
   
    // 移动项目的父对象物体
    private void SetItemParentTransform(SwarmItem item, Transform parentTransform)
    {
        // reparent this item's transform
        item.ThisTransform.parent = parentTransform;
        
        // reset the position, rotation, and scale to unit values
        item.ThisTransform.localPosition = Vector3.zero;
        item.ThisTransform.localRotation = Quaternion.identity;
        item.ThisTransform.localScale = Vector3.one;
        
        // if the position, rotation, or scale need to be changed after reparenting, do it in the
        // item's OnSetParentTransform method
        item.OnSetParentTransform();
    }
    
  //帧更新
    public virtual void FrameUpdate()
    {
        // iterate through each SwarmItem type
        for (int i=0; i<_prefabItemLists.Length; i++)
        {
            // only bother if the active list has some items
            if (_prefabItemLists[i].activeItems.Count > 0)
            {
                // we don't iterate through the active list using foreach here
                // because there would be errors if the item was killed in its FrameUpdate method.
                // instead we manually move to the next linkedlist node
                
                LinkedListNode<SwarmItem> item;
                LinkedListNode<SwarmItem> nextItem;
                
                item = _prefabItemLists[i].activeItems.First;
                
                // while there are items left to process
                while (item != null)
                {
                    // cache the next item in case this item is killed in its FrameUpdate
                    nextItem = item.Next;
                    
                    // update and move to the next item
                    item.Value.FrameUpdate();
                    item = nextItem;
                }
            }
            
            // if this list has its prune timer turned on
            if (_prefabItemLists[i].inactivePruneTimeLeft > 0)
            {
                // decrement the prune timer
                _prefabItemLists[i].inactivePruneTimeLeft -= Time.deltaTime;
                
                // if the timer has expired
                if (_prefabItemLists[i].inactivePruneTimeLeft <= 0)
                {
                    // prune the list
                    PruneList(i, itemPrefabs[i].inactivePrunePercentage);
                }
            }
        }
    }
   
    /// Removes inactive items from the list after the inactive item count exceeds a threshold and
    /// no new items are activated from the list before the prune timer countdown expires. Alternatively,
    /// you could call this manually to free up memory at any time.

修剪list列表
    public void PruneList(int itemPrefabIndex, float prunePercentage)
    {
        // turn off the prune timer
        _prefabItemLists[itemPrefabIndex].inactivePruneTimeLeft = 0;
        
        // get the number of items to prune based on the prune percentage.
        // the amount is a percentage of the inactive items, not the total item count for this list
        int pruneCount = Mathf.FloorToInt(prunePercentage * (float)_prefabItemLists[itemPrefabIndex].inactiveItems.Count);
        SwarmItem item;
        
        if (debugEvents)
            Debug.Log("Pruning " + pruneCount + " items [" + (itemPrefabs[itemPrefabIndex].inactivePrunePercentage*100) + "% of " + _prefabItemLists[itemPrefabIndex].inactiveItems.Count + "] from inactive " + itemPrefabs[itemPrefabIndex].prefab.name + " list at frame: " + Time.frameCount);
        
        // prune each item
        while (pruneCount > 0)
        {
            // pop an item from the inactive stack
            item = (SwarmItem)_prefabItemLists[itemPrefabIndex].inactiveItems.Pop();
            
            // call the overloaded PreDestroy function to let the inherited objects
            // free any memory
            item.PreDestroy();
            
            if (debugEvents)
                Debug.Log("Destroyed " + item.name + " at frame: " + Time.frameCount);
            
            // destroy the item
            Destroy(item.gameObject);
            item = null;
            
            // decrement this list's item count and the manager's total item count
            _prefabItemLists[itemPrefabIndex].itemCount--;
            _itemCount--;
            
            // move to the next item to prune
            pruneCount--;
        }        
    }
}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值