美文网首页
使用Unity自带的对象池实现飘字(如怪物受创时显示伤害数字)

使用Unity自带的对象池实现飘字(如怪物受创时显示伤害数字)

作者: 全新的饭 | 来源:发表于2024-01-08 16:19 被阅读0次

    示意

    如图,每次点击屏幕时,将Player(球)设置到随机位置,并在其位置处显示一个随机类型的飘字。


    飘字示意.gif

    使用

    初始化FloatValueSys时,需传入相应Model。


    FloatValueModel
    FloatValueObj

    可调用FloatValueSys.Show方法显示飘字。

    代码

    FloatValueSys.cs

    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.Pool;
    
    public enum FloatValueType
    {
        None,
        MonsterGetHit,
        MonsterGetCritHit,
        MonsterGetPoisonHit,
    }
    
    [System.Serializable]
    public class FloatValueTypeAndObjTemplate
    {
        [SerializeField]
        private FloatValueType _type;
        public FloatValueType Type => _type;
        [SerializeField]
        private FloatValueObj _template;
        public FloatValueObj Template => _template;
    }
    
    [System.Serializable]
    public class FloatValueModel
    {
        public Transform Parent;
        public FloatValueTypeAndObjTemplate[] ObjAndTemplates;
        public Camera UICam;
    
    }
    public class FloatValueSys
    {
        private FloatValueModel _model;
        private RectTransform _root;
        private Dictionary<FloatValueType, FloatValueObjPool> _poolDict;
    
        public FloatValueSys(FloatValueModel model)
        {
            _model = model;
            CreateRoot();
            InitPoolDict();
    
            void CreateRoot()
            {
                _root = new GameObject(nameof(FloatValueSys)).AddComponent<RectTransform>();
                _root.SetParent(_model.Parent);
                _root.SetAsFirstSibling();
                SetRectTransAsFullScreen(_root);
            }
            void InitPoolDict()
            {
                _poolDict = new Dictionary<FloatValueType, FloatValueObjPool>();
                foreach (var o in _model.ObjAndTemplates)
                {
                    _poolDict.Add(o.Type, new FloatValueObjPool(o.Template, _root));
                }
            }
            void SetRectTransAsFullScreen(RectTransform rectTrans)
            {
                rectTrans.localPosition = Vector3.zero;
                rectTrans.sizeDelta = Vector2.zero;
                rectTrans.localScale = Vector3.one;
                rectTrans.anchorMin = Vector2.zero;
                rectTrans.anchorMax = Vector2.one;
            }
        }
        public void Destroy()
        {
            DestroyPoolDict();
            DestroyRoot();
            _model = null;
    
            void DestroyPoolDict()
            {
                foreach (var v in _poolDict.Values)
                {
                    v.Destroy();
                }
                _poolDict.Clear();
                _poolDict = null;
            }
            void DestroyRoot()
            {
                if (_root != null && _root.gameObject != null)
                {
                    GameObject.Destroy(_root.gameObject);
                    _root = null;
                }
            }
        }
    
        public void Show(FloatValueType type, string content, Vector3 pos)
        {
            var pool = _poolDict[type];
            var obj = pool.Get();
            obj.Init();
            obj.Show(content, ConvertWorldPosToUIPos(pos));
            MonoSys.Instance.DelayCall(pool.LifeSeconds, () =>
            {
                obj.Destroy();
                pool.Release(obj);
            });
    
    
            Vector3 ConvertWorldPosToUIPos(Vector3 worldPos)
            {
                return _model.UICam.ScreenToWorldPoint(Camera.main.WorldToScreenPoint(worldPos));
            }
        }
    
        private class FloatValueObjPool
        {
            private Transform _root;
            private FloatValueObj _template;
            public float LifeSeconds => _template.LifeSeconds;
            private IObjectPool<FloatValueObj> _pool;
    
            public FloatValueObjPool(FloatValueObj template, Transform root)
            {
                _template = template;
                _root = root;
                _pool = new ObjectPool<FloatValueObj>(CreatePooledItem, OnTakeFromPool, OnReturnedToPool, OnDestroyPoolObject);
            }
            public void Destroy()
            {
                _pool.Clear();
                _pool = null;
                _root = null;
                _template = null;
            }
            public FloatValueObj Get()
            {
                return _pool.Get();
            }
            public void Release(FloatValueObj obj)
            {
                _pool.Release(obj);
            }
    
            private FloatValueObj CreatePooledItem()
            {
                var obj = GameObject.Instantiate(_template.gameObject).GetComponent<FloatValueObj>();
                obj.transform.SetParent(_root);
                obj.transform.localScale = Vector3.one;
                return obj;
            }
            private void OnReturnedToPool(FloatValueObj obj)
            {
                obj.gameObject.SetActive(false);
            }
            private void OnTakeFromPool(FloatValueObj obj)
            { }
            void OnDestroyPoolObject(FloatValueObj obj)
            {
                if (obj != null && obj.gameObject != null)
                {
                    GameObject.Destroy(obj.gameObject);
                }
            }
    
        }
    }
    

    FloatValueObj.cs

    using UnityEngine;
    using UnityEngine.UI;
    
    // 飘字
    public class FloatValueObj : MonoBehaviour
    {
        [SerializeField]
        private Text _content;
        [SerializeField]
        private float _lifeSeconds;
        public float LifeSeconds => _lifeSeconds;
        public void Init()
        { }
        public void Show(string content, Vector3 pos)
        {
            _content.text = content;
            transform.position = pos;
            gameObject.SetActive(true);
        }
        public void Destroy()
        { }
    }
    

    MyTest.cs

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class MyTest : MonoBehaviour
    {
        private FloatValueSys _floatValueSys;
        [SerializeField]
        private FloatValueModel _model;
    
        [SerializeField]
        private Transform _minTrans;
        [SerializeField]
        private Transform _maxTrans;
        [SerializeField]
        private Transform _playerTrans;
    
        private void Start()
        {
            Init();
        }
    
        private void Update()
        {
            MyUpdate();
        }
    
        private void OnDestroy()
        {
            MyDestroy();
        }
    
        private void Init()
        {
            _floatValueSys = new FloatValueSys(_model);
        }
    
        private void MyUpdate()
        {
            if (Input.GetMouseButtonDown(0))
            {
                // 随机设置player位置
                SetPlayerPosInAreaRandomly();
                // 在player处飘一种随机类型的字
                CreateFloatValueOnPlayerRandomly();
            }
    
            void SetPlayerPosInAreaRandomly()
            {
                var minPos = _minTrans.position;
                var maxPos = _maxTrans.position;
                var pos = new Vector3(UnityEngine.Random.Range(minPos.x, maxPos.x),
                                      _playerTrans.position.y,
                                      UnityEngine.Random.Range(minPos.z, maxPos.z));
                _playerTrans.position = pos;
            }
            void CreateFloatValueOnPlayerRandomly()
            {
                var allTypes = Enum.GetValues(typeof(FloatValueType)) as FloatValueType[];
                var curType = FloatValueType.None;
                while (curType == FloatValueType.None)
                {
                    curType = allTypes[UnityEngine.Random.Range(0, allTypes.Length)];
                }
                var value = UnityEngine.Random.Range(10, 100);
                _floatValueSys.Show(curType, value.ToString(), _playerTrans.position);
            }
        }
    
        private void MyDestroy()
        {
            _floatValueSys.Destroy();
            _floatValueSys = null;
        }
    }
    

    相关文章

      网友评论

          本文标题:使用Unity自带的对象池实现飘字(如怪物受创时显示伤害数字)

          本文链接:https://www.haomeiwen.com/subject/ivtondtx.html