2014-06-27 105 views
3

我在將對象池腳本從UnityScript轉換爲C#時遇到了麻煩,因爲我在這裏得到了很多很好的幫助。現在我遇到了一個問題,試圖從池中獲取遊戲對象。我有三個腳本互相交互,所以我不太確定哪裏出了問題。下面是這兩個腳本對象池,我相信都是平方路程,他們沒有給出任何錯誤:在Unity中從對象池中獲取遊戲對象時遇到困難

public class EasyObjectPool : MonoBehaviour { 
    [System.Serializable] 
    public class PoolInfo{ 
     [SerializeField] 
     public string poolName; 
     public GameObject prefab; 
     public int poolSize; 
     public bool canGrowPoolSize = true; 

} 

[System.Serializable] 
public class Pool{ 

    public List<PoolObject> list = new List<PoolObject>(); 
    public bool canGrowPoolSize; 

    public void Add (PoolObject poolObject){ 
     list.Add(poolObject); 
    } 

    public int Count(){ 
     return list.Count; 
    } 


    public PoolObject ObjectAt (int index ){ 

     PoolObject result = null; 
     if(index < list.Count) { 
      result = list[index]; 
     } 

     return result; 

    } 
} 
static public EasyObjectPool instance ; 

[SerializeField] 
PoolInfo[] poolInfo = null; 

private Dictionary<string, Pool> poolDictionary = new Dictionary<string, Pool>(); 


void Start() { 

    instance = this; 

    CheckForDuplicatePoolNames(); 

    CreatePools(); 

} 

private void CheckForDuplicatePoolNames() { 

    for (int index = 0; index < poolInfo.Length; index++) { 
     string poolName= poolInfo[index].poolName; 
     if(poolName.Length == 0) { 
      Debug.LogError(string.Format("Pool {0} does not have a name!",index)); 
     } 
     for (int internalIndex = index + 1; internalIndex < poolInfo.Length; internalIndex++) { 
      if(poolName == poolInfo[internalIndex].poolName) { 
       Debug.LogError(string.Format("Pool {0} & {1} have the same name. Assign different names.", index, internalIndex)); 
      } 
     } 
    } 
} 

private void CreatePools() { 

    foreach(PoolInfo currentPoolInfo in poolInfo){ 

     Pool pool = new Pool(); 
     pool.canGrowPoolSize = currentPoolInfo.canGrowPoolSize; 

     for(int index = 0; index < currentPoolInfo.poolSize; index++) { 
      //instantiate 
      GameObject go = Instantiate(currentPoolInfo.prefab) as GameObject; 
      PoolObject poolObject = go.GetComponent<PoolObject>(); 
      if(poolObject == null) { 
       Debug.LogError("Prefab must have PoolObject script attached!: " + currentPoolInfo.poolName); 
      } else { 
       //set state 
       poolObject.ReturnToPool(); 
       //add to pool 
       pool.Add(poolObject); 
      } 
     } 

     Debug.Log("Adding pool for: " + currentPoolInfo.poolName); 
     poolDictionary[currentPoolInfo.poolName] = pool; 

    } 
} 

public PoolObject GetObjectFromPool (string poolName ){ 
    PoolObject poolObject = null; 

    if(poolDictionary.ContainsKey(poolName)) { 
     Pool pool = poolDictionary[poolName]; 

     //get the available object 
     for (int index = 0; index < pool.Count(); index++) { 
      PoolObject currentObject = pool.ObjectAt(index); 

      if(currentObject.AvailableForReuse()) { 
       //found an available object in pool 
       poolObject = currentObject; 
       break; 
      } 
     } 


     if(poolObject == null) { 
      if(pool.canGrowPoolSize) { 
       Debug.Log("Increasing pool size by 1: " + poolName); 

       foreach (PoolInfo currentPoolInfo in poolInfo) {  

        if(poolName == currentPoolInfo.poolName) { 

         GameObject go = Instantiate(currentPoolInfo.prefab) as GameObject; 
         poolObject = go.GetComponent<PoolObject>(); 
         //set state 
         poolObject.ReturnToPool(); 
         //add to pool 
         pool.Add(poolObject); 

         break; 

        } 
       } 
      } else { 
       Debug.LogWarning("No object available in pool. Consider setting canGrowPoolSize to true.: " + poolName); 
      } 
     } 

    } else { 
     Debug.LogError("Invalid pool name specified: " + poolName); 
    } 

    return poolObject; 
} 

} 

和:

public class PoolObject : MonoBehaviour { 

[HideInInspector] 
public bool availableForReuse = true; 


void Activate() { 

    availableForReuse = false; 
    gameObject.SetActive(true); 

} 


public void ReturnToPool() { 

    gameObject.SetActive(false); 
    availableForReuse = true; 


} 

public bool AvailableForReuse() { 
    //true when isAvailableForReuse & inactive in hierarchy 

    return availableForReuse && (gameObject.activeInHierarchy == false); 



} 
} 

原來UnityScript表示檢索對象從這個說法池:

var poolObject : PoolObject = EasyObjectPool.instance.GetObjectFromPool(poolName); 

這是我試圖做的是,在我的拍攝腳本它試圖從池火子彈預製:

