Unity Stack+GameObject.SetActive()实现对象池。

本文介绍了一个用于Unity游戏开发的对象池管理系统,通过该系统可以有效地管理游戏中的对象实例,实现对象的复用,减少内存分配与垃圾回收的压力,提高游戏性能。
public class ObjectPoolManager : Singleton<ObjectPoolManager>
	{
		private class InternalPool
		{
			private Stack<GameObject> m_pool;
			private int m_poolDepth;
			private GameObject m_poolParent;

			public InternalPool(GameObject poolParent, int defPoolDepth)
			{
				m_pool = new Stack<GameObject>();
				m_poolParent = poolParent;
				m_poolDepth = defPoolDepth;
			}

			public void SetPoolDepthAndKeepNum(int poolDepth)
			{
				if (poolDepth == m_poolDepth)
				{
					return;
				}
				m_poolDepth = Mathf.Clamp(poolDepth, 0, 1000);
				CleanToDepthNum();
			}

			public void Release(GameObject go)
			{
				if (m_pool.Contains(go))
				{
					go.SetActive(false);
					return;
				}
				if (m_pool.Count >= m_poolDepth)
				{
					GameObject.Destroy(go);
					return;
				}
				go.SetActive(false);
				go.transform.SetParent(m_poolParent.transform);
				m_pool.Push(go);
			}

			public GameObject Get(bool setActive = true)
			{
				if (m_pool.Count > 0)
				{
					var go = m_pool.Pop();
					if (setActive)
					{
						go.SetActive(true);
					}
					go.transform.SetParent(null);
					return go;
				}

				return null;
			}

			private void CleanToDepthNum()
			{
				int keepNum = m_poolDepth;

				while (m_pool.Count > keepNum)
				{
					GameObject.Destroy(m_pool.Pop());
				}
			}

			public void Clean()
			{
				while (m_pool.Count > 0)
				{
					Object.DestroyImmediate(m_pool.Pop());
				}
			}

			public int GetCount()
			{
				return m_pool.Count;
			}
		}

		private readonly GameObject m_poolParent;
		private readonly Dictionary<string, InternalPool> m_pools;
		private readonly Dictionary<string, int> m_poolSeparateDepth;

		private int m_defaultPoolDepth;
		public int PoolDepth
		{
			get { return m_defaultPoolDepth; }
			set
			{
				m_defaultPoolDepth = value;
				m_defaultPoolDepth = Mathf.Clamp(m_defaultPoolDepth, 0, 1000);
			}
		}

		private ObjectPoolManager()
		{
			m_defaultPoolDepth = 10;
			m_pools = new Dictionary<string, InternalPool>();
			m_poolSeparateDepth = new Dictionary<string, int>();
			if (m_poolParent == null)
			{
				m_poolParent = new GameObject("PoolParent");
				GameObject.DontDestroyOnLoad(m_poolParent);
			}
		}

		public override void Dispose()
		{
			GameObject.Destroy(m_poolParent);
			m_pools.Clear();
			m_poolSeparateDepth.Clear();
			base.Dispose();
		}

		//setactive 专门为了某些需要先前置设置然后才能显示出来的对象
		public GameObject Get(string key, bool setActive = true)
		{
			InternalPool pool = null;
			if (m_pools.TryGetValue(key, out pool))
			{
				return pool.Get();
			}

			return null;
		}

		public void Release(string key, GameObject go, bool isIntoPool = true)
		{
			if (!isIntoPool)
			{
				GameObject.Destroy(go);
				return;
			}

			if (!m_pools.ContainsKey(key))
			{
				int depth = 0;
				if (!m_poolSeparateDepth.TryGetValue(key, out depth))
				{
					depth = m_defaultPoolDepth;
				}
				m_pools.Add(key, new InternalPool(m_poolParent, depth));
			}

			InternalPool pool = null;
			if (m_pools.TryGetValue(key, out pool))
			{
				pool.Release(go);
			}
		}

		public void Clean()
		{
			List<string> keys = new List<string>(m_pools.Keys);
			for (int i = 0; i != keys.Count; ++i)
			{
				var pool = m_pools[keys[i]];
				pool.Clean();
			}
			m_poolSeparateDepth.Clear();
		}

		public int GetGameObjectNum(string key)
		{
			InternalPool pool = null;
			if (m_pools.TryGetValue(key, out pool))
			{
				return pool.GetCount();
			}

			return 0;
		}

		public void SetKeyPoolDepthAndKeepNum(string key, int poolDepth)
		{
			InternalPool pool = null;
			if (m_pools.TryGetValue(key, out pool))
			{
				pool.SetPoolDepthAndKeepNum(poolDepth);
			}
			else
			{
				if (m_poolSeparateDepth.ContainsKey(key))
				{
					m_poolSeparateDepth[key] = poolDepth;
				}
				else
				{
					m_poolSeparateDepth.Add(key, poolDepth);
				}
			}
		}
	}

