一、战斗系统架构设计原则
- 扩展性:支持快速添加新技能类型
- 网络同步:基于状态同步的预测与补偿
- 性能优化:批量处理战斗计算,对象池管理
- 解耦设计:模块化分离技能逻辑、效果表现、数值计算
二、技能系统核心实现
1. 技能数据配置(ScriptableObject)
[CreateAssetMenu(menuName = "Combat/SkillConfig")]
public class SkillConfig : ScriptableObject
{
public string skillID;
public float castTime = 0.5f;
public float cooldown = 2.0f;
public float attackRange = 5.0f;
public SkillTargetType targetType;
public GameObject castVFX;
public SkillBehavior behaviorPrefab;
[Header("Damage Settings")]
public DamageType damageType;
public float baseDamage;
public float criticalChance;
public float damageMultiplier = 1.0f;
}
2. 技能状态机(State Pattern)
public abstract class SkillState
{
protected SkillSystem skillSystem;
public SkillState(SkillSystem system) => skillSystem = system;
public virtual void Enter() {}
public virtual void Update() {}
public virtual void Exit() {}
}
public class CastingState : SkillState
{
private float timer;
public CastingState(SkillSystem system) : base(system) {}
public override void Enter()
{
timer = 0;
skillSystem.PlayCastAnimation();
skillSystem.SpawnVFX(skillSystem.CurrentSkill.castVFX);
}
public override void Update()
{
timer += Time.deltaTime;
if (timer >= skillSystem.CurrentSkill.castTime)
{
skillSystem.TransitionTo(new ExecutingState(skillSystem));
}
}
public override void Exit()
{
skillSystem.StopCastAnimation();
}
}
3. 技能行为基类(Strategy Pattern)
public abstract class SkillBehavior : MonoBehaviour
{
public abstract void Initialize(SkillConfig config, Transform caster);
protected abstract void ExecuteSkillLogic();
protected void ApplyDamageToTarget(CombatUnit target)
{
DamageCalculator.CalculateDamage(
caster.Stats,
target.Stats,
config.damageType,
config.baseDamage,
config.criticalChance,
config.damageMultiplier
);
}
// 通用效果处理方法
protected void PlayEffectAtPosition(Vector3 position)
{
EffectManager.Instance.PlayEffect(
config.hitEffect,
position,
Quaternion.identity
);
}
}
三、伤害计算系统
1. 属性修饰器接口
public interface IDamageModifier
{
float ModifyDamage(DamageContext context);
}
public class CriticalModifier : IDamageModifier
{
public float ModifyDamage(DamageContext context)
{
float critRoll = Random.value;
if (critRoll <= context.attacker.CriticalChance)
{
context.isCritical = true;
return context.attacker.CriticalMultiplier;
}
return 1.0f;
}
}
public class DefenseModifier : IDamageModifier
{
public float ModifyDamage(DamageContext context)
{
float defense = context.target.GetDefense(context.damageType);
return 1 - Mathf.Clamp01(defense / (defense + 500));
}
}
2. 组合式伤害计算
public class DamageCalculator
{
private static List<IDamageModifier> modifiers = new List<IDamageModifier>
{
new CriticalModifier(),
new DefenseModifier(),
new ElementalModifier(),
new BuffModifier()
};
public static DamageResult CalculateDamage(CharacterStats attacker,
CharacterStats defender, DamageType type, float baseDamage)
{
var context = new DamageContext(attacker, defender, type, baseDamage);
float finalMultiplier = 1.0f;
foreach (var modifier in modifiers)
{
finalMultiplier *= modifier.ModifyDamage(context);
}
return new DamageResult
{
damage = Mathf.FloorToInt(baseDamage * finalMultiplier),
isCritical = context.isCritical,
damageType = type
};
}
}
四、网络同步策略
1. 状态同步封装
[Command]
public void CmdCastSkill(int skillID, Vector3 targetPosition)
{
if (CanCastSkill(skillID))
{
StartCoroutine(ServerCastSkill(skillID, targetPosition));
RpcPlayCastEffects(targetPosition);
}
}
private IEnumerator ServerCastSkill(int skillID, Vector3 targetPos)
{
var skill = skillManager.GetSkill(skillID);
yield return new WaitForSeconds(skill.castTime);
foreach (var target in FindValidTargets(targetPos))
{
target.TakeDamage(CalculateFinalDamage(skill));
}
}
[ClientRpc]
private void RpcPlayCastEffects(Vector3 position)
{
if (!isLocalPlayer)
{
PlayRemoteCastEffects(position);
}
}
2. 客户端预测与补偿
public void ClientCastSkill(int skillID)
{
if (skillCooldown[skillID] > 0) return;
// 本地预测
predictedCooldown[skillID] = Time.time + skills[skillID].cooldown;
PlayLocalCastEffects();
// 发送命令到服务器
CmdCastSkill(skillID, currentTargetPosition);
// 启动补偿检测
StartCoroutine(ReconciliationCheck(skillID));
}
private IEnumerator ReconciliationCheck(int skillID)
{
yield return new WaitForSeconds(0.3f);
if (Mathf.Abs(predictedCooldown[skillID] - serverCooldown[skillID]) > 0.1f)
{
// 执行状态回滚
ResetSkillState(skillID);
}
}
五、性能优化实践
1. 批量处理战斗事件
public class CombatEventSystem : MonoBehaviour
{
private readonly Queue<CombatEvent> eventQueue = new Queue<CombatEvent>();
private const int MAX_PROCESS_PER_FRAME = 10;
private void Update()
{
int processed = 0;
while (eventQueue.Count > 0 && processed < MAX_PROCESS_PER_FRAME)
{
var evt = eventQueue.Dequeue();
ProcessEvent(evt);
processed++;
}
}
private void ProcessEvent(CombatEvent evt)
{
switch (evt.eventType)
{
case CombatEventType.Damage:
HandleDamageEvent((DamageEvent)evt);
break;
case CombatEventType.Heal:
HandleHealEvent((HealEvent)evt);
break;
// 其他事件类型...
}
}
}
2. 对象池管理
public class EffectPool : MonoBehaviour
{
private Dictionary<string, Queue<GameObject>> pool = new Dictionary<string, Queue<GameObject>>();
public GameObject GetEffect(string effectID)
{
if (!pool.ContainsKey(effectID))
{
pool[effectID] = new Queue<GameObject>();
}
if (pool[effectID].Count > 0)
{
var obj = pool[effectID].Dequeue();
obj.SetActive(true);
return obj;
}
else
{
return Instantiate(GetPrefab(effectID));
}
}
public void ReturnEffect(string effectID, GameObject obj)
{
obj.SetActive(false);
pool[effectID].Enqueue(obj);
}
}
六、总结与展望
本文实现的战斗系统具备以下特点:
- 通过状态模式实现清晰的技能流程控制
- 使用组合式修饰器实现灵活的战斗公式
- 基于命令模式的网络同步架构
- 对象池和批量处理保证性能表现
后续优化方向:
- 引入ECS架构优化大规模战斗场景
- 实现基于行为树的智能AI系统
- 添加技能连招组合系统
- 完善战斗回放与反作弊机制
以上代码示例展示了MMORPG战斗系统的核心实现思路,开发者可根据实际项目需求进行扩展和优化。建议通过配置表驱动技能参数,结合Addressables实现资源动态加载,最终构建出高性能、易扩展的战斗系统框架。