游戏开发实用模块代码

Unity通用组件单例代码:

using UnityEngine;

public abstract class Singleton<T> : MonoBehaviour where T : MonoBehaviour {
    
    private static T instance;

    public static T Instance {
        get => instance != null ? instance : InstanceInit();
        set => instance = value;
    }

    protected static T InstanceInit() {
        if (instance != null) return instance;
        instance = GameObject.FindObjectOfType(typeof(T)) as T;
        if (instance != null) return instance;
        var obj = new GameObject(typeof(T).Name) {
            //hideFlags = HideFlags.HideAndDontSave
        };
        DontDestroyOnLoad(obj);
        instance = obj.AddComponent<T>();
        return instance; 
    }
}

Unity通用对象池:

using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using UnityEngine;
using Object = UnityEngine.Object;

public class ObjectPoolManager : MonoBehaviour
{
    private static ObjectPoolManager _instance;

    public static ObjectPoolManager Instance {
        get {
            if (_instance) return _instance;
            _instance = FindObjectOfType<ObjectPoolManager>();
            if (_instance) return _instance;
            var obj = new GameObject("ObjectPoolManager");
            DontDestroyOnLoad(obj);
            _instance = obj.AddComponent<ObjectPoolManager>();
            return _instance;
        }
    }
    
    
    private Dictionary<string, Queue<GameObject>> objectPoolDictionary = new ();

    private void Awake() {
        _instance = this;
    }

    public void Clear() {
        foreach (var (objName, goList) in objectPoolDictionary) {
            foreach (var obj in goList) {
                Destroy(obj);
            }
        }
        objectPoolDictionary.Clear(); 
    }

    /// <summary>
    /// 创建对象池
    /// </summary>
    /// <param name="prefab"></param>
    /// <param name="initialPoolSize"></param>
    public void CreateObjectPool(GameObject prefab, int initialPoolSize) {
        
        var prefabName = prefab.name;
        
        if (!objectPoolDictionary.ContainsKey(prefabName))
        {
            Queue<GameObject> objectPoolQueue = new Queue<GameObject>();

            for (int i = 0; i < initialPoolSize; i++)
            {
                GameObject obj = Instantiate(prefab);
                obj.SetActive(false);
                objectPoolQueue.Enqueue(obj);
            }

            objectPoolDictionary.Add(prefabName, objectPoolQueue);
        }
    }

    /// <summary>
    /// 获取对象
    /// </summary>
    /// <param name="prefab"></param>
    /// <param name="parent"></param>
    /// <param name="status"></param>
    /// <returns></returns>
    public GameObject GetObj(GameObject prefab, Transform parent = null, bool status = true) {

        var prefabName = prefab.name;
        //当前没有对象池,新创建并返回
        GameObject obj;
        if (!objectPoolDictionary.TryGetValue(prefabName, out var objectPoolQueue)) {
            objectPoolQueue = new Queue<GameObject>();
            objectPoolDictionary.Add(prefabName, objectPoolQueue); 
            
            obj = Instantiate(prefab, parent);
            obj.name = prefab.name;
            obj.SetActive(status);
            
            return obj;
        }

        if (objectPoolQueue.TryDequeue(out obj)) {
            if (obj) return obj;

            objectPoolQueue.Clear();
            
            obj = Instantiate(prefab, parent);
            obj.name = prefab.name;
            obj.SetActive(status);
            
            return obj;
        }
        
        obj = Instantiate(prefab, parent);
        obj.name = prefab.name;
        obj.SetActive(status);
            
        return obj; 
    }


    /// <summary>
    /// 放回对象池
    /// </summary>
    /// <param name="obj"></param>
    public void ReturnObj(GameObject obj) {
        var prefabName = obj.name;
        
        if(!objectPoolDictionary.TryGetValue(prefabName, out var objectPoolQueue)) {
            objectPoolQueue = new Queue<GameObject>();
            objectPoolDictionary.Add(prefabName, objectPoolQueue);
        }
        try {obj.SetActive(false);} catch{}

        if(objectPoolQueue.Contains(obj)) return;
        
        objectPoolQueue.Enqueue(obj);
    }

    public readonly Dictionary<int, Transform> findTransforms = new();
}

public static class PoolManagerEx {

    private static Dictionary<int, GameObject> _objCache = new Dictionary<int, GameObject>();

    static PoolManagerEx() {
        _objCache = new Dictionary<int, GameObject>();
        Application.quitting += () => {
            Debug.Log("ObjectCache clear!");
            _objCache.Clear();
        };
    }

