Unity中常用的设计模式
🎨 创建型模式(Creational Patterns)
1. 单例模式(Singleton) ⭐⭐⭐⭐⭐
Unity中最常用的模式
// A. 普通C#单例
public class GameManager {
private static GameManager instance;
private static readonly object lockObj = new object();
public static GameManager Instance {
get {
if (instance == null) {
lock (lockObj) {
if (instance == null) {
instance = new GameManager();
}
}
}
return instance;
}
}
private GameManager() {
// 私有构造函数
}
}
// B. MonoBehaviour单例(最常用)
public class MonoSingleton<T> : MonoBehaviour where T : MonoBehaviour {
private static T instance;
private static object lockObj = new object();
public static T Instance {
get {
if (instance == null) {
lock (lockObj) {
if (instance == null) {
instance = FindObjectOfType<T>();
if (instance == null) {
GameObject singleton = new GameObject($"[Singleton]{typeof(T)}");
instance = singleton.AddComponent<T>();
DontDestroyOnLoad(singleton);
}
}
}
}
return instance;
}
}
protected virtual void Awake() {
if (instance == null) {
instance = this as T;
DontDestroyOnLoad(gameObject);
} else if (instance != this) {
Destroy(gameObject);
}
}
}
// 使用
public class AudioManager : MonoSingleton<AudioManager> {
public void PlaySound(string soundName) {
Debug.Log($"播放音效: {soundName}");
}
}
// 调用
AudioManager.Instance.PlaySound("explosion");
// C. 懒汉式单例(线程安全)
public sealed class LazyGameManager {
private static readonly Lazy<LazyGameManager> lazy =
new Lazy<LazyGameManager>(() => new LazyGameManager());
public static LazyGameManager Instance => lazy.Value;
private LazyGameManager() { }
}
应用场景:
- 游戏管理器(GameManager)
- 音频管理器(AudioManager)
- UI管理器(UIManager)
- 资源管理器(ResourceManager)
2. 工厂模式(Factory) ⭐⭐⭐⭐⭐
// A. 简单工厂
public enum EnemyType {
Zombie,
Skeleton,
Boss
}
public class EnemyFactory {
public Enemy CreateEnemy(EnemyType type) {
switch (type) {
case EnemyType.Zombie:
return new Zombie();
case EnemyType.Skeleton:
return new Skeleton();
case EnemyType.Boss:
return new Boss();
default:
return null;
}
}
}
// B. 工厂方法(更灵活)
public abstract class Enemy : MonoBehaviour {
public abstract void Attack();
}
public class Zombie : Enemy {
public override void Attack() {
Debug.Log("僵尸攻击");
}
}
public abstract class EnemySpawner : MonoBehaviour {
public abstract Enemy CreateEnemy();
public Enemy SpawnEnemy(Vector3 position) {
Enemy enemy = CreateEnemy();
enemy.transform.position = position;
return enemy;
}
}
public class ZombieSpawner : EnemySpawner {
public GameObject zombiePrefab;
public override Enemy CreateEnemy() {
GameObject obj = Instantiate(zombiePrefab);
return obj.GetComponent<Zombie>();
}
}
// C. 抽象工厂(创建产品族)
public interface IUIFactory {
IButton CreateButton();
IPanel CreatePanel();
ISlider CreateSlider();
}
public class ModernUIFactory : IUIFactory {
public IButton CreateButton() => new ModernButton();
public IPanel CreatePanel() => new ModernPanel();
public ISlider CreateSlider() => new ModernSlider();
}
public class ClassicUIFactory : IUIFactory {
public IButton CreateButton() => new ClassicButton();
public IPanel CreatePanel() => new ClassicPanel();
public ISlider CreateSlider() => new ClassicSlider();
}
// 使用
public class UIManager : MonoBehaviour {
private IUIFactory uiFactory;
void Start() {
// 根据配置选择UI风格
if (GameSettings.UIStyle == "Modern") {
uiFactory = new ModernUIFactory();
} else {
uiFactory = new ClassicUIFactory();
}
// 创建UI组件(统一风格)
IButton btn = uiFactory.CreateButton();
IPanel panel = uiFactory.CreatePanel();
}
}
应用场景:
- 敌人生成系统
- UI组件创建
- 道具/装备生成
- 关卡元素生成
3. 对象池模式(Object Pool) ⭐⭐⭐⭐⭐
// Unity中性能优化必备
public class ObjectPool<T> where T : Component {
private Queue<T> pool;
private T prefab;
private Transform parent;
public ObjectPool(T prefab, int initialSize = 10, Transform parent = null) {
this.prefab = prefab;
this.parent = parent;
this.pool = new Queue<T>();
// 预创建对象
for (int i = 0; i < initialSize; i++) {
T obj = Object.Instantiate(prefab, parent);
obj.gameObject.SetActive(false);
pool.Enqueue(obj);
}
}
public T Get() {
T obj;
if (pool.Count > 0) {
obj = pool.Dequeue();
obj.gameObject.SetActive(true);
} else {
obj = Object.Instantiate(prefab, parent);
}
return obj;
}
public void Return(T obj) {
obj.gameObject.SetActive(false);
pool.Enqueue(obj);
}
public void Clear() {
while (pool.Count > 0) {
Object.Destroy(pool.Dequeue().gameObject);
}
}
}
// 使用示例
public class BulletManager : MonoBehaviour {
public Bullet bulletPrefab;
private ObjectPool<Bullet> bulletPool;
void Start() {
bulletPool = new ObjectPool<Bullet>(bulletPrefab, 50, transform);
}
public void Fire(Vector3 position, Vector3 direction) {
Bullet bullet = bulletPool.Get();
bullet.transform.position = position;
bullet.Fire(direction);
// 3秒后回收
StartCoroutine(ReturnBulletAfterDelay(bullet, 3f));
}
IEnumerator ReturnBulletAfterDelay(Bullet bullet, float delay) {
yield return new WaitForSeconds(delay);
bulletPool.Return(bullet);
}
}
// Unity官方的对象池(2021+)
using UnityEngine.Pool;
public class ModernBulletManager : MonoBehaviour {
public Bullet bulletPrefab;
private ObjectPool<Bullet> bulletPool;
void Start() {
bulletPool = new ObjectPool<Bullet>(
createFunc: () => Instantiate(bulletPrefab),
actionOnGet: bullet => bullet.gameObject.SetActive(true),
actionOnRelease: bullet => bullet.gameObject.SetActive(false),
actionOnDestroy: bullet => Destroy(bullet.gameObject),
collectionCheck: true,
defaultCapacity: 50,
maxSize: 100
);
}
public void Fire() {
Bullet bullet = bulletPool.Get();
// 使用子弹
bulletPool.Release(bullet);
}
}
4. 建造者模式(Builder) ⭐⭐⭐⭐
// 构建复杂对象
public class Character {
public string Name;
public int Level;
public int Health;
public int Mana;
public List<string> Skills;
public Dictionary<string, int> Attributes;
}
public class CharacterBuilder {
private Character character;
public CharacterBuilder() {
character = new Character {
Skills = new List<string>(),
Attributes = new Dictionary<string, int>()
};
}
public CharacterBuilder SetName(string name) {
character.Name = name;
return this;
}
public CharacterBuilder SetLevel(int level) {
character.Level = level;
character.Health = level * 100;
character.Mana = level * 50;
return this;
}
public CharacterBuilder AddSkill(string skill) {
character.Skills.Add(skill);
return this;
}
public CharacterBuilder SetAttribute(string attr, int value) {
character.Attributes[attr] = value;
return this;
}
public Character Build() {
return character;
}
}
// 使用(链式调用)
Character warrior = new CharacterBuilder()
.SetName("战士")
.SetLevel(10)
.AddSkill("重击")
.AddSkill("旋风斩")
.SetAttribute("力量", 50)
.SetAttribute("体质", 40)
.Build();
// 更复杂的建造者:武器系统
public class Weapon {
public string Name;
public int BaseDamage;
public float AttackSpeed;
public List<WeaponMod> Mods;
public GameObject Model;
public AudioClip AttackSound;
public ParticleSystem Effect;
}
public class WeaponBuilder {
private Weapon weapon = new Weapon { Mods = new List<WeaponMod>() };
public WeaponBuilder SetBase(string name, int damage, float speed) {
weapon.Name = name;
weapon.BaseDamage = damage;
weapon.AttackSpeed = speed;
return this;
}
public WeaponBuilder AddMod(WeaponMod mod) {
weapon.Mods.Add(mod);
weapon.BaseDamage += mod.DamageBonus;
return this;
}
public WeaponBuilder SetVisuals(GameObject model, ParticleSystem effect) {
weapon.Model = model;
weapon.Effect = effect;
return this;
}
public WeaponBuilder SetAudio(AudioClip sound) {
weapon.AttackSound = sound;
return this;
}
public Weapon Build() => weapon;
}
应用场景:
- 角色创建
- 装备/武器配置
- 关卡生成器
- UI对话框构建
5. 原型模式(Prototype) ⭐⭐⭐
// 克隆对象
public interface ICloneable<T> {
T Clone();
}
public class Enemy : MonoBehaviour, ICloneable<Enemy> {
public string enemyName;
public int health;
public int damage;
public List<string> abilities;
public Enemy Clone() {
// 深拷贝
Enemy clone = Instantiate(this);
clone.abilities = new List<string>(this.abilities);
return clone;
}
}
// ScriptableObject作为原型
[CreateAssetMenu(fileName = "EnemyData", menuName = "Game/Enemy")]
public class EnemyData : ScriptableObject {
public string enemyName;
public int baseHealth;
public int baseDamage;
public GameObject prefab;
// 从原型创建实例
public Enemy CreateEnemy() {
GameObject obj = Instantiate(prefab);
Enemy enemy = obj.GetComponent<Enemy>();
enemy.enemyName = enemyName;
enemy.health = baseHealth;
enemy.damage = baseDamage;
return enemy;
}
}
// 使用原型管理器
public class EnemyPrototypeManager : MonoBehaviour {
private Dictionary<string, EnemyData> prototypes = new Dictionary<string, EnemyData>();
void Start() {
// 加载所有原型
EnemyData[] datas = Resources.LoadAll<EnemyData>("Enemies");
foreach (var data in datas) {
prototypes[data.enemyName] = data;
}
}
public Enemy SpawnEnemy(string enemyName, Vector3 position) {
if (prototypes.TryGetValue(enemyName, out EnemyData data)) {
Enemy enemy = data.CreateEnemy();
enemy.transform.position = position;
return enemy;
}
return null;
}
}
🏗️ 结构型模式(Structural Patterns)
6. 组合模式(Composite) ⭐⭐⭐⭐
// Unity的Transform天然就是组合模式
// 实现技能组合系统
public abstract class SkillComponent {
public abstract void Execute();
public abstract float GetCooldown();
}
// 叶子节点:基础技能
public class BasicSkill : SkillComponent {
private string skillName;
private float cooldown;
public BasicSkill(string name, float cd) {
skillName = name;
cooldown = cd;
}
public override void Execute() {
Debug.Log($"执行技能: {skillName}");
}
public override float GetCooldown() => cooldown;
}
// 组合节点:技能组合
public class ComboSkill : SkillComponent {
private List<SkillComponent> skills = new List<SkillComponent>();
private string comboName;
public ComboSkill(string name) {
comboName = name;
}
public void Add(SkillComponent skill) {
skills.Add(skill);
}
public void Remove(SkillComponent skill) {
skills.Remove(skill);
}
public override void Execute() {
Debug.Log($"执行连招: {comboName}");
foreach (var skill in skills) {
skill.Execute();
}
}
public override float GetCooldown() {
float total = 0;
foreach (var skill in skills) {
total += skill.GetCooldown();
}
return total;
}
}
// 使用
ComboSkill ultimateCombo = new ComboSkill("终极连招");
ultimateCombo.Add(new BasicSkill("破甲", 1f));
ultimateCombo.Add(new BasicSkill("重击", 2f));
ultimateCombo.Add(new BasicSkill("终结", 3f));
ultimateCombo.Execute(); // 执行整个连招
float totalCD = ultimateCombo.GetCooldown(); // 总冷却时间
7. 装饰器模式(Decorator) ⭐⭐⭐⭐
// 动态添加功能
public interface IWeapon {
int GetDamage();
string GetDescription();
}
public class BasicSword : IWeapon {
public int GetDamage() => 10;
public string GetDescription() => "基础剑";
}
// 装饰器基类
public abstract class WeaponDecorator : IWeapon {
protected IWeapon weapon;
public WeaponDecorator(IWeapon weapon) {
this.weapon = weapon;
}
public virtual int GetDamage() => weapon.GetDamage();
public virtual string GetDescription() => weapon.GetDescription();
}
// 具体装饰器
public class FireEnchantment : WeaponDecorator {
public FireEnchantment(IWeapon weapon) : base(weapon) { }
public override int GetDamage() => weapon.GetDamage() + 5;
public override string GetDescription() => weapon.GetDescription() + " + 火焰附魔";
}
public class SharpnessEnchantment : WeaponDecorator {
public SharpnessEnchantment(IWeapon weapon) : base(weapon) { }
public override int GetDamage() => weapon.GetDamage() + 3;
public override string GetDescription() => weapon.GetDescription() + " + 锋利";
}
public class CriticalHitMod : WeaponDecorator {
public CriticalHitMod(IWeapon weapon) : base(weapon) { }
public override int GetDamage() {
// 20%暴击
if (UnityEngine.Random.value < 0.2f) {
return weapon.GetDamage() * 2;
}
return weapon.GetDamage();
}
public override string GetDescription() => weapon.GetDescription() + " + 暴击";
}
// 使用(动态叠加)
IWeapon weapon = new BasicSword();
weapon = new FireEnchantment(weapon);
weapon = new SharpnessEnchantment(weapon);
weapon = new CriticalHitMod(weapon);
Debug.Log(weapon.GetDescription()); // "基础剑 + 火焰附魔 + 锋利 + 暴击"
Debug.Log($"伤害: {weapon.GetDamage()}"); // 18 (或暴击36)
8. 适配器模式(Adapter) ⭐⭐⭐⭐
// 适配不同的输入系统
public interface IInputSystem {
Vector2 GetMovement();
bool GetJumpButton();
bool GetAttackButton();
}
// 旧的输入系统
public class OldInputSystem {
public float GetHorizontal() => Input.GetAxis("Horizontal");
public float GetVertical() => Input.GetAxis("Vertical");
public bool GetSpace() => Input.GetKeyDown(KeyCode.Space);
public bool GetMouse0() => Input.GetMouseButtonDown(0);
}
// 适配器
public class InputAdapter : IInputSystem {
private OldInputSystem oldInput = new OldInputSystem();
public Vector2 GetMovement() {
return new Vector2(oldInput.GetHorizontal(), oldInput.GetVertical());
}
public bool GetJumpButton() => oldInput.GetSpace();
public bool GetAttackButton() => oldInput.GetMouse0();
}
// 新的输入系统(Unity Input System)
using UnityEngine.InputSystem;
public class NewInputAdapter : IInputSystem {
private PlayerInput playerInput;
public NewInputAdapter() {
playerInput = new PlayerInput();
playerInput.Enable();
}
public Vector2 GetMovement() {
return playerInput.Player.Move.ReadValue<Vector2>();
}
public bool GetJumpButton() {
return playerInput.Player.Jump.triggered;
}
public bool GetAttackButton() {
return playerInput.Player.Attack.triggered;
}
}
// 使用(统一接口)
public class PlayerController : MonoBehaviour {
private IInputSystem input;
void Start() {
// 可以轻松切换输入系统
#if USE_NEW_INPUT
input = new NewInputAdapter();
#else
input = new InputAdapter();
#endif
}
void Update() {
Vector2 movement = input.GetMovement();
if (input.GetJumpButton()) {
Jump();
}
}
void Jump() { }
}
9. 外观模式(Facade) ⭐⭐⭐⭐⭐
// 简化复杂子系统
public class AudioFacade : MonoBehaviour {
private AudioSource bgmSource;
private AudioSource sfxSource;
private Dictionary<string, AudioClip> audioClips;
// 简化的接口
public void PlayBGM(string bgmName, bool loop = true) {
AudioClip clip = GetClip(bgmName);
bgmSource.clip = clip;
bgmSource.loop = loop;
bgmSource.Play();
}
public void PlaySFX(string sfxName, float volume = 1f) {
AudioClip clip = GetClip(sfxName);
sfxSource.PlayOneShot(clip, volume);
}
public void StopBGM(float fadeTime = 1f) {
StartCoroutine(FadeOut(bgmSource, fadeTime));
}
public void SetBGMVolume(float volume) {
bgmSource.volume = volume;
}
public void SetSFXVolume(float volume) {
sfxSource.volume = volume;
}
// 隐藏复杂实现
private AudioClip GetClip(string name) {
if (!audioClips.ContainsKey(name)) {
audioClips[name] = Resources.Load<AudioClip>($"Audio/{name}");
}
return audioClips[name];
}
private IEnumerator FadeOut(AudioSource source, float time) {
float startVolume = source.volume;
while (source.volume > 0) {
source.volume -= startVolume * Time.deltaTime / time;
yield return null;
}
source.Stop();
source.volume = startVolume;
}
}
// 使用(简单调用)
AudioFacade.Instance.PlayBGM("battle_theme");
AudioFacade.Instance.PlaySFX("explosion", 0.8f);
🎭 行为型模式(Behavioral Patterns)
10. 观察者模式(Observer) ⭐⭐⭐⭐⭐
// Unity事件系统的基础
// A. C# Event实现
public class Player : MonoBehaviour {
public delegate void HealthChangedHandler(int currentHealth, int maxHealth);
public event HealthChangedHandler OnHealthChanged;
public delegate void PlayerDiedHandler();
public event PlayerDiedHandler OnPlayerDied;
private int health = 100;
private int maxHealth = 100;
public void TakeDamage(int damage) {
health -= damage;
// 通知观察者
OnHealthChanged?.Invoke(health, maxHealth);
if (health <= 0) {
OnPlayerDied?.Invoke();
}
}
}
// 观察者
public class HealthUI : MonoBehaviour {
public Slider healthBar;
public Player player;
void Start() {
// 订阅事件
player.OnHealthChanged += UpdateHealthBar;
player.OnPlayerDied += ShowDeathScreen;
}
void OnDestroy() {
// 取消订阅(重要!)
player.OnHealthChanged -= UpdateHealthBar;
player.OnPlayerDied -= ShowDeathScreen;
}
void UpdateHealthBar(int current, int max) {
healthBar.value = (float)current / max;
}
void ShowDeathScreen() {
Debug.Log("显示死亡界面");
}
}
// B. UnityEvent实现
using UnityEngine.Events;
[System.Serializable]
public class HealthEvent : UnityEvent<int, int> { }
public class ModernPlayer : MonoBehaviour {
public HealthEvent onHealthChanged;
public UnityEvent onPlayerDied;
private int health = 100;
public void TakeDamage(int damage) {
health -= damage;
onHealthChanged?.Invoke(health, 100);
if (health <= 0) {
onPlayerDied?.Invoke();
}
}
}
11. 命令模式(Command) ⭐⭐⭐⭐⭐
// 将操作封装成对象,支持撤销/重做
public interface ICommand {
void Execute();
void Undo();
}
// 移动命令
public class MoveCommand : ICommand {
private Transform target;
private Vector3 displacement;
private Vector3 previousPosition;
public MoveCommand(Transform target, Vector3 displacement) {
this.target = target;
this.displacement = displacement;
}
public void Execute() {
previousPosition = target.position;
target.position += displacement;
}
public void Undo() {
target.position = previousPosition;
}
}
// 旋转命令
public class RotateCommand : ICommand {
private Transform target;
private Vector3 rotation;
private Quaternion previousRotation;
public RotateCommand(Transform target, Vector3 rotation) {
this.target = target;
this.rotation = rotation;
}
public void Execute() {
previousRotation = target.rotation;
target.Rotate(rotation);
}
public void Undo() {
target.rotation = previousRotation;
}
}
// 改变颜色命令
public class ChangeColorCommand : ICommand {
private Renderer renderer;
private Color newColor;
private Color previousColor;
public ChangeColorCommand(Renderer renderer, Color color) {
this.renderer = renderer;
this.newColor = color;
}
public void Execute() {
previousColor = renderer.material.color;
renderer.material.color = newColor;
}
public void Undo() {
renderer.material.color = previousColor;
}
}
// 命令管理器(支持撤销/重做)
public class CommandManager : MonoBehaviour {
private Stack<ICommand> commandHistory = new Stack<ICommand>();
private Stack<ICommand> redoStack = new Stack<ICommand>();
public void ExecuteCommand(ICommand command) {
command.Execute();
commandHistory.Push(command);
redoStack.Clear(); // 执行新命令清空重做栈
}
public void Undo() {
if (commandHistory.Count > 0) {
ICommand command = commandHistory.Pop();
command.Undo();
redoStack.Push(command);
}
}
public void Redo() {
if (redoStack.Count > 0) {
ICommand command = redoStack.Pop();
command.Execute();
commandHistory.Push(command);
}
}
public void ClearHistory() {
commandHistory.Clear();
redoStack.Clear();
}
}
// 使用示例
public class LevelEditor : MonoBehaviour {
public Transform selectedObject;
private CommandManager commandManager;
void Start() {
commandManager = GetComponent<CommandManager>();
}
void Update() {
// 移动
if (Input.GetKeyDown(KeyCode.W)) {
commandManager.ExecuteCommand(
new MoveCommand(selectedObject, Vector3.forward)
);
}
// 撤销
if (Input.GetKeyDown(KeyCode.Z) && Input.GetKey(KeyCode.LeftControl)) {
commandManager.Undo();
}
// 重做
if (Input.GetKeyDown(KeyCode.Y) && Input.GetKey(KeyCode.LeftControl)) {
commandManager.Redo();
}
}
}
// 宏命令(组合多个命令)
public class MacroCommand : ICommand {
private List<ICommand> commands = new List<ICommand>();
public void AddCommand(ICommand command) {
commands.Add(command);
}
public void Execute() {
foreach (var command in commands) {
command.Execute();
}
}
public void Undo() {
// 反向撤销
for (int i = commands.Count - 1; i >= 0; i--) {
commands[i].Undo();
}
}
}
// 使用宏命令
MacroCommand createCharacter = new MacroCommand();
createCharacter.AddCommand(new MoveCommand(character, spawnPoint));
createCharacter.AddCommand(new ChangeColorCommand(characterRenderer, Color.red));
createCharacter.AddCommand(new RotateCommand(character, new Vector3(0, 180, 0)));
commandManager.ExecuteCommand(createCharacter); // 一次执行所有命令
应用场景:
- 关卡编辑器(撤销/重做)
- 回合制游戏(记录操作)
- 输入缓冲(格斗游戏)
- 录制回放系统
12. 状态模式(State) ⭐⭐⭐⭐⭐
// 将对象的状态封装成独立的类
public interface IState {
void Enter();
void Update();
void FixedUpdate();
void Exit();
}
// 状态机
public class StateMachine {
private IState currentState;
public void ChangeState(IState newState) {
currentState?.Exit();
currentState = newState;
currentState?.Enter();
}
public void Update() {
currentState?.Update();
}
public void FixedUpdate() {
currentState?.FixedUpdate();
}
}
// 具体状态:空闲
public class IdleState : IState {
private PlayerController player;
public IdleState(PlayerController player) {
this.player = player;
}
public void Enter() {
Debug.Log("进入Idle状态");
player.Animator.Play("Idle");
}
public void Update() {
// 状态转换逻辑
if (Input.GetAxis("Horizontal") != 0 || Input.GetAxis("Vertical") != 0) {
player.StateMachine.ChangeState(new RunState(player));
}
if (Input.GetKeyDown(KeyCode.Space)) {
player.StateMachine.ChangeState(new JumpState(player));
}
if (Input.GetMouseButtonDown(0)) {
player.StateMachine.ChangeState(new AttackState(player));
}
}
public void FixedUpdate() { }
public void Exit() {
Debug.Log("离开Idle状态");
}
}
// 具体状态:跑步
public class RunState : IState {
private PlayerController player;
private float moveSpeed = 5f;
public RunState(PlayerController player) {
this.player = player;
}
public void Enter() {
Debug.Log("进入Run状态");
player.Animator.Play("Run");
}
public void Update() {
if (Input.GetAxis("Horizontal") == 0 && Input.GetAxis("Vertical") == 0) {
player.StateMachine.ChangeState(new IdleState(player));
}
if (Input.GetKeyDown(KeyCode.Space)) {
player.StateMachine.ChangeState(new JumpState(player));
}
}
public void FixedUpdate() {
// 移动逻辑
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
Vector3 direction = new Vector3(horizontal, 0, vertical).normalized;
player.Rigidbody.MovePosition(
player.transform.position + direction * moveSpeed * Time.fixedDeltaTime
);
}
public void Exit() { }
}
// 具体状态:跳跃
public class JumpState : IState {
private PlayerController player;
private float jumpForce = 5f;
public JumpState(PlayerController player) {
this.player = player;
}
public void Enter() {
Debug.Log("进入Jump状态");
player.Animator.Play("Jump");
player.Rigidbody.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
}
public void Update() {
// 检测落地
if (player.IsGrounded()) {
player.StateMachine.ChangeState(new IdleState(player));
}
}
public void FixedUpdate() { }
public void Exit() { }
}
// 具体状态:攻击
public class AttackState : IState {
private PlayerController player;
private float attackDuration = 0.5f;
private float elapsedTime;
public AttackState(PlayerController player) {
this.player = player;
}
public void Enter() {
Debug.Log("进入Attack状态");
player.Animator.Play("Attack");
elapsedTime = 0;
// 攻击判定
Collider[] hitColliders = Physics.OverlapSphere(
player.transform.position + player.transform.forward,
1f
);
foreach (var col in hitColliders) {
if (col.CompareTag("Enemy")) {
col.GetComponent<Enemy>()?.TakeDamage(10);
}
}
}
public void Update() {
elapsedTime += Time.deltaTime;
// 攻击动画结束
if (elapsedTime >= attackDuration) {
player.StateMachine.ChangeState(new IdleState(player));
}
}
public void FixedUpdate() { }
public void Exit() { }
}
// 玩家控制器
public class PlayerController : MonoBehaviour {
public StateMachine StateMachine { get; private set; }
public Animator Animator { get; private set; }
public Rigidbody Rigidbody { get; private set; }
void Awake() {
StateMachine = new StateMachine();
Animator = GetComponent<Animator>();
Rigidbody = GetComponent<Rigidbody>();
}
void Start() {
// 初始状态
StateMachine.ChangeState(new IdleState(this));
}
void Update() {
StateMachine.Update();
}
void FixedUpdate() {
StateMachine.FixedUpdate();
}
public bool IsGrounded() {
return Physics.Raycast(transform.position, Vector3.down, 1.1f);
}
}
// 敌人AI状态机
public class EnemyAI : MonoBehaviour {
public enum State { Idle, Patrol, Chase, Attack }
private State currentState;
private Transform player;
private float detectionRange = 10f;
private float attackRange = 2f;
void Update() {
switch (currentState) {
case State.Idle:
IdleUpdate();
break;
case State.Patrol:
PatrolUpdate();
break;
case State.Chase:
ChaseUpdate();
break;
case State.Attack:
AttackUpdate();
break;
}
}
void IdleUpdate() {
if (PlayerInRange(detectionRange)) {
ChangeState(State.Chase);
}
}
void PatrolUpdate() {
// 巡逻逻辑
if (PlayerInRange(detectionRange)) {
ChangeState(State.Chase);
}
}
void ChaseUpdate() {
if (PlayerInRange(attackRange)) {
ChangeState(State.Attack);
} else if (!PlayerInRange(detectionRange)) {
ChangeState(State.Patrol);
} else {
// 追逐玩家
Vector3 direction = (player.position - transform.position).normalized;
transform.position += direction * 3f * Time.deltaTime;
}
}
void AttackUpdate() {
if (!PlayerInRange(attackRange)) {
ChangeState(State.Chase);
} else {
// 攻击逻辑
}
}
void ChangeState(State newState) {
currentState = newState;
Debug.Log($"Enemy state changed to: {newState}");
}
bool PlayerInRange(float range) {
return Vector3.Distance(transform.position, player.position) < range;
}
}
应用场景:
- 角色控制器(Idle/Run/Jump/Attack)
- AI状态机
- UI状态管理
- 游戏流程(Menu/Playing/Paused/GameOver)
13. 策略模式(Strategy) ⭐⭐⭐⭐⭐
// 封装算法,使其可以互换
public interface IAttackStrategy {
void Attack(Enemy enemy);
}
// 具体策略:近战攻击
public class MeleeAttackStrategy : IAttackStrategy {
public void Attack(Enemy enemy) {
Debug.Log("近战攻击");
Collider[] hits = Physics.OverlapSphere(enemy.transform.position, 2f);
foreach (var hit in hits) {
if (hit.CompareTag("Enemy")) {
hit.GetComponent<Enemy>()?.TakeDamage(10);
}
}
}
}
// 具体策略:远程攻击
public class RangedAttackStrategy : IAttackStrategy {
private GameObject bulletPrefab;
public RangedAttackStrategy(GameObject bulletPrefab) {
this.bulletPrefab = bulletPrefab;
}
public void Attack(Enemy enemy) {
Debug.Log("远程攻击");
GameObject bullet = Object.Instantiate(bulletPrefab);
bullet.transform.position = enemy.transform.position;
Vector3 direction = (enemy.transform.forward).normalized;
bullet.GetComponent<Rigidbody>().velocity = direction * 10f;
}
}
// 具体策略:魔法攻击
public class MagicAttackStrategy : IAttackStrategy {
private ParticleSystem magicEffect;
public MagicAttackStrategy(ParticleSystem effect) {
this.magicEffect = effect;
}
public void Attack(Enemy enemy) {
Debug.Log("魔法攻击");
ParticleSystem effect = Object.Instantiate(magicEffect);
effect.transform.position = enemy.transform.position;
effect.Play();
// AOE伤害
Collider[] hits = Physics.OverlapSphere(enemy.transform.position, 5f);
foreach (var hit in hits) {
if (hit.CompareTag("Enemy")) {
hit.GetComponent<Enemy>()?.TakeDamage(15);
}
}
}
}
// 使用策略的类
public class Weapon : MonoBehaviour {
private IAttackStrategy attackStrategy;
public void SetAttackStrategy(IAttackStrategy strategy) {
attackStrategy = strategy;
}
public void Attack() {
attackStrategy?.Attack(GetComponent<Enemy>());
}
}
// 使用
public class Player : MonoBehaviour {
private Weapon weapon;
void Start() {
weapon = GetComponent<Weapon>();
// 初始策略:近战
weapon.SetAttackStrategy(new MeleeAttackStrategy());
}
void Update() {
if (Input.GetKeyDown(KeyCode.Alpha1)) {
// 切换到近战
weapon.SetAttackStrategy(new MeleeAttackStrategy());
}
else if (Input.GetKeyDown(KeyCode.Alpha2)) {
// 切换到远程
weapon.SetAttackStrategy(new RangedAttackStrategy(bulletPrefab));
}
else if (Input.GetKeyDown(KeyCode.Alpha3)) {
// 切换到魔法
weapon.SetAttackStrategy(new MagicAttackStrategy(magicEffectPrefab));
}
if (Input.GetKeyDown(KeyCode.Space)) {
weapon.Attack();
}
}
public GameObject bulletPrefab;
public ParticleSystem magicEffectPrefab;
}
// 寻路策略
public interface IPathfindingStrategy {
List<Vector3> FindPath(Vector3 start, Vector3 end);
}
public class AStarStrategy : IPathfindingStrategy {
public List<Vector3> FindPath(Vector3 start, Vector3 end) {
Debug.Log("使用A*寻路");
// A*算法实现
return new List<Vector3>();
}
}
public class DijkstraStrategy : IPathfindingStrategy {
public List<Vector3> FindPath(Vector3 start, Vector3 end) {
Debug.Log("使用Dijkstra寻路");
// Dijkstra算法实现
return new List<Vector3>();
}
}
public class NavMeshStrategy : IPathfindingStrategy {
public List<Vector3> FindPath(Vector3 start, Vector3 end) {
Debug.Log("使用NavMesh寻路");
// Unity NavMesh
return new List<Vector3>();
}
}
// AI根据地形选择寻路策略
public class AIController : MonoBehaviour {
private IPathfindingStrategy pathfinding;
void Start() {
// 根据场景选择策略
if (IsIndoorScene()) {
pathfinding = new NavMeshStrategy();
} else if (IsLargeOpenWorld()) {
pathfinding = new AStarStrategy();
} else {
pathfinding = new DijkstraStrategy();
}
}
void MoveTo(Vector3 target) {
List<Vector3> path = pathfinding.FindPath(transform.position, target);
// 沿路径移动
}
bool IsIndoorScene() { return true; }
bool IsLargeOpenWorld() { return false; }
}
应用场景:
- 不同的攻击方式
- 不同的寻路算法
- 不同的排序算法
- 不同的存档格式
14. 模板方法模式(Template Method) ⭐⭐⭐⭐
// 定义算法骨架,子类实现具体步骤
public abstract class GameLevel {
// 模板方法(定义流程)
public void PlayLevel() {
LoadAssets();
InitializeLevel();
SpawnPlayer();
SpawnEnemies();
StartGameLoop();
// 可选步骤
if (HasBoss()) {
SpawnBoss();
}
CleanUp();
}
// 抽象方法(子类必须实现)
protected abstract void LoadAssets();
protected abstract void InitializeLevel();
protected abstract void SpawnEnemies();
// 钩子方法(子类可选实现)
protected virtual bool HasBoss() => false;
protected virtual void SpawnBoss() { }
// 具体方法(共用实现)
protected void SpawnPlayer() {
Debug.Log("生成玩家");
}
protected void StartGameLoop() {
Debug.Log("开始游戏循环");
}
protected void CleanUp() {
Debug.Log("清理资源");
}
}
// 具体实现:森林关卡
public class ForestLevel : GameLevel {
protected override void LoadAssets() {
Debug.Log("加载森林资源");
}
protected override void InitializeLevel() {
Debug.Log("初始化森林地形");
}
protected override void SpawnEnemies() {
Debug.Log("生成森林怪物:哥布林、树人");
}
}
// 具体实现:地下城关卡
public class DungeonLevel : GameLevel {
protected override void LoadAssets() {
Debug.Log("加载地下城资源");
}
protected override void InitializeLevel() {
Debug.Log("初始化地下城");
}
protected override void SpawnEnemies() {
Debug.Log("生成地下城怪物:骷髅、恶魔");
}
protected override bool HasBoss() => true;
protected override void SpawnBoss() {
Debug.Log("生成Boss:恶魔领主");
}
}
// 使用
public class GameManager : MonoBehaviour {
void StartLevel(int levelIndex) {
GameLevel level;
switch (levelIndex) {
case 1:
level = new ForestLevel();
break;
case 2:
level = new DungeonLevel();
break;
default:
return;
}
level.PlayLevel();
}
}
// UI动画模板
public abstract class UIAnimation {
public void PlayAnimation() {
Prepare();
AnimateIn();
Hold();
AnimateOut();
Complete();
}
protected virtual void Prepare() {
Debug.Log("准备动画");
}
protected abstract void AnimateIn();
protected abstract void AnimateOut();
protected virtual void Hold() {
// 默认停留1秒
System.Threading.Thread.Sleep(1000);
}
protected virtual void Complete() {
Debug.Log("动画完成");
}
}
public class FadeAnimation : UIAnimation {
private CanvasGroup canvasGroup;
public FadeAnimation(CanvasGroup cg) {
canvasGroup = cg;
}
protected override void AnimateIn() {
Debug.Log("淡入");
canvasGroup.alpha = 0;
// DOTween.To(() => canvasGroup.alpha, x => canvasGroup.alpha = x, 1, 0.5f);
}
protected override void AnimateOut() {
Debug.Log("淡出");
// DOTween.To(() => canvasGroup.alpha, x => canvasGroup.alpha = x, 0, 0.5f);
}
}
public class ScaleAnimation : UIAnimation {
private Transform target;
public ScaleAnimation(Transform t) {
target = t;
}
protected override void AnimateIn() {
Debug.Log("缩放进入");
target.localScale = Vector3.zero;
// DOTween.To(() => target.localScale, x => target.localScale = x, Vector3.one, 0.5f);
}
protected override void AnimateOut() {
Debug.Log("缩放退出");
// DOTween.To(() => target.localScale, x => target.localScale = x, Vector3.zero, 0.5f);
}
}
15. 责任链模式(Chain of Responsibility) ⭐⭐⭐⭐
// 请求沿着处理者链传递
public abstract class DamageHandler {
protected DamageHandler nextHandler;
public void SetNext(DamageHandler handler) {
nextHandler = handler;
}
public abstract int HandleDamage(int damage, DamageType type);
}
public enum DamageType {
Physical,
Magic,
Fire,
Ice,
Poison
}
// 护甲处理器
public class ArmorHandler : DamageHandler {
private int armorValue = 10;
public override int HandleDamage(int damage, DamageType type) {
if (type == DamageType.Physical) {
damage = Mathf.Max(0, damage - armorValue);
Debug.Log($"护甲减免,剩余伤害: {damage}");
}
return nextHandler != null ? nextHandler.HandleDamage(damage, type) : damage;
}
}
// 魔抗处理器
public class MagicResistHandler : DamageHandler {
private float resistPercent = 0.3f;
public override int HandleDamage(int damage, DamageType type) {
if (type == DamageType.Magic) {
damage = Mathf.RoundToInt(damage * (1 - resistPercent));
Debug.Log($"魔抗减免,剩余伤害: {damage}");
}
return nextHandler != null ? nextHandler.HandleDamage(damage, type) : damage;
}
}
// 护盾处理器
public class ShieldHandler : DamageHandler {
private int shieldValue = 50;
public override int HandleDamage(int damage, DamageType type) {
if (shieldValue > 0) {
int absorbed = Mathf.Min(damage, shieldValue);
shieldValue -= absorbed;
damage -= absorbed;
Debug.Log($"护盾吸收{absorbed}伤害,剩余伤害: {damage}");
}
return nextHandler != null ? nextHandler.HandleDamage(damage, type) : damage;
}
}
// Buff处理器
public class BuffHandler : DamageHandler {
private bool hasImmunity = false;
private float damageReduction = 0.2f;
public override int HandleDamage(int damage, DamageType type) {
if (hasImmunity) {
Debug.Log("免疫伤害");
return 0;
}
damage = Mathf.RoundToInt(damage * (1 - damageReduction));
Debug.Log($"Buff减免,剩余伤害: {damage}");
return nextHandler != null ? nextHandler.HandleDamage(damage, type) : damage;
}
}
// 使用责任链
public class Character : MonoBehaviour {
private DamageHandler damageChain;
private int health = 100;
void Start() {
// 构建责任链
damageChain = new ShieldHandler();
var armorHandler = new ArmorHandler();
var magicResistHandler = new MagicResistHandler();
var buffHandler = new BuffHandler();
damageChain.SetNext(armorHandler);
armorHandler.SetNext(magicResistHandler);
magicResistHandler.SetNext(buffHandler);
}
public void TakeDamage(int damage, DamageType type) {
// 伤害经过责任链处理
int finalDamage = damageChain.HandleDamage(damage, type);
health -= finalDamage;
Debug.Log($"最终受到{finalDamage}伤害,剩余血量: {health}");
}
}
// 使用
character.TakeDamage(100, DamageType.Physical);
// 输出:
// 护盾吸收50伤害,剩余伤害: 50
// 护甲减免,剩余伤害: 40
// Buff减免,剩余伤害: 32
// 最终受到32伤害,剩余血量: 68
// 输入处理链
public abstract class InputHandler {
protected InputHandler nextHandler;
public void SetNext(InputHandler handler) {
nextHandler = handler;
}
public abstract bool Handle(KeyCode key);
}
public class UIInputHandler : InputHandler {
public override bool Handle(KeyCode key) {
if (key == KeyCode.Escape) {
Debug.Log("UI处理:打开菜单");
return true; // 处理完毕,不传递
}
return nextHandler != null && nextHandler.Handle(key);
}
}
public class PlayerInputHandler : InputHandler {
public override bool Handle(KeyCode key) {
if (key == KeyCode.Space) {
Debug.Log("玩家处理:跳跃");
return true;
}
return nextHandler != null && nextHandler.Handle(key);
}
}
public class CheatInputHandler : InputHandler {
public override bool Handle(KeyCode key) {
if (key == KeyCode.F1) {
Debug.Log("作弊处理:无敌模式");
return true;
}
return nextHandler != null && nextHandler.Handle(key);
}
}
16. 访问者模式(Visitor) ⭐⭐⭐
// 在不修改类结构的情况下添加新操作
public interface IVisitor {
void Visit(Player player);
void Visit(Enemy enemy);
void Visit(NPC npc);
}
public interface IVisitable {
void Accept(IVisitor visitor);
}
// 具体访问者:治疗访问者
public class HealVisitor : IVisitor {
private int healAmount = 20;
public void Visit(Player player) {
player.Health += healAmount;
Debug.Log($"玩家恢复{healAmount}生命值");
}
public void Visit(Enemy enemy) {
// 敌人不受治疗影响
Debug.Log("敌人不能被治疗");
}
public void Visit(NPC npc) {
npc.Health += healAmount;
Debug.Log($"NPC恢复{healAmount}生命值");
}
}
// 具体访问者:伤害访问者
public class DamageVisitor : IVisitor {
private int damageAmount = 50;
public void Visit(Player player) {
player.Health -= damageAmount;
Debug.Log($"玩家受到{damageAmount}伤害");
}
public void Visit(Enemy enemy) {
enemy.Health -= damageAmount * 2; // 敌人受到双倍伤害
Debug.Log($"敌人受到{damageAmount * 2}伤害");
}
public void Visit(NPC npc) {
npc.Health -= damageAmount / 2; // NPC只受到一半伤害
Debug.Log($"NPC受到{damageAmount / 2}伤害");
}
}
// 具体访问者:属性显示访问者
public class InfoVisitor : IVisitor {
public void Visit(Player player) {
Debug.Log($"玩家信息 - 生命:{player.Health}, 等级:{player.Level}");
}
public void Visit(Enemy enemy) {
Debug.Log($"敌人信息 - 生命:{enemy.Health}, 类型:{enemy.EnemyType}");
}
public void Visit(NPC npc) {
Debug.Log($"NPC信息 - 生命:{npc.Health}, 名字:{npc.Name}");
}
}
// 可访问的对象
public class Player : MonoBehaviour, IVisitable {
public int Health = 100;
public int Level = 1;
public void Accept(IVisitor visitor) {
visitor.Visit(this);
}
}
public class Enemy : MonoBehaviour, IVisitable {
public int Health = 50;
public string EnemyType = "Goblin";
public void Accept(IVisitor visitor) {
visitor.Visit(this);
}
}
public class NPC : MonoBehaviour, IVisitable {
public int Health = 80;
public string Name = "村民";
public void Accept(IVisitor visitor) {
visitor.Visit(this);
}
}
// 使用示例
public class GameController : MonoBehaviour {
void Start() {
List<IVisitable> entities = new List<IVisitable> {
new Player(),
new Enemy(),
new NPC()
};
// 治疗所有单位
IVisitor healVisitor = new HealVisitor();
foreach (var entity in entities) {
entity.Accept(healVisitor);
}
// 对所有单位造成伤害
IVisitor damageVisitor = new DamageVisitor();
foreach (var entity in entities) {
entity.Accept(damageVisitor);
}
// 显示所有单位信息
IVisitor infoVisitor = new InfoVisitor();
foreach (var entity in entities) {
entity.Accept(infoVisitor);
}
}
}
// Buff系统使用访问者
public class BuffVisitor : IVisitor {
public enum BuffType { Speed, Damage, Defense }
private BuffType buffType;
private float buffValue;
public BuffVisitor(BuffType type, float value) {
buffType = type;
buffValue = value;
}
public void Visit(Player player) {
switch (buffType) {
case BuffType.Speed:
player.MoveSpeed *= buffValue;
break;
case BuffType.Damage:
player.AttackDamage += (int)buffValue;
break;
case BuffType.Defense:
player.Defense += (int)buffValue;
break;
}
}
public void Visit(Enemy enemy) {
// 敌人不受Buff影响
}
public void Visit(NPC npc) {
// NPC不受Buff影响
}
}
应用场景:
- Buff/Debuff系统
- AOE技能效果
- 场景对象批量操作
- 数据统计/序列化
17. 中介者模式(Mediator) ⭐⭐⭐⭐
// 用中介者对象封装对象间的交互
public interface IMediator {
void Notify(Component sender, string eventName);
}
// 战斗系统中介者
public class BattleMediator : IMediator {
private Player player;
private List<Enemy> enemies = new List<Enemy>();
private BattleUI ui;
private ScoreSystem scoreSystem;
public void RegisterPlayer(Player p) {
player = p;
player.SetMediator(this);
}
public void RegisterEnemy(Enemy e) {
enemies.Add(e);
e.SetMediator(this);
}
public void RegisterUI(BattleUI battleUI) {
ui = battleUI;
}
public void RegisterScoreSystem(ScoreSystem score) {
scoreSystem = score;
}
public void Notify(Component sender, string eventName) {
switch (eventName) {
case "PlayerAttack":
OnPlayerAttack();
break;
case "EnemyDead":
OnEnemyDead(sender as Enemy);
break;
case "PlayerTakeDamage":
OnPlayerTakeDamage();
break;
case "PlayerDead":
OnPlayerDead();
break;
}
}
void OnPlayerAttack() {
// 找最近的敌人
Enemy nearestEnemy = FindNearestEnemy();
if (nearestEnemy != null) {
nearestEnemy.TakeDamage(player.AttackDamage);
}
}
void OnEnemyDead(Enemy enemy) {
enemies.Remove(enemy);
scoreSystem.AddScore(100);
ui.UpdateEnemyCount(enemies.Count);
// 检查胜利条件
if (enemies.Count == 0) {
ui.ShowVictory();
}
}
void OnPlayerTakeDamage() {
ui.UpdateHealthBar(player.Health, player.MaxHealth);
// 屏幕震动
Camera.main.GetComponent<CameraShake>()?.Shake();
}
void OnPlayerDead() {
// 停止所有敌人AI
foreach (var enemy in enemies) {
enemy.Stop();
}
ui.ShowGameOver();
scoreSystem.SaveHighScore();
}
Enemy FindNearestEnemy() {
Enemy nearest = null;
float minDistance = float.MaxValue;
foreach (var enemy in enemies) {
float distance = Vector3.Distance(player.transform.position, enemy.transform.position);
if (distance < minDistance) {
minDistance = distance;
nearest = enemy;
}
}
return nearest;
}
}
// 组件基类
public abstract class Component : MonoBehaviour {
protected IMediator mediator;
public void SetMediator(IMediator m) {
mediator = m;
}
}
// 玩家
public class Player : Component {
public int Health = 100;
public int MaxHealth = 100;
public int AttackDamage = 10;
public void Attack() {
mediator?.Notify(this, "PlayerAttack");
}
public void TakeDamage(int damage) {
Health -= damage;
mediator?.Notify(this, "PlayerTakeDamage");
if (Health <= 0) {
mediator?.Notify(this, "PlayerDead");
}
}
}
// 敌人
public class Enemy : Component {
public int Health = 50;
public void TakeDamage(int damage) {
Health -= damage;
if (Health <= 0) {
mediator?.Notify(this, "EnemyDead");
Destroy(gameObject);
}
}
public void Stop() {
// 停止AI
GetComponent<EnemyAI>().enabled = false;
}
}
// UI管理器中介者
public class UIMediator : MonoBehaviour {
private Dictionary<string, UIPanel> panels = new Dictionary<string, UIPanel>();
public void RegisterPanel(string name, UIPanel panel) {
panels[name] = panel;
panel.SetMediator(this);
}
public void ShowPanel(string name) {
// 隐藏所有面板
foreach (var panel in panels.Values) {
panel.Hide();
}
// 显示指定面板
if (panels.TryGetValue(name, out UIPanel targetPanel)) {
targetPanel.Show();
}
}
public void OnButtonClick(string buttonName) {
switch (buttonName) {
case "StartGame":
ShowPanel("GamePanel");
break;
case "Settings":
ShowPanel("SettingsPanel");
break;
case "Back":
ShowPanel("MainMenu");
break;
}
}
}
public class UIPanel : MonoBehaviour {
protected UIMediator mediator;
public void SetMediator(UIMediator m) {
mediator = m;
}
public virtual void Show() {
gameObject.SetActive(true);
}
public virtual void Hide() {
gameObject.SetActive(false);
}
}
应用场景:
- 战斗系统协调
- UI面板管理
- 多人联机通信
- 游戏流程控制
18. 备忘录模式(Memento) ⭐⭐⭐⭐
// 保存和恢复对象状态
// 存档系统
[System.Serializable]
public class GameMemento {
public int playerLevel;
public int playerHealth;
public Vector3 playerPosition;
public List<int> inventory;
public Dictionary<string, bool> questStatus;
public float playTime;
public string saveTime;
public GameMemento(GameState state) {
playerLevel = state.Level;
playerHealth = state.Health;
playerPosition = state.Position;
inventory = new List<int>(state.Inventory);
questStatus = new Dictionary<string, bool>(state.QuestStatus);
playTime = state.PlayTime;
saveTime = System.DateTime.Now.ToString();
}
}
// 游戏状态(原发器)
public class GameState {
public int Level = 1;
public int Health = 100;
public Vector3 Position = Vector3.zero;
public List<int> Inventory = new List<int>();
public Dictionary<string, bool> QuestStatus = new Dictionary<string, bool>();
public float PlayTime = 0;
// 创建备忘录
public GameMemento CreateMemento() {
return new GameMemento(this);
}
// 从备忘录恢复
public void RestoreMemento(GameMemento memento) {
Level = memento.playerLevel;
Health = memento.playerHealth;
Position = memento.playerPosition;
Inventory = new List<int>(memento.inventory);
QuestStatus = new Dictionary<string, bool>(memento.questStatus);
PlayTime = memento.playTime;
}
}
// 存档管理器(守护者)
public class SaveManager : MonoBehaviour {
private const string SAVE_KEY = "GameSave_";
private Dictionary<int, GameMemento> saveSlots = new Dictionary<int, GameMemento>();
public void Save(int slotIndex, GameState state) {
GameMemento memento = state.CreateMemento();
saveSlots[slotIndex] = memento;
// 序列化保存
string json = JsonUtility.ToJson(memento);
PlayerPrefs.SetString(SAVE_KEY + slotIndex, json);
PlayerPrefs.Save();
Debug.Log($"游戏保存到插槽{slotIndex}");
}
public void Load(int slotIndex, GameState state) {
string json = PlayerPrefs.GetString(SAVE_KEY + slotIndex, "");
if (!string.IsNullOrEmpty(json)) {
GameMemento memento = JsonUtility.FromJson<GameMemento>(json);
state.RestoreMemento(memento);
saveSlots[slotIndex] = memento;
Debug.Log($"从插槽{slotIndex}加载游戏");
} else {
Debug.LogWarning($"插槽{slotIndex}没有存档");
}
}
public bool HasSave(int slotIndex) {
return PlayerPrefs.HasKey(SAVE_KEY + slotIndex);
}
public void DeleteSave(int slotIndex) {
PlayerPrefs.DeleteKey(SAVE_KEY + slotIndex);
saveSlots.Remove(slotIndex);
}
public GameMemento GetSaveInfo(int slotIndex) {
if (saveSlots.TryGetValue(slotIndex, out GameMemento memento)) {
return memento;
}
string json = PlayerPrefs.GetString(SAVE_KEY + slotIndex, "");
if (!string.IsNullOrEmpty(json)) {
return JsonUtility.FromJson<GameMemento>(json);
}
return null;
}
}
// 使用示例
public class GameManager : MonoBehaviour {
private GameState gameState;
private SaveManager saveManager;
void Start() {
gameState = new GameState();
saveManager = GetComponent<SaveManager>();
}
void Update() {
// F5快速保存
if (Input.GetKeyDown(KeyCode.F5)) {
saveManager.Save(0, gameState);
}
// F9快速加载
if (Input.GetKeyDown(KeyCode.F9)) {
saveManager.Load(0, gameState);
}
}
}
// 撤销/重做系统(使用备忘录)
public class EditorHistory {
private Stack<GameMemento> undoStack = new Stack<GameMemento>();
private Stack<GameMemento> redoStack = new Stack<GameMemento>();
private GameState currentState;
public EditorHistory(GameState state) {
currentState = state;
}
public void SaveState() {
undoStack.Push(currentState.CreateMemento());
redoStack.Clear(); // 新操作清空重做栈
}
public void Undo() {
if (undoStack.Count > 0) {
// 保存当前状态到重做栈
redoStack.Push(currentState.CreateMemento());
// 恢复上一个状态
GameMemento memento = undoStack.Pop();
currentState.RestoreMemento(memento);
Debug.Log("撤销");
}
}
public void Redo() {
if (redoStack.Count > 0) {
// 保存当前状态到撤销栈
undoStack.Push(currentState.CreateMemento());
// 恢复重做的状态
GameMemento memento = redoStack.Pop();
currentState.RestoreMemento(memento);
Debug.Log("重做");
}
}
}
应用场景:
- 存档系统
- 关卡编辑器(撤销/重做)
- 时间倒流机制
- 回放系统
19. 迭代器模式(Iterator) ⭐⭐⭐
// C#天生支持迭代器(foreach、IEnumerable)
// 自定义迭代器:背包系统
public class Inventory : IEnumerable<Item> {
private List<Item> items = new List<Item>();
public void AddItem(Item item) {
items.Add(item);
}
public void RemoveItem(Item item) {
items.Remove(item);
}
// 普通迭代器
public IEnumerator<Item> GetEnumerator() {
return items.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
// 自定义迭代器:只遍历武器
public IEnumerable<Item> GetWeapons() {
foreach (var item in items) {
if (item.Type == ItemType.Weapon) {
yield return item;
}
}
}
// 自定义迭代器:按稀有度排序
public IEnumerable<Item> GetItemsByRarity() {
return items.OrderByDescending(i => i.Rarity);
}
// 反向迭代器
public IEnumerable<Item> GetItemsReverse() {
for (int i = items.Count - 1; i >= 0; i--) {
yield return items[i];
}
}
}
public class Item {
public string Name;
public ItemType Type;
public int Rarity;
}
public enum ItemType {
Weapon,
Armor,
Potion,
Material
}
// 使用
public class PlayerInventory : MonoBehaviour {
private Inventory inventory = new Inventory();
void Start() {
// 添加物品
inventory.AddItem(new Item { Name = "剑", Type = ItemType.Weapon, Rarity = 3 });
inventory.AddItem(new Item { Name = "盾", Type = ItemType.Armor, Rarity = 2 });
// 遍历所有物品
foreach (var item in inventory) {
Debug.Log($"物品: {item.Name}");
}
// 只遍历武器
foreach (var weapon in inventory.GetWeapons()) {
Debug.Log($"武器: {weapon.Name}");
}
// 按稀有度遍历
foreach (var item in inventory.GetItemsByRarity()) {
Debug.Log($"稀有物品: {item.Name}, 稀有度: {item.Rarity}");
}
}
}
// 技能树迭代器
public class SkillTree {
private Dictionary<int, SkillNode> nodes = new Dictionary<int, SkillNode>();
public void AddNode(SkillNode node) {
nodes[node.Id] = node;
}
// 广度优先遍历
public IEnumerable<SkillNode> BreadthFirstTraversal(int startId) {
Queue<int> queue = new Queue<int>();
HashSet<int> visited = new HashSet<int>();
queue.Enqueue(startId);
visited.Add(startId);
while (queue.Count > 0) {
int currentId = queue.Dequeue();
SkillNode node = nodes[currentId];
yield return node;
foreach (var childId in node.Children) {
if (!visited.Contains(childId)) {
queue.Enqueue(childId);
visited.Add(childId);
}
}
}
}
// 深度优先遍历
public IEnumerable<SkillNode> DepthFirstTraversal(int startId) {
HashSet<int> visited = new HashSet<int>();
return DFSHelper(startId, visited);
}
private IEnumerable<SkillNode> DFSHelper(int nodeId, HashSet<int> visited) {
if (visited.Contains(nodeId)) {
yield break;
}
visited.Add(nodeId);
SkillNode node = nodes[nodeId];
yield return node;
foreach (var childId in node.Children) {
foreach (var child in DFSHelper(childId, visited)) {
yield return child;
}
}
}
}
public class SkillNode {
public int Id;
public string Name;
public List<int> Children = new List<int>();
}
🎮 Unity特有的模式
20. 组件模式(Component Pattern) ⭐⭐⭐⭐⭐
// Unity的核心设计模式
// GameObject + Component 架构
// 功能组件化
public class Health : MonoBehaviour {
public int maxHealth = 100;
private int currentHealth;
public event Action<int> OnHealthChanged;
public event Action OnDeath;
void Start() {
currentHealth = maxHealth;
}
public void TakeDamage(int damage) {
currentHealth -= damage;
OnHealthChanged?.Invoke(currentHealth);
if (currentHealth <= 0) {
OnDeath?.Invoke();
}
}
public void Heal(int amount) {
currentHealth = Mathf.Min(currentHealth + amount, maxHealth);
OnHealthChanged?.Invoke(currentHealth);
}
}
public class Mover : MonoBehaviour {
public float moveSpeed = 5f;
public void Move(Vector3 direction) {
transform.position += direction * moveSpeed * Time.deltaTime;
}
}
public class Shooter : MonoBehaviour {
public GameObject bulletPrefab;
public Transform firePoint;
public float fireRate = 0.5f;
private float nextFireTime;
public void Fire() {
if (Time.time >= nextFireTime) {
Instantiate(bulletPrefab, firePoint.position, firePoint.rotation);
nextFireTime = Time.time + fireRate;
}
}
}
// 组合组件
public class Player : MonoBehaviour {
private Health health;
private Mover mover;
private Shooter shooter;
void Awake() {
health = GetComponent<Health>();
mover = GetComponent<Mover>();
shooter = GetComponent<Shooter>();
}
void Update() {
// 移动
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
mover.Move(new Vector3(horizontal, 0, vertical));
// 射击
if (Input.GetButton("Fire1")) {
shooter.Fire();
}
}
}
21. 更新方法模式(Update Method) ⭐⭐⭐⭐⭐
// Unity的Update就是这个模式
// 集中管理更新逻辑
public class UpdateManager : MonoSingleton<UpdateManager> {
private List<IUpdatable> updatables = new List<IUpdatable>();
public void Register(IUpdatable updatable) {
if (!updatables.Contains(updatable)) {
updatables.Add(updatable);
}
}
public void Unregister(IUpdatable updatable) {
updatables.Remove(updatable);
}
void Update() {
// 统一调用所有注册对象的更新
for (int i = updatables.Count - 1; i >= 0; i--) {
updatables[i].OnUpdate(Time.deltaTime);
}
}
}
public interface IUpdatable {
void OnUpdate(float deltaTime);
}
// 不继承MonoBehaviour的类也能使用Update
public class CustomLogic : IUpdatable {
public void OnUpdate(float deltaTime) {
// 自定义更新逻辑
}
}
// 优化:分时更新
public class TimedUpdateManager : MonoSingleton<TimedUpdateManager> {
private Dictionary<float, List<Action>> timedUpdates = new Dictionary<float, List<Action>>();
public void RegisterTimedUpdate(float interval, Action callback) {
if (!timedUpdates.ContainsKey(interval)) {
timedUpdates[interval] = new List<Action>();
StartCoroutine(TimedUpdateCoroutine(interval));
}
timedUpdates[interval].Add(callback);
}
IEnumerator TimedUpdateCoroutine(float interval) {
WaitForSeconds wait = new WaitForSeconds(interval);
while (true) {
yield return wait;
if (timedUpdates.TryGetValue(interval, out List<Action> callbacks)) {
foreach (var callback in callbacks) {
callback?.Invoke();
}
}
}
}
}
// 使用
public class Enemy : MonoBehaviour {
void Start() {
// 每秒更新一次AI(性能优化)
TimedUpdateManager.Instance.RegisterTimedUpdate(1f, UpdateAI);
}
void UpdateAI() {
// AI逻辑
}
}
22. 脏标记模式(Dirty Flag) ⭐⭐⭐⭐
// 只在需要时才重新计算
public class Transform2D {
private Vector2 localPosition;
private float localRotation;
private Vector2 localScale = Vector2.one;
private Matrix3x3 localMatrix;
private Matrix3x3 worldMatrix;
private bool isLocalDirty = true;
private bool isWorldDirty = true;
private Transform2D parent;
public Vector2 LocalPosition {
get => localPosition;
set {
localPosition = value;
SetDirty();
}
}
public float LocalRotation {
get => localRotation;
set {
localRotation = value;
SetDirty();
}
}
public Matrix3x3 WorldMatrix {
get {
if (isWorldDirty) {
UpdateWorldMatrix();
}
return worldMatrix;
}
}
private void SetDirty() {
isLocalDirty = true;
isWorldDirty = true;
// 递归标记所有子节点为脏
foreach (var child in GetChildren()) {
child.SetDirty();
}
}
private void UpdateWorldMatrix() {
if (isLocalDirty) {
UpdateLocalMatrix();
}
if (parent != null) {
worldMatrix = parent.WorldMatrix * localMatrix;
} else {
worldMatrix = localMatrix;
}
isWorldDirty = false;
}
private void UpdateLocalMatrix() {
// 计算本地矩阵(TRS)
localMatrix = Matrix3x3.TRS(localPosition, localRotation, localScale);
isLocalDirty = false;
}
private List<Transform2D> GetChildren() {
return new List<Transform2D>();
}
}
// Mesh合批优化使用脏标记
public class BatchRenderer : MonoBehaviour {
private List<MeshData> meshes = new List<MeshData>();
private Mesh combinedMesh;
private bool isDirty = false;
public void AddMesh(MeshData mesh) {
meshes.Add(mesh);
isDirty = true;
}
public void RemoveMesh(MeshData mesh) {
meshes.Remove(mesh);
isDirty = true;
}
void LateUpdate() {
// 只在有修改时才重新合并Mesh
if (isDirty) {
RebuildCombinedMesh();
isDirty = false;
}
}
void RebuildCombinedMesh() {
CombineInstance[] combines = new CombineInstance[meshes.Count];
for (int i = 0; i < meshes.Count; i++) {
combines[i].mesh = meshes[i].mesh;
combines[i].transform = meshes[i].transform.localToWorldMatrix;
}
combinedMesh = new Mesh();
combinedMesh.CombineMeshes(combines);
GetComponent<MeshFilter>().mesh = combinedMesh;
}
}
public class MeshData {
public Mesh mesh;
public Transform transform;
}
// 简单示例
public struct Matrix3x3 {
public static Matrix3x3 TRS(Vector2 pos, float rot, Vector2 scale) {
return new Matrix3x3();
}
public static Matrix3x3 operator *(Matrix3x3 a, Matrix3x3 b) {
return new Matrix3x3();
}
}
总结:以上一共22种设计模式,几乎涵盖了所有Unity的设计模式
✨随便写写
by 马克·哈默
1725

被折叠的 条评论
为什么被折叠?