using System.Collections.Generic; using UnityEngine; using TMPro; using System.Collections; using UnityEngine.UI; using UnityEngine.SceneManagement; using UnityEngine.EventSystems; public class DialogueManager : MonoBehaviour { public enum DialogueState { Before, Win, Lost } public static DialogueManager Instance; [Header("UI Elements")] public TextMeshProUGUI tmpText; public float typingSpeed = 0.05f; [Header("Dialogue Content")] public List<string> beforeBattleDialogues = new List<string>(); public List<string> winDialogues = new List<string>(); public List<string> lostDialogues = new List<string>(); [Header("按钮设置")] public Button mainMenuButton; public Button startButton; public Button loseButton; public Button winButton; private bool isTyping = false; private Coroutine typingCoroutine; private string currentSentence; private DialogueState currentState = DialogueState.Before; private int currentDialogueIndex = 0; private List<string> currentDialogueList; void Start() { // 隐藏所有按钮 // 检查战斗结果 int result = PlayerPrefs.GetInt("LastBattleResult", -1); if (result == 1) { Debug.Log("战斗胜利 - 触发胜利对话"); SetDialogueState(DialogueState.Win); } else if (result == 0) { Debug.Log("战斗失败 - 触发失败对话"); SetDialogueState(DialogueState.Lost); } else { Debug.Log("首次进入 - 默认对话"); SetDialogueState(DialogueState.Before); } // 清除状态 PlayerPrefs.DeleteKey("LastBattleResult"); } void Awake() { if (Instance == null) { Instance = this; } else { Destroy(gameObject); } // 初始化当前对话列表 currentDialogueList = beforeBattleDialogues; // 设置按钮点击事件 if (mainMenuButton != null) mainMenuButton.onClick.AddListener(OnMainMenuClick); if (startButton != null) startButton.onClick.AddListener(OnStartClick); if (loseButton != null) loseButton.onClick.AddListener(OnLoseClick); if (winButton != null) winButton.onClick.AddListener(OnWinClick); } void Update() { // 添加跳过功能:按E键跳过当前打字效果 if (Input.GetKeyDown(KeyCode.E) && isTyping) { SkipTyping(); } // 按E键继续下一句对话 else if (Input.GetKeyDown(KeyCode.E) && !isTyping && tmpText.gameObject.activeSelf) { NextSentence(); } } // 隐藏所有按钮 // 设置当前对话状态 public void SetDialogueState(DialogueState newState) { currentState = newState; currentDialogueIndex = 0; switch (newState) { case DialogueState.Before: currentDialogueList = beforeBattleDialogues; break; case DialogueState.Win: currentDialogueList = winDialogues; break; case DialogueState.Lost: currentDialogueList = lostDialogues; break; } Debug.Log($"状态已切换至: {newState}"); } // 启动当前状态的对话 public void StartStateDialogue() { if (currentDialogueList == null || currentDialogueList.Count == 0) return; // 如果正在显示其他文本,先停止 if (isTyping) { StopCoroutine(typingCoroutine); } // 确保索引在有效范围内 currentDialogueIndex = Mathf.Clamp(currentDialogueIndex, 0, currentDialogueList.Count - 1); currentSentence = currentDialogueList[currentDialogueIndex]; // 暂停玩家移动 playercontrol player = FindObjectOfType<playercontrol>(); if (player != null) player.canMove = false; // 锁定玩家输入 Cursor.lockState = CursorLockMode.None; Cursor.visible = true; // 显示对话框UI tmpText.gameObject.SetActive(true); // 启动打字效果协程 typingCoroutine = StartCoroutine(TypeSentence(currentSentence)); } // 显示下一句对话 public void NextSentence() { currentDialogueIndex++; if (currentDialogueIndex < currentDialogueList.Count) { StartStateDialogue(); } else { // 对话结束 EndDialogue(); } } IEnumerator TypeSentence(string sentence) { isTyping = true; tmpText.text = ""; // 逐字显示 foreach (char letter in sentence.ToCharArray()) { tmpText.text += letter; yield return new WaitForSeconds(typingSpeed); } isTyping = false; } // 跳过当前打字效果 public void SkipTyping() { if (isTyping) { StopCoroutine(typingCoroutine); tmpText.text = currentSentence; isTyping = false; } } public void EndDialogue() { if (isTyping) { StopCoroutine(typingCoroutine); isTyping = false; } // 恢复玩家控制 playercontrol player = FindObjectOfType<playercontrol>(); if (player != null) player.canMove = true; // 隐藏对话框 tmpText.gameObject.SetActive(false); // 根据状态显示对应按钮 switch (currentState) { case DialogueState.Before: if (startButton != null) startButton.gameObject.SetActive(true); if (mainMenuButton != null) mainMenuButton.gameObject.SetActive(true); break; case DialogueState.Win: if (winButton != null) winButton.gameObject.SetActive(true); if (mainMenuButton != null) mainMenuButton.gameObject.SetActive(true); break; case DialogueState.Lost: if (loseButton != null) loseButton.gameObject.SetActive(true); if (mainMenuButton != null) mainMenuButton.gameObject.SetActive(true); break; } // 确保事件系统可用 EnsureEventSystemExists(); // 设置按钮为选中状态 if (currentState == DialogueState.Before && startButton != null) { EventSystem.current.SetSelectedGameObject(startButton.gameObject); } else if (currentState == DialogueState.Win && winButton != null) { EventSystem.current.SetSelectedGameObject(winButton.gameObject); } else if (currentState == DialogueState.Lost && loseButton != null) { EventSystem.current.SetSelectedGameObject(loseButton.gameObject); } } private void EnsureEventSystemExists() { EventSystem eventSystem = FindObjectOfType<EventSystem>(); if (eventSystem == null) { GameObject eventSystemObj = new GameObject("EventSystem"); eventSystem = eventSystemObj.AddComponent<EventSystem>(); eventSystemObj.AddComponent<StandaloneInputModule>(); } else if (eventSystem.GetComponent<StandaloneInputModule>() == null) { eventSystem.gameObject.AddComponent<StandaloneInputModule>(); } } private void OnMainMenuClick() { Debug.Log("主菜单按钮点击"); SceneManager.LoadScene("MainMenu"); } private void OnStartClick() { Debug.Log("开始作战"); SceneManager.LoadScene("Fight"); } private void OnLoseClick() { Debug.Log("失败按钮点击"); SceneManager.LoadScene("Fight"); } private void OnWinClick() { Debug.Log("胜利按钮点击"); // 解除玩家限制 playercontrol player = FindObjectOfType<playercontrol>(); if (player != null) player.canMove = true; } }using TMPro; using UnityEngine; using UnityEngine.UI; public class NPC2 : MonoBehaviour { public GameObject image; public GameObject image1; public GameObject image2; public TextMeshProUGUI text; [Header("按钮设置")] public Button mainMenuButton; public Button startButton; public Button loseButton; public Button winButton; void Start() { // 将按钮引用传递给DialogueManager if (DialogueManager.Instance != null) { DialogueManager.Instance.mainMenuButton = mainMenuButton; DialogueManager.Instance.startButton = startButton; DialogueManager.Instance.loseButton = loseButton; DialogueManager.Instance.winButton = winButton; } // 初始化时隐藏所有按钮 if (mainMenuButton != null) mainMenuButton.gameObject.SetActive(false); if (startButton != null) startButton.gameObject.SetActive(false); if (loseButton != null) loseButton.gameObject.SetActive(false); if (winButton != null) winButton.gameObject.SetActive(false); } void OnTriggerStay2D(Collider2D other) { if (other.CompareTag("Player") && Input.GetKeyDown(KeyCode.F)) { DialogueManager.Instance.EndDialogue(); image.SetActive(true); image1.SetActive(true); image2.SetActive(true); text.gameObject.SetActive(true); // 启动对话 DialogueManager.Instance.StartStateDialogue(); } } }为什么我到win状态下点击win的button按钮会转移到FIghtsence里面战斗
08-02
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

国家一级摸鱼选手

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值