2026/6/10 1:18:13
网站建设
项目流程
北京企业建站哪家好,网站设计公司网站设计,wordpress 公告,中国商标注册网查询网官网Unity状态模式实战#xff1a;解决GameObject行为扩展难题
下面是一个关于方块的简单实现#xff0c;关于方块 以及地图方块的相关内容#xff0c;主要是鼠标移动到方块#xff0c;以及单击方块的内容。
方块的生成涉及对象池#xff0c;但在本文可以不需要过多理解。
…Unity状态模式实战解决GameObject行为扩展难题下面是一个关于方块的简单实现关于方块 以及地图方块的相关内容主要是鼠标移动到方块以及单击方块的内容。方块的生成涉及对象池但在本文可以不需要过多理解。using System.Collections; using System.Collections.Generic; using UnityEngine; public abstract class Square : MonoBehaviour { public SquareTypeList Type; public enum SquareTypeList { MapSquare0, } public abstract void Initialize(Vector2 position, SquareTypeList squareType); public abstract void Activate(); public abstract void Deactivate(); } using System.Collections; using System.Collections.Generic; using UnityEngine; public class MapSquare : Square { private SpriteRenderer _spriteRenderer; private void Awake() { _spriteRenderer GetComponentSpriteRenderer(); } public override void Activate() { gameObject.SetActive(true); } public override void Deactivate() { gameObject.SetActive(false); } public override void Initialize(Vector2 squarePosiont, SquareTypeList squareType) { transform.position squarePosiont; Type squareType; Activate(); return; } private void Update() { } private void OnMouseEnter() { _spriteRenderer.color Color.red; } private void OnMouseExit() { _spriteRenderer.color Color.white; } private void OnMouseDown() { EventCenter.Instance.TriggerEventGameObject( GameEvent.ReturnSquareToPoolEvent, this, this.gameObject); } }上面是我问题的源代码部分这个代码在继承上存在设计问题假如我要扩展更多类型的方块并且方块类型改变自然的切换到另一种。一般的思路可能是要么1写更多的方块脚本如map2square之类的让方块实体卸载当前脚本再挂上它。2还是设计一种状态根据其基本的类型值进行变换成其他方块但都写在一个类脚本里,3创建不同的预制体设置更多的不同种类砖块的对象池来进行。问题分别是1卸载脚本在砖块很多的当下似乎并不划算。2一个类里代码太多比如5种砖块的5种消失执行都写在同一个脚本里设计上看起来就很奇怪。3可行 但思路上还是跟状态模式不一样。你也许发现了代码中SquareTypeList根本没用上如果参照状态模式进行的话状态模式管Square叫做上下文图里面的两个方块 就是状态切换机制 通过接口来实现对不同状态下的方法的调用算是一种简单的分离法。具体代码如下同样只包含核心内容。using System.Collections; using System.Collections.Generic; using UnityEngine; public class Square : MonoBehaviour { [HideInInspector] public SquareType currentType; private ISquareState _currentState; private SpriteRenderer _spriteRenderer; private static readonly DictionarySquareType, ISquareState _stateMap new() { {SquareType.MapSquare,new MapSquareState() }, }; private void Awake() { _spriteRenderer GetComponentSpriteRenderer(); } public void Initialize(Vector2 position, SquareType squareType) { currentType squareType; // 切换到对应状态并初始化 _currentState _stateMap[squareType]; _currentState.Initialize(this, position); Activate(); } public void Activate() _currentState?.Activate(); public void Deactivate() _currentState?.Deactivate(); private void OnMouseEnter() _currentState?.OnMouseEnter(); private void OnMouseExit() _currentState?.OnMouseExit(); private void OnMouseDown() _currentState?.OnMouseDown(); public SpriteRenderer GetSpriteRenderer() _spriteRenderer; }接口代码using UnityEngine; public interface ISquareState { void Initialize(Square square, Vector2 position); void Activate(); void Deactivate(); void OnMouseEnter(); void OnMouseExit(); void OnMouseDown(); }一个实现using UnityEngine; public class MapSquareState : ISquareState { private Square _square; private SpriteRenderer _spriteRenderer; public void Initialize(Square square, Vector2 position) { _square square; _spriteRenderer _square.GetComponentSpriteRenderer(); _square.transform.position position; } public void Activate() { _square.gameObject.SetActive(true); } public void Deactivate() { _square.gameObject.SetActive(false); } public void OnMouseEnter() { _spriteRenderer.color Color.red; } public void OnMouseExit() { _spriteRenderer.color Color.white;} public void OnMouseDown() { EventCenter.Instance.TriggerEventGameObject( GameEvent.ReturnSquareToPoolEvent, _square, _square.gameObject); } }可以发现在MapSquareState是有Square类的 _square引用的该设计模式存在耦合 但耦合并非绝对的错误。在这里可以方便的扩展更多的类别只要在一个枚举类里增加如下public enum SquareType { // 基础地图方块 MapSquare 0, BlockedSquare 1, // 封禁层 - 需要特殊条件触发不可点击 }然后是状态类using UnityEngine public class BlockedSquareState : ISquareState { public void Activate() { throw new System.NotImplementedException(); } public void Deactivate() { throw new System.NotImplementedException(); } public void Initialize(Square square, Vector2 position) { throw new System.NotImplementedException(); } public void OnMouseDown() { Debug.Log(封禁层 不可点); return; } public void OnMouseEnter() { throw new System.NotImplementedException(); } public void OnMouseExit() { throw new System.NotImplementedException(); } }以及在square类中添加一个新的状态private static readonly DictionarySquareType, ISquareState _stateMap new() { {SquareType.MapSquare,new MapSquareState() }, {SquareType.BlockedSquare,new BlockedSquareState() }, //新增 };后回到页面里添加一些方块实例的预制体就好了这是指我的对象池子对象池也有更改。展现部分关键代码。public class MapSquareManager : MonoBehaviour { [System.Serializable] public class SquarePoolConfig { public SquareType squareType; // 方块类型 public Square squarePrefab; // 对应预制体挂载Square组件 public int maxCount 30; // 该类型池最大数量 } [Header(多类型方块池配置)] [SerializeField] private ListSquarePoolConfig poolConfigs; // 多类型配置列表 private DictionarySquareType, QueueGameObject _squarePools; private void Awake() { _squarePools new DictionarySquareType, QueueGameObject(); InitializePool(); } private void Start() { GenerateMap(); } public void InitializePool() { //for (int i 0; i mapSquareMaxCount; i) //{ // GameObject mapSquare Instantiate(mapSquarePre); // mapSquare.SetActive(false); // mapSquarePool.Enqueue(mapSquare); //} foreach (var config in poolConfigs) { QueueGameObject pool new QueueGameObject(); for (int i 0; i config.maxCount; i) { Square square Instantiate(config.squarePrefab); square.gameObject.SetActive(false); square.gameObject.transform.SetParent(transform);//这样的话square 是mapsquarestate 还是 square pool.Enqueue(square.gameObject); } _squarePools.Add(config.squareType, pool); } } }以上 完毕