Unity中,简易的光效播放系统
2022-05-27 本文已影响0人
全新的饭
使用方法
EffectSys.Instance.CreateEffect(光效模板(如预制体), 位置, 光效持续时间(可不填));
EffectSys.Instance.CreateEffect(光效模板(如预制体), 父节点, 光效持续时间(可不填));
若不填光效持续时间,则CreateEffect方法会返回生成的光效:由外部自行控制光效的销毁。
相关代码
EffectSys.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EffectSys : MonoBehaviour
{
private static EffectSys _instance;
public static EffectSys Instance
{
get
{
if (_instance == null)
{
GameObject go = new GameObject(nameof(EffectSys));
_instance = go.AddComponent<EffectSys>();
var parentGo = GameObject.Find("Singleton");
if (parentGo == null)
{
parentGo = new GameObject("Singleton");
UnityEngine.Object.DontDestroyOnLoad(parentGo);
}
go.transform.SetParent(parentGo.transform);
}
return _instance;
}
}
public void Destroy()
{
Destroy(Instance.gameObject);
_instance = null;
}
private void DelayCall(float delayTime, Action action)
{
StartCoroutine(DelayCallCoroutine());
IEnumerator DelayCallCoroutine()
{
yield return new WaitForSeconds(delayTime);
action?.Invoke();
}
}
#region 创建和销毁光效
// 在指定位置创建一个特效,经过指定时间后消失
public void CreateEffect(GameObject templateGo, Vector3 pos, float lifeTime)
{
CreateEffect(templateGo, pos, transform, lifeTime);
}
// 在指定Transform下创建一个特效,经过指定时间后消失
public void CreateEffect(GameObject templateGo, Transform parent, float lifeTime)
{
CreateEffect(templateGo, parent.transform.position, parent, lifeTime);
}
// 在指定位置创建一个特效,外部控制其消失
public GameObject CreateEffect(GameObject templateGo, Vector3 pos)
{
return CreateEffect(templateGo, pos, transform, -1);
}
// 在指定Transform下创建一个特效,外部控制其消失
public GameObject CreateEffect(GameObject templateGo, Transform parent)
{
return CreateEffect(templateGo, parent.transform.position, parent, -1);
}
private GameObject CreateEffect(GameObject templateGo, Vector3 pos, Transform parent, float lifeTime)
{
var go = GOPool.Instance.GetInstance(templateGo);
go.transform.position = pos;
go.transform.SetParent(parent);
go.SetActive(true);
if (lifeTime > 0)
{
DelayCall(lifeTime, () => DestroyEffect(templateGo, go));
}
return go;
}
// 销毁光效
public void DestroyEffect(GameObject templateGo, GameObject go)
{
GOPool.Instance.RecycleInstance(templateGo, go);
}
#endregion
}
GOPool.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 外界可以传入GO模板,获取GO实例
/// </summary>
public class GOPool : MonoBehaviour
{
private static GOPool _instance;
private Dictionary<GameObject, GOPoolObj> _goPoolDict;
public static GOPool Instance
{
get
{
if (_instance == null)
{
GameObject go = new GameObject(nameof(GOPool));
_instance = go.AddComponent<GOPool>();
_instance._goPoolDict = new Dictionary<GameObject, GOPoolObj>();
var parentGo = GameObject.Find("Singleton");
if (parentGo == null)
{
parentGo = new GameObject("Singleton");
UnityEngine.Object.DontDestroyOnLoad(parentGo);
}
go.transform.SetParent(parentGo.transform);
}
return _instance;
}
}
public void Destroy()
{
foreach (var value in _goPoolDict.Values)
{
value.Destroy();
}
_goPoolDict.Clear();
_goPoolDict = null;
Destroy(Instance.gameObject);
_instance = null;
}
public GameObject GetInstance(GameObject goTemplate)
{
EnsureDictHasKey(goTemplate);
return _goPoolDict[goTemplate].GetInstance();
}
public void RecycleInstance(GameObject goTemplate, GameObject go)
{
EnsureDictHasKey(goTemplate);
_goPoolDict[goTemplate].RecycleInstance(go);
}
private void EnsureDictHasKey(GameObject key)
{
if (!_goPoolDict.ContainsKey(key))
{
var go = new GameObject(key.name);
go.transform.SetParent(transform);
var goPoolObj = new GOPoolObj(go, key);
_goPoolDict.Add(key, goPoolObj);
}
}
private class GOPoolObj
{
private readonly GameObject MyGo;
private readonly GameObject GOTemplate;
private List<GameObject> _gos;
public GOPoolObj(GameObject myGo, GameObject goTemplate)
{
MyGo = myGo;
GOTemplate = goTemplate;
_gos = new List<GameObject>();
}
public void Destroy()
{
_gos.Clear();
_gos = null;
GameObject.Destroy(MyGo);
}
public GameObject GetInstance()
{
if (_gos.Count == 0)
{
var instance = Instantiate(GOTemplate, MyGo.transform);
instance.name = GOTemplate.name + "_0";
_gos.Add(instance);
}
var go = _gos[0];
_gos.RemoveAt(0);
return go;
}
public void RecycleInstance(GameObject go)
{
if (MyGo == null)
{
return;
}
go.name = GOTemplate.name + "_" + _gos.Count;
go.transform.SetParent(MyGo.transform);
go.transform.localPosition = Vector3.zero;
go.transform.localRotation = Quaternion.identity;
go.transform.localScale = Vector3.one;
go.SetActive(false);
_gos.Add(go);
}
}
}