    /// <summary>
    /// 获取对象实例
    /// </summary>
    /// <param name="objName"></param>
    /// <param name="getOrigin"></param>
    /// <param name="parent"></param>
    /// <param name="status"></param>
    /// <returns></returns>
    public static async UniTask<GameObject> GetInstance(this string objName, bool getOrigin = false, Transform parent = null, bool status = true) {
        int idx = objName.GetHashCode();
        
        if (_objCache.TryGetValue(idx, out var obj)) 
            return getOrigin ? obj : ObjectPoolManager.Instance.GetObj(obj, parent, status);
        
        obj = await objName.GetAssetAsync<GameObject>();
        _objCache[idx] = obj;
        
        return ObjectPoolManager.Instance.GetObj(obj, parent, status);
    }
    
    public static GameObject GetInstance(this GameObject gameObject, Transform parent = null, bool status = true) {
        return ObjectPoolManager.Instance.GetObj(gameObject,parent, status);
    }

    public static void Recovery(this GameObject gameObject) {
        ObjectPoolManager.Instance.ReturnObj(gameObject);
    }

    public static bool Find(this MonoBehaviour mono, string objName, out Transform target) {
        
        target = null;
        var objHash = objName.GetHashCode();
        if (ObjectPoolManager.Instance.findTransforms.TryGetValue(objHash, out var transform)) {
            if (transform != null) {
                target = transform;
                return true;
            }
        }

        try {
            var obj = GameObject.Find(objName);
            if (obj == null) return false;
            
            ObjectPoolManager.Instance.findTransforms[objHash] = obj.transform;
            target = obj.transform;
            return true;
        }
        catch {
            Debug.LogWarning("Does not find Obj");
            return false;
        }
    }

    public static bool FindWithType<T>(this MonoBehaviour mono, out Transform target) where T : MonoBehaviour {
        target = null;
        
        var objName = typeof(T).Name.GetHashCode();
        
        if (ObjectPoolManager.Instance.findTransforms.TryGetValue(objName, out var transform)) {
            if (transform != null) {
                target = transform;
                return true;
            }
        }

        try {
            var obj = Object.FindObjectOfType<T>();
            if (obj == null) return false;
            
            ObjectPoolManager.Instance.findTransforms[objName] = obj.transform;
            target = obj.transform;
            return true;
        }
        catch {
            Debug.LogWarning("Does not find Obj");
            return false;
        } 
    }
    
}

状态机:

  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Reflection;
  using UnityEngine;

  namespace Module.StateMachine {
     public class StateManager {

         //当前状态ID
         public int CurStateId { get; private set; }
         //下一状态ID
         public int NextStateId { get; private set; }
         //当前状态委托
         private StateAction _curStateAction;
         //当前状态持续时间
         public float CurStateDuration { get; private set; }
         //状态映射表
         private readonly Dictionary<int, StateAction> _stateMapping = new(5);

         public bool displayDebugInfo;

#if UNITY_EDITOR
         public Dictionary<int, string> _stateNameMapping = new(5);
#endif

         public void OnUpdate() {
             CurStateDuration += Time.deltaTime;
             _curStateAction?.OnUpdate?.Invoke();
         }
         
         /// <summary>
         /// 转换状态
         /// </summary>
         /// <param name="newState"></param>
         /// <param name="forceSwitch"></param>
         public void ChangeState(int newState, bool forceSwitch = true) {
             //新状态不存在
             if(!_stateMapping.TryGetValue(newState, out var newStateAction)) return;
             NextStateId = newState;
             if (_curStateAction == null) {
                 CurStateDuration = 0;
                 CurStateId = newState;
                 newStateAction.OnEnter?.Invoke();
                 _curStateAction = newStateAction;
                 return;
             }
             
             //当前状态无法转换
             if(!forceSwitch && !_curStateAction.CanSwitchNext()) return;

#if UNITY_EDITOR
             if(displayDebugInfo)
                 Debug.Log($"ChangeState: [{_stateNameMapping[CurStateId]}] ----> [{_stateNameMapping[newState]}]");
#endif
             _curStateAction.OnExit?.Invoke();
             
             _curStateAction = newStateAction;
             CurStateDuration = 0;
             CurStateId = newState;
             
             newStateAction.OnEnter?.Invoke();
             NextStateId = -1;
         }

         
         /// <summary>
         /// 状态注册
         /// </summary>
         /// <param name="stateId"></param>
         /// <param name="stateAction"></param>
         public void StateRegister(int stateId, StateAction stateAction) {
             _stateMapping[stateId] = stateAction;
         }

         
         /// <summary>
         /// 使用枚举注册状态机
         /// </summary>
         /// <typeparam name="T"></typeparam>
         public void StateRegister<T>(object obj) where T : Enum {
             var methodInfos = obj.GetType().GetMethods(BindingFlags.Instance | BindingFlags.NonPublic).ToList();
             foreach (string stateName in Enum.GetNames(typeof(T))) {
                 var methodInfo = methodInfos.Find(item => item.Name.Equals(stateName));
                 if (methodInfo == null) continue;
                 Enum.TryParse(typeof(T), stateName, true, out object state);
#if UNITY_EDITOR
                 _stateNameMapping[(int)state] = stateName;
#endif
                 StateRegister((int)state, (StateAction)methodInfo.Invoke(obj, null));
             }
         }

         
         /// <summary>
         /// 移除状态
         /// </summary>
         /// <param name="stateId"></param>
         public void RemoveState(int stateId) {
             _stateMapping.Remove(stateId);
         }

         public void ChangeState(Enum enumType, bool forceSwitch = false) {
             ChangeState(enumType.GetHashCode(),forceSwitch);
         }
         
     }
 }