public class ShootScript : MonoBehaviour { 

public PoolObject poolObject; 

private Transform myTransform; 

private Transform cameraTransform; 

private Vector3 launchPosition = new Vector3(); 

public float fireRate = 0.2f; 

public float nextFire = 0; 

// Use this for initialization 
void Start() { 

    myTransform = transform; 

    cameraTransform = myTransform.FindChild("BulletSpawn"); 

} 


void Update() { 

    poolObject = EasyObjectPool.instance.GetObjectFromPool<poolName>(); 

    if(Input.GetButton("Fire1") && Time.time > nextFire){ 

     nextFire = Time.time + fireRate; 

     launchPosition = cameraTransform.TransformPoint(0, 0, 0.2f); 

     poolObject.Activate(); 

     poolObject.transform.position = launchPosition; 
     poolObject.transform.rotation = Quaternion.Euler(cameraTransform.eulerAngles.x + 90, myTransform.eulerAngles.y, 0); 

    } 

} 
} 

我拍的腳本是給我兩個錯誤:

1類型或命名空間名稱「POOLNAME」找不到。你是否缺少using指令或程序集引用?

對於行:

poolObject = EasyObjectPool.instance.GetObjectFromPool<poolName>(); 

2. 'PoolObject.Activate()' 是不可訪問的,因爲它保護級別

對於行:

poolObject.Activate(); 

沒有符合我錯誤翻譯了UnityScript,還是錯過了其他的東西?任何輸入,非常感謝

回答

0

你寫內<事情>應該是一個類名像PoolObject如果函數是通用的,它不是。因此,要解決這個問題,你只需要改變

poolObject = EasyObjectPool.instance.GetObjectFromPool<poolName>(); 

string poolName = "thePoolNameYouWant"; 
poolObject = EasyObjectPool.instance.GetObjectFromPool(poolName); 

功能在默認情況下私人所以要解決「無法訪問由於其保護級別」的錯誤,你需要通過使函數public改變這種

void Activate() { 
    availableForReuse = false; 
    gameObject.SetActive(true); 
} 

這個

public void Activate() { 
    availableForReuse = false; 
    gameObject.SetActive(true); 
} 
+0

感謝您的幫助。更改poolObject行給了我更多的錯誤: – user3776884

+0

名稱'poolName'在當前上下文中不存在 – user3776884

+0

'EasyObjectPool.GetObjectFromPool(string)'的最佳重載方法匹配有一些無效參數 – user3776884

1

我認爲你的對象池被錯誤地編程。當你有像CheckForDuplicatePoolNames()這樣的方法時,問問你自己是否需要像字典這樣的不同集合。

保持簡單。 我最近實施了一個,我測試了。它工作得很好。

using UnityEngine; 
using System.Collections; 
using System.Collections.Generic; 

[System.Serializable] 
public class PoolObject{ 
    public GameObject prefab; 
    public int startNum; 
    public int allocateNum; 
    public Transform anchor; 
} 

public class ObjectPool<T> : MonoBehaviour where T:Component{ 
    public PoolObject[] poolObjects; 
    public bool ______________; 
    public Dictionary<string,Queue<T>> pool = new Dictionary<string, Queue<T>>(); 
    public Dictionary<string, List<T>> spawned = new Dictionary<string, List<T>>(); 
    public Transform anchor; 


    public void Init(){ 
     InitPool(); 
     StartAllocate(); 
    } 


    public T Spawn(string type){ 
     if (pool [type].Count == 0) { 
      int i = FindPrefabPosition(type); 
      if(poolObjects[i].allocateNum == 0) 
       return null; 
      Allocate(poolObjects[i], poolObjects[i].allocateNum); 
     } 
     T t = pool [type].Dequeue(); 
     spawned[type].Add (t); 
     t.gameObject.SetActive (true); 
     return t; 
    } 


    public void Recycle(T t){ 
     if (spawned [t.name].Remove (t)) { 
      pool[t.name].Enqueue(t); 
      t.gameObject.SetActive(false); 
     } 
    } 


    private void Allocate(PoolObject po, int number){ 
     for (int i=0; i<number; i++) { 
      GameObject go = Instantiate (po.prefab) as GameObject; 
      go.name = po.prefab.name; 
      go.transform.parent = po.anchor != null? po.anchor : anchor; 
      T t = go.GetComponent<T>(); 
      pool[t.name].Enqueue(t); 
      t.gameObject.SetActive(false); 
     } 
    } 

    private int FindPrefabPosition(string type){ 
     int position = 0; 
     while (poolObjects[position].prefab.name != type) { 
      position++;  
     } 
     return position; 
    } 

    void InitPool(){ 
     if(anchor == null) 
      anchor = new GameObject("AnchorPool").transform; 
     for (int i =0; i<poolObjects.Length; i++) { 
      T t = poolObjects[i].prefab.GetComponent<T>(); 
      t.name = poolObjects[i].prefab.name; 
      pool[t.name] = new Queue<T>(); 
      spawned[t.name] = new List<T>(); 
     } 
    } 

    void StartAllocate(){ 
     for (int i=0; i<poolObjects.Length; i++) { 
       Allocate(poolObjects[i], poolObjects[i].startNum); 
     } 
    } 
} 

實施例:

public class CoinsPool : ObjectPool<CoinScript>{} 

在統一檢查員配置硬幣預製的startNum和allocateNum。

某處:

void Awake(){ 
    coinsPool = GetComponent<CoinsPool>(); 
    coinsPool.Init(); 
} 

CoinScript cs = coinsPool.Spawn("Coin"); //Coin is the name of the coin prefab. 

後來

coinsPool.Recycle(cs); 
相關問題