VR射击子弹
管理场景中大量的频繁使用的物体: 子弹的生成与销毁,改为激活和隐藏
1.子弹挂载脚本
public class Pool1Item : MonoBehaviour
{
public string PoolName; //对象池的名称
public bool IsInPool; //是否再池中
void OnTriggerEnter(Collider c) //碰撞到墙上,入池隐藏
{
Pool1Manager.GetInstance().GetPoolByName (PoolName).Enqueue (this);
}
void OnDisable()
{
Rigidbody r = GetComponent<Rigidbody> ();
if (r != null)
r.velocity = Vector3.zero;
}
}
2.对象池类:队列存储所有子对象
public class Pool1 : MonoBehaviour
{
//池的名称
private string poolName;
//队列
private Queue<Pool1Item> pools;
//池中的对象
private GameObject prefab; //预制体,子弹或者怪物
//上限
private int maxCount;
//初始化
public void Init(string _name, GameObject _prefab, int _maxCount, int initCount)
{
pools = new Queue<Pool1Item>();
poolName = _name;
prefab = _prefab;
maxCount = _maxCount;
for (int i = 0; i < initCount; i++) //提前添加一些对象
{
Enqueue(CreateNewItem());
}
}
//出池
public Pool1Item Dequeue() //得到池中一个子弹对象
{
if (pools == null)
pools = new Queue<Pool1Item>(); //安全操作
if (pools.Count <= 0) //对象池中没有对象
pools.Enqueue(CreateNewItem()); //创建新对象添加到池中,调用本类中的方法
Pool1Item item = pools.Dequeue(); //有对象后可以出池了
item.IsInPool = false;
item.gameObject.SetActive(true);
Debug.Log(item.name);
return (item);
}
//入池
public void Enqueue(Pool1Item item)
{
if (pools == null)
{ pools = new Queue<Pool1Item>(); }
if (pools.Count >= maxCount)
{
Destroy(item.gameObject);
return;
}
item.IsInPool = true;
item.gameObject.SetActive(false);
pools.Enqueue(item);
}
//创建新的池对象
private Pool1Item CreateNewItem()
{
GameObject go = Instantiate(prefab); //生成实例对象
go.transform.SetParent(transform); //设置父物体(当前池)
go.SetActive(false); //隐藏
Pool1Item item = go.AddComponent<Pool1Item>();
item.PoolName = poolName;
item.IsInPool = true;
return item;
}
}
3.对象池管理类
public class Pool1Manager : SingleTon<Pool1Manager>
{
private Dictionary <string ,Pool1> poolDic = new Dictionary<string, Pool1>();
//创建新的对象池
public Pool1 CreateNewPool(string poolName,GameObject prefab)
{
if (poolDic.ContainsKey (poolName))
{
Debug.LogFormat ("对象池创建失败:{0}已存在", poolName);
return null;
}
GameObject go = new GameObject (); ..//创建新对象池
go.name = poolName;
Pool1 pool = go.AddComponent<Pool1> ();
pool.Init (poolName, prefab, 10, 3);
poolDic.Add (poolName, pool); //将池存储起来
return pool;
}
//获取对象池,根据名称
public Pool1 GetPoolByName(string poolName)
{
if (!poolDic.ContainsKey (poolName))
{
Debug.LogFormat ("对象池获取失败:{0}不存在", poolName);
return null;
}
return poolDic [poolName];
}
//销毁对象池
public void DestoryPool(string poolName)
{
Pool1 pool = GetPoolByName (poolName);
if (pool == null)
return;
poolDic.Remove (poolName);
Destroy (pool.gameObject);
}
}
4.调用
public class Weapon1Ctrl : MonoBehaviour
{
//获取VR组件
SteamVR_TrackedObject trackedObj;
private GameObject bullet;
private const string poolName = "NormalBullet1";
public Transform gunpos;
private Pool1 pool;
private AudioSource audio;
void Start()
{
bullet = Resources.Load("Bullet1") as GameObject;
pool = Pool1Manager.GetInstance().CreateNewItem(poolName, bullet);
//获取vr手柄上的组件
trackedObj = this.GetComponentInParent<SteamVR_TrackedObject>();
//trackedObj = this.transform.parent.GetComponent<SteamVR_TrackedObject>();
audio = GameObject.Find("Sound").GetComponent<AudioSource>();
}
void Update()
{
//获取vr手柄输入
var dev = SteamVR_Controller.Input((int)trackedObj.index);
//按下扳机键
if (dev.GetPress(SteamVR_Controller.ButtonMask.Trigger))
{
Fire();
audio.Play();
}
}
void Fire()
{
Pool1Item item = pool.Dequeue(); //出池
//注意谁发射子弹,就将子弹的层级设置为一样
item.gameObject.layer = gameObject.layer;
item.transform.position = gunpos.position;
item.transform.rotation = gunpos.rotation;
item.gameObject.GetComponent<Rigidbody>().AddForce(gunpos.transform.forward * 50, ForceMode.Impulse);
}
}