文章目录
🎮 策略模式(Strategy Pattern)深度解析
——以Unity实现灵活AI行为与动态伤害计算为核心案例
一、模式本质与核心价值
核心目标:
✅ 定义算法族,封装每个算法,使它们可互换
✅ 运行时动态切换算法,避免使用多重条件判断
✅ 符合开闭原则,易于扩展新算法
关键术语:
- Strategy(策略接口):定义算法族的通用接口
- ConcreteStrategy(具体策略):实现具体算法逻辑
- Context(上下文):持有策略引用,负责调用算法
数学表达:
设算法集合S = {s₁, s₂, …, sₙ},上下文C满足:
C.Algorithm = sᵢ → C.Execute() = sᵢ.Process()
二、经典UML结构
三、Unity实战代码(动态伤害计算系统)
1. 定义策略接口与上下文
public interface IDamageStrategy {
float CalculateDamage(Character attacker, Character target);
}
public class Weapon : MonoBehaviour {
private IDamageStrategy _damageStrategy;
public void SetStrategy(IDamageStrategy strategy) {
_damageStrategy = strategy;
}
public void Attack(Character attacker, Character target) {
float damage = _damageStrategy.CalculateDamage(attacker, target);
target.TakeDamage(damage);
}
}
2. 实现具体策略
// 物理伤害策略
public class PhysicalDamage : IDamageStrategy {
public float CalculateDamage(Character attacker, Character target) {
return attacker.Strength * 2 - target.Defense;
}
}
// 魔法伤害策略
public class MagicDamage : IDamageStrategy {
public float CalculateDamage(Character attacker, Character target) {
return attacker.Intelligence * 3 - target.MagicResist;
}
}
// 暴击伤害策略
public class CriticalStrike : IDamageStrategy {
[SerializeField] private float _critChance = 0.3f;
public float CalculateDamage(Character attacker, Character target) {
float baseDamage = attacker.Strength * 1.5f;
return Random.value < _critChance ? baseDamage * 2 : baseDamage;
}
}
3. 客户端使用
public class PlayerCombat : MonoBehaviour {
[SerializeField] private Weapon _sword;
void Update() {
if(Input.GetKeyDown(KeyCode.Alpha1)) {
_sword.SetStrategy(new PhysicalDamage());
}
if(Input.GetKeyDown(KeyCode.Alpha2)) {
_sword.SetStrategy(new MagicDamage());
}
if(Input.GetMouseButtonDown(0)) {
Character enemy = GetTargetEnemy();
_sword.Attack(GetComponent<Character>(), enemy);
}
}
}
四、模式进阶技巧
1. 策略组合
public class CompositeStrategy : IDamageStrategy {
private List<IDamageStrategy> _strategies = new();
public void AddStrategy(IDamageStrategy strategy) {
_strategies.Add(strategy);
}
public float CalculateDamage(Character attacker, Character target) {
return _strategies.Sum(s => s.CalculateDamage(attacker, target));
}
}
2. 策略工厂
public class DamageStrategyFactory {
public IDamageStrategy Create(WeaponType type) {
return type switch {
WeaponType.Sword => new PhysicalDamage(),
WeaponType.Staff => new MagicDamage(),
WeaponType.Dagger => new CriticalStrike(),
_ => throw new ArgumentException()
};
}
}
3. 数据驱动策略
[CreateAssetMenu]
public class DamageConfig : ScriptableObject {
public AnimationCurve DamageCurve;
public GameObject ImpactEffect;
}
public class ConfigurableDamage : IDamageStrategy {
private DamageConfig _config;
public float CalculateDamage(Character attacker, Character target) {
float levelFactor = _config.DamageCurve.Evaluate(attacker.Level);
return attacker.BaseDamage * levelFactor;
}
}
五、游戏开发典型应用场景
AI行为系统
public class NPCController { private IMovementStrategy _movementStrategy; public void SetMovementStrategy(IMovementStrategy strategy) { _movementStrategy = strategy; } void Update() { _movementStrategy.Move(transform); } }
技能效果系统
public class SkillSystem { private ISkillEffect _effect; public void CastSkill() { _effect.ApplyEffect(target); } }
成就解锁条件
public class AchievementCondition { private IUnlockStrategy _strategy; public bool CheckUnlock(Player player) { return _strategy.IsUnlocked(player); } }
物理材质系统
public class SurfaceResponse { private IBounceStrategy _bounceStrategy; public Vector3 CalculateBounce(Vector3 input) { return _bounceStrategy.CalculateBounce(input); } }
六、性能优化策略
策略 | 实现方式 | 适用场景 |
---|---|---|
策略缓存 | 对象池管理策略实例 | 高频策略切换 |
预编译策略 | 使用C#委托或表达式树 | 高性能计算场景 |
数据导向设计 | 策略参数结构体化 | 大量相似策略 |
异步加载 | 按需加载策略资源 | 复杂策略配置 |
七、模式对比与选择
维度 | 策略模式 | 状态模式 |
---|---|---|
关注点 | 算法实现 | 状态转换 |
切换机制 | 主动切换 | 自动转换 |
对象关系 | 平行策略 | 状态链 |
典型应用 | 伤害计算 | AI状态机 |
八、最佳实践原则
- 接口最小化:策略接口保持单一职责
- 无状态策略:尽量设计无状态的策略类
- 防御性编程:
public void SetStrategy(IDamageStrategy strategy) { _damageStrategy = strategy ?? throw new ArgumentNullException(); }
- 策略验证:
public bool IsStrategyValid() { return _damageStrategy != null && _damageStrategy.IsAvailable(); }
九、常见问题解决方案
Q1:如何处理策略间共享数据?
→ 使用上下文传递参数
public interface IStrategy {
void Execute(SharedData context);
}
public class SharedData {
public Character Attacker;
public Character Target;
public float EnvironmentFactor;
}
Q2:如何实现跨策略配置?
→ 使用策略配置中心
public class StrategyConfig : MonoBehaviour {
[SerializeField] private StrategyMapping[] _mappings;
public IStrategy GetStrategy(string key) {
return _mappings.FirstOrDefault(m => m.Key == key)?.Strategy;
}
}
[System.Serializable]
public class StrategyMapping {
public string Key;
public IStrategy Strategy;
}
Q3:如何调试策略执行流程?
→ 实现策略日志代理
public class LoggingStrategyProxy : IStrategy {
private IStrategy _wrapped;
public void Execute() {
Debug.Log($"开始执行策略:{_wrapped.GetType().Name}");
_wrapped.Execute();
Debug.Log("策略执行完成");
}
}
上一篇 【行为型之状态模式】深度剖析——Unity角色行为控制与AI决策的终极解决方案
下一篇 【行为型之模板方法模式】游戏开发实战——Unity标准化流程与可扩展架构的核心实现