为什么我的障碍会在我的对象池中执行此操作?
Why Do My Obstacles Do This In My Object Pooler?
我几乎完成了我的 PickAxe 游戏对象的对象池系统,但我有一个问题需要帮助。
我想弄清楚的是,为什么当第一个镐撞到墙上时我的所有产卵都会重新开始?我怎样才能使镐在撞到墙壁时回到 "pooler" 的位置?
我拍了两张截图,我也会 post 我的代码也在下面。第一个是在生成的第一个镐撞到墙上之前,第二个屏幕截图是在同一个镐撞到墙上之后。
下面是我的一些代码:
此脚本生成我的镐。我 99% 确定我的问题出在我在 CoRoutine 中调用事件函数的地方。我说得对吗?
using UnityEngine;
using System.Collections;
[System.Serializable]
public class Obstacle4 // Pick Axe Obstacle
{
public float SpawnWait; // Time in seconds between next wave of obstacle 4.
public float StartGameWait; // Time in seconds between when the game starts and when the fourth obstacle start spawning.
public float WaveSpawnWait; // Time in seconds between waves when the next wave of obstacle 4 will spawn.
}
public class SpawnPickAxe : MonoBehaviour
{
public GameObject pickAxePrefab;
public Obstacle4 obstacle4_;
void Start ()
{
PickAxePoolManager.instance.CreatePool (pickAxePrefab, 15); //CreatePool is a method in PickAxePoolManager
StartCoroutine (PickAxeSpawner ());
}
IEnumerator PickAxeSpawner ()
{
yield return new WaitForSeconds (obstacle4_.StartGameWait);
while (true)
{
for (int i = 0; i < 5; i++)
{
Vector3 newSpawnPosition = new Vector3 (Random.Range(-10.0f, 10.0f), 1.2f, 30.0f);
Quaternion newSpawnRotation = Quaternion.Euler (0.0f, -90.0f, 0.0f);
PickAxePoolManager.instance.ReuseObject (pickAxePrefab, newSpawnPosition, newSpawnRotation); //ReuseObject is also a method in PickAxePoolManager
//Instantiate (obstacle4.pickAxe, spawnPosition, spawnRotation);
yield return new WaitForSeconds (obstacle4_.SpawnWait);
ResetByWall.instance.onTriggerEntered += delegate(GameObject obj)
{
PickAxePoolManager.instance.ReuseObject(pickAxePrefab, newSpawnPosition, newSpawnRotation);
};
}
yield return new WaitForSeconds (obstacle4_.WaveSpawnWait);
}
}
}
下面是我的 "ResetByWall" 脚本。这个脚本也很重要,因为它包含 public 事件,让我可以检测到任何与我的墙发生碰撞的碰撞,而我的墙就是触发器。
using System;
using UnityEngine;
using System.Collections;
public class ResetByWall : MonoBehaviour
{
//public bool collided;
//public GameObject pickAxePrefab;
//NOTE:
//Singleton Pattern from lines 12 to 25 //
// ************************************
static ResetByWall _instance; // Reference to the Reset By Wall script
public static ResetByWall instance // This is the accessor
{
get
{
if(_instance == null) // Check to see if _instance is null
{
_instance = FindObjectOfType<ResetByWall>(); //Find the instance in the Reset By Wall script in the currently active scene
}
return _instance;
}
}
public event Action <GameObject> onTriggerEntered;
void OnTriggerEnter(Collider other)
{
if (onTriggerEntered != null) {
onTriggerEntered (other.gameObject);
}
}
}
下面是我的 PoolManager 脚本。您甚至可能不需要查看此脚本,但我还是会 post 以防万一。
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class PickAxePoolManager : MonoBehaviour {
Dictionary<int,Queue<GameObject>> poolDictionary = new Dictionary<int,Queue<GameObject>>();
//NOTE:
//Singleton Pattern used from lines 12 to 25
static PickAxePoolManager _instance; // Reference to the Pool Manager script
public static PickAxePoolManager instance // This is the accessor
{
get
{
if(_instance == null) // Check to see if _instance is null
{
_instance = FindObjectOfType<PickAxePoolManager>(); //Find the instance in the Pool Manager script in the currently active scene
}
return _instance;
}
}
/// <summary>
/// Creates the pool.
/// </summary>
/// <param name="prefab">Prefab.</param>
/// <param name="poolSize">Pool size.</param>
public void CreatePool(GameObject prefab, int poolSize)
{
int poolKey = prefab.GetInstanceID (); // Unique integer for every GameObject
if (!poolDictionary.ContainsKey (poolKey)) //Make sure poolKey is not already in the Dictionary,
//if it's not then we can create the pool
{
poolDictionary.Add(poolKey, new Queue<GameObject>());
for (int i = 0; i < poolSize; i++) //Instantiate the prefabs as dictated by the "poolSize" integer
{
GameObject newObject = Instantiate (prefab) as GameObject; //Instantiate as a GameObject
newObject.SetActive(false); // Don't want it to be visible in the scene yet
poolDictionary [poolKey].Enqueue(newObject); // Add it to our Pool
}
}
}
我解决了这个问题。我将在我的 ResetByWall 脚本中使用它:
void OnTriggerEnter (Collider obstacle)
{
if (obstacle.gameObject.tag == "Pick Axe")
{
obstacle.gameObject.SetActive (false);
}
}
谢谢! :)
我几乎完成了我的 PickAxe 游戏对象的对象池系统,但我有一个问题需要帮助。
我想弄清楚的是,为什么当第一个镐撞到墙上时我的所有产卵都会重新开始?我怎样才能使镐在撞到墙壁时回到 "pooler" 的位置?
我拍了两张截图,我也会 post 我的代码也在下面。第一个是在生成的第一个镐撞到墙上之前,第二个屏幕截图是在同一个镐撞到墙上之后。
下面是我的一些代码:
此脚本生成我的镐。我 99% 确定我的问题出在我在 CoRoutine 中调用事件函数的地方。我说得对吗?
using UnityEngine;
using System.Collections;
[System.Serializable]
public class Obstacle4 // Pick Axe Obstacle
{
public float SpawnWait; // Time in seconds between next wave of obstacle 4.
public float StartGameWait; // Time in seconds between when the game starts and when the fourth obstacle start spawning.
public float WaveSpawnWait; // Time in seconds between waves when the next wave of obstacle 4 will spawn.
}
public class SpawnPickAxe : MonoBehaviour
{
public GameObject pickAxePrefab;
public Obstacle4 obstacle4_;
void Start ()
{
PickAxePoolManager.instance.CreatePool (pickAxePrefab, 15); //CreatePool is a method in PickAxePoolManager
StartCoroutine (PickAxeSpawner ());
}
IEnumerator PickAxeSpawner ()
{
yield return new WaitForSeconds (obstacle4_.StartGameWait);
while (true)
{
for (int i = 0; i < 5; i++)
{
Vector3 newSpawnPosition = new Vector3 (Random.Range(-10.0f, 10.0f), 1.2f, 30.0f);
Quaternion newSpawnRotation = Quaternion.Euler (0.0f, -90.0f, 0.0f);
PickAxePoolManager.instance.ReuseObject (pickAxePrefab, newSpawnPosition, newSpawnRotation); //ReuseObject is also a method in PickAxePoolManager
//Instantiate (obstacle4.pickAxe, spawnPosition, spawnRotation);
yield return new WaitForSeconds (obstacle4_.SpawnWait);
ResetByWall.instance.onTriggerEntered += delegate(GameObject obj)
{
PickAxePoolManager.instance.ReuseObject(pickAxePrefab, newSpawnPosition, newSpawnRotation);
};
}
yield return new WaitForSeconds (obstacle4_.WaveSpawnWait);
}
}
}
下面是我的 "ResetByWall" 脚本。这个脚本也很重要,因为它包含 public 事件,让我可以检测到任何与我的墙发生碰撞的碰撞,而我的墙就是触发器。
using System;
using UnityEngine;
using System.Collections;
public class ResetByWall : MonoBehaviour
{
//public bool collided;
//public GameObject pickAxePrefab;
//NOTE:
//Singleton Pattern from lines 12 to 25 //
// ************************************
static ResetByWall _instance; // Reference to the Reset By Wall script
public static ResetByWall instance // This is the accessor
{
get
{
if(_instance == null) // Check to see if _instance is null
{
_instance = FindObjectOfType<ResetByWall>(); //Find the instance in the Reset By Wall script in the currently active scene
}
return _instance;
}
}
public event Action <GameObject> onTriggerEntered;
void OnTriggerEnter(Collider other)
{
if (onTriggerEntered != null) {
onTriggerEntered (other.gameObject);
}
}
}
下面是我的 PoolManager 脚本。您甚至可能不需要查看此脚本,但我还是会 post 以防万一。
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class PickAxePoolManager : MonoBehaviour {
Dictionary<int,Queue<GameObject>> poolDictionary = new Dictionary<int,Queue<GameObject>>();
//NOTE:
//Singleton Pattern used from lines 12 to 25
static PickAxePoolManager _instance; // Reference to the Pool Manager script
public static PickAxePoolManager instance // This is the accessor
{
get
{
if(_instance == null) // Check to see if _instance is null
{
_instance = FindObjectOfType<PickAxePoolManager>(); //Find the instance in the Pool Manager script in the currently active scene
}
return _instance;
}
}
/// <summary>
/// Creates the pool.
/// </summary>
/// <param name="prefab">Prefab.</param>
/// <param name="poolSize">Pool size.</param>
public void CreatePool(GameObject prefab, int poolSize)
{
int poolKey = prefab.GetInstanceID (); // Unique integer for every GameObject
if (!poolDictionary.ContainsKey (poolKey)) //Make sure poolKey is not already in the Dictionary,
//if it's not then we can create the pool
{
poolDictionary.Add(poolKey, new Queue<GameObject>());
for (int i = 0; i < poolSize; i++) //Instantiate the prefabs as dictated by the "poolSize" integer
{
GameObject newObject = Instantiate (prefab) as GameObject; //Instantiate as a GameObject
newObject.SetActive(false); // Don't want it to be visible in the scene yet
poolDictionary [poolKey].Enqueue(newObject); // Add it to our Pool
}
}
}
我解决了这个问题。我将在我的 ResetByWall 脚本中使用它:
void OnTriggerEnter (Collider obstacle)
{
if (obstacle.gameObject.tag == "Pick Axe")
{
obstacle.gameObject.SetActive (false);
}
}
谢谢! :)