namespace Module.StateMachine {
    
    public delegate bool StateDelegateBool();
    public delegate void StateDelegate();
    
    public class StateAction {
        
        public StateDelegateBool CanSwitchNext = () => true;
        public StateDelegate OnEnter = null;
        public StateDelegate OnUpdate = null;
        public StateDelegate OnExit = null;
        
    }
}

AI控制器:

using Module.StateMachine;
using UnityEngine;

namespace Module.AIController {
    public class AIBase : MonoBehaviour {

        protected StateManager StateMachine;
        protected Vector3 moveDir;
        protected float moveSpeed = 1;
        protected Transform _transform;
        
        private void Awake() {
            _transform = transform;
            StateMachine = new StateManager();
            OnInit();
        }

        private void Update() {
            StateMachine.OnUpdate();
        }

        protected virtual void OnInit(){}

        protected Vector3 Movement() {
            var position = _transform.position;
            position += moveSpeed * Time.deltaTime * moveDir;
            _transform.position = position;
            return position;
        }

        protected void ChangeDir() {
            var localScale = _transform.localScale;
            localScale.x = Mathf.Abs(localScale.x) * (moveDir.x > 0 ? 1 : -1);
            _transform.localScale = localScale;
        }
    }
}

正交摄像机平滑移动:

public class LandCameraComponent
{
    public Camera camera;
    public Rect cameraMoveRange;
    public Vector3 cameraPosition;
    public Vector3 cameraMovePosition;

        private static void InitCameraMoveRange(this LandCameraComponent self)
        {
            Rect moveRange = new()
            {
                xMin = 0,
                xMax = (Vector3.right * 宽度).x,
                yMin = 0,
                yMax = (Vector3.up * 高度).y
            };
            Vector3 cameraViewCenter = self.GetInCameraWorldPosition(new Vector3(Screen.width / 2, Screen.height / 2));
            Vector3 upperRight = self.GetInCameraWorldPosition(new Vector3(Screen.width, Screen.height));
            Vector3 lowerLeft = self.GetInCameraWorldPosition(Vector3.zero);

            //xMin
            moveRange.xMin = cameraViewCenter.x - lowerLeft.x;
            //yMin
            moveRange.yMin = cameraViewCenter.y - lowerLeft.y;
            //xMax
            float value = upperRight.x - cameraViewCenter.x;
            moveRange.xMax -= value;
            //yMax
            value = upperRight.y - cameraViewCenter.y;
            moveRange.yMax -= value;

            self.cameraMoveRange = moveRange;
        }

        private static void MoveCamera(this LandCameraComponent self)
        {
            if(Input.GetMouseButtonDown(0))
            {
                self.cameraPosition = Input.mousePosition;
            }
            if (Input.GetMouseButton(0))
            {
                if(self.cameraMovePosition != Input.mousePosition)
                {
                    Vector3 cameraPosition = self.cameraMovePosition;
                    Vector3 newPosition = Input.mousePosition - cameraPosition;
                    newPosition.z = cameraPosition.z;
                    cameraPosition = self.camera.transform.position - 16 * Time.deltaTime * newPosition.normalized;
                    if(cameraPosition.x > self.cameraMoveRange.xMax)
                        cameraPosition.x = self.cameraMoveRange.xMax;
                    if (cameraPosition.x < self.cameraMoveRange.xMin)
                        cameraPosition.x = self.cameraMoveRange.xMin;
                    if(cameraPosition.y > self.cameraMoveRange.yMax)
                        cameraPosition.y = self.cameraMoveRange.yMax;
                    if(cameraPosition.y < self.cameraMoveRange.yMin)
                        cameraPosition.y = self.cameraMoveRange.yMin;
                    self.camera.transform.position = cameraPosition;
                }
                self.cameraMovePosition = Input.mousePosition;
            }
            if (Input.GetMouseButtonUp(0))
            {
                Vector3 moveDistances = Input.mousePosition - self.cameraPosition;
                if(moveDistances.sqrMagnitude < 0.01f)
                {
                    Log.Warning($"点击执行代码区域{self.GetInCameraWorldPosition(Input.mousePosition)}");
                }
                self.cameraPosition = Input.mousePosition;
            }
        }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值