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);
        }
    }
}
上一篇下一篇

猜你喜欢

热点阅读