游戏战斗系统编码思路
1. 战斗系统架构设计
1.1 核心组件分层
graph TD
A[输入层] --> B[逻辑层]
B --> C[表现层]
D[数据层] --> B
E[网络层] --> B
1.2 状态驱动设计
\(\text{战斗实体状态} = \begin{cases} \text{Idle} & \text{待机} \\ \text{Attack} & \text{攻击} \\ \text{Hit} & \text{受击} \\ \text{Skill} & \text{技能} \\ \text{Dead} & \text{死亡} \end{cases}\)
2. 伤害计算系统
2.1 基础公式
\(\text{最终伤害} = (\text{基础攻击} \times \text{暴击系数} - \text{防御减免}) \times \text{元素反应倍率}\)
2.2 属性克制关系
flowchart LR
火 --> 冰[+30%伤害]
冰 --> 雷[+25%伤害]
雷 --> 水[+20%伤害]
水 --> 火[+15%伤害]
3. 技能系统实现
3.1 技能数据结构
graph TD
A[技能数据层] --> B[技能逻辑层]
B --> C[技能表现层]
{
"skill_id": 1001,
"cooldown": 5.0,
"hit_count": 3,
"damage_ratio": 0.8,
"effect_prefab": "Assets/Effects/fireball.prefab",
"hit_sound": "Audio/SFX/fire_explosion.wav"
}
3.2 技能状态机
public abstract class SkillState : IState
{
public virtual void OnEnter() {}
public virtual void OnUpdate() {}
public virtual void OnExit() {}
protected void PlayVFX(GameObject prefab)
{
// 粒子特效播放逻辑
}
}
4. 连招系统设计
4.1 输入缓冲机制
class InputBuffer:
def __init__(self):
self.buffer = []
self.buffer_time = 0.3 # 秒
def add_input(self, input_type):
self.buffer.append({
'type': input_type,
'time': Time.time
})
def get_valid_input(self):
current_time = Time.time
return [i for i in self.buffer
if current_time - i['time'] <= self.buffer_time]
4.2 连招判定树
stateDiagram-v2
[*] --> Idle
Idle --> Attack1: 轻攻击
Attack1 --> Attack2: 0.5秒内轻攻击
Attack2 --> Attack3: 0.5秒内重攻击
Attack3 --> Special: 成功触发终结技
5. 网络同步方案
5.1 帧同步与状态同步对比
方案 | 带宽消耗 | 实现复杂度 | 适用场景 |
---|---|---|---|
帧同步 | 低 | 高 | 格斗/MOBA |
状态同步 | 高 | 中 | MMO/RPG |
5.2 伤害同步逻辑
[Command]
void CmdApplyDamage(int targetId, int skillId)
{
// 服务器验证
if(IsValidAttack(targetId, skillId))
{
int damage = CalculateDamage(skillId);
TargetRpcTakeDamage(targetId, damage);
}
}
6. 性能优化策略
6.1 碰撞检测优化
- 使用空间分区树(QuadTree/Octree)
- 伤害判定采用球体/胶囊体简化碰撞体
- 非活跃实体跳过检测
6.2 动画事件优化
void OnAttackFrameEvent(int frameIndex)
{
if(frameIndex == 12) // 关键帧触发伤害
{
ApplyHitBox();
}
}
7. 现代战斗系统趋势
7.1 物理引擎融合
- 布娃娃系统受击反应
- 基于力的击飞计算
- 可破坏环境交互
7.2 AI增强战斗
pie
title AI行为权重
"攻击倾向" : 45
"防御倾向" : 30
"走位策略" : 25
高级战斗系统实现专题
1. 《鬼泣》风格华丽连招系统实现
1.1 连招架构设计
classDiagram
class ComboSystem{
+InputBuffer buffer
+ComboTree comboTree
+EvaluateCombo() Skill
}
class ComboNode{
+string animation
+float cancelWindow
+ComboLink[] links
}
class ComboLink{
+InputType input
+ComboNode nextNode
}
ComboSystem --> ComboNode
ComboNode --> ComboLink
1.2 关键技术实现
1.2.1 动画取消窗口
// Unity示例:动画状态机行为脚本
public class ComboCancelState : StateMachineBehaviour
{
[Range(0,1)] public float cancelStart = 0.3f;
[Range(0,1)] public float cancelEnd = 0.7f;
override public void OnStateUpdate(Animator animator,
AnimatorStateInfo stateInfo,
int layerIndex)
{
float normalizedTime = stateInfo.normalizedTime % 1;
bool inCancelWindow = normalizedTime > cancelStart &&
normalizedTime < cancelEnd;
animator.SetBool("CanCancel", inCancelWindow);
}
}
1.2.2 风格评分系统
class StyleMeter:
def __init__(self):
self.points = 0
self.multiplier = 1
self.decay_rate = 0.5 # 点数每秒衰减率
def add_action(self, action_type):
base_points = {
'basic_attack': 50,
'aerial_attack': 80,
'dodge': 30,
'taunt': 100
}
self.points += base_points[action_type] * self.multiplier
self.multiplier = min(5, self.multiplier + 0.2)
def update(self, delta_time):
self.points = max(0, self.points - self.decay_rate * delta_time)
if self.points <= 0:
self.multiplier = 1
2. 《黑暗之魂》类锁定机制实现方案
2.1 锁定系统架构
sequenceDiagram
Player->>LockSystem: 按下锁定键
LockSystem->>TargetManager: 获取可锁定目标列表
TargetManager->>SpatialHash: 查询10m内敌人
SpatialHash-->>TargetManager: 返回候选目标
TargetManager->>LockSystem: 按优先级排序
LockSystem->>CameraController: 设置注视目标
2.2 关键技术实现
2.2.1 目标选择算法
public class LockOnTargetSelector : MonoBehaviour
{
[SerializeField] float maxDistance = 10f;
[SerializeField] float angleThreshold = 45f;
public Transform FindBestTarget(Vector3 playerPosition,
Vector3 playerForward)
{
Collider[] candidates = Physics.OverlapSphere(
playerPosition, maxDistance, LayerMask.GetMask("Enemy"));
Transform bestTarget = null;
float bestScore = float.MinValue;
foreach (var col in candidates)
{
Vector3 dirToTarget = (col.transform.position - playerPosition).normalized;
float angle = Vector3.Angle(playerForward, dirToTarget);
if (angle <= angleThreshold)
{
float distanceScore = 1 - Vector3.Distance(
playerPosition, col.transform.position) / maxDistance;
float angleScore = 1 - angle / angleThreshold;
float totalScore = distanceScore * 0.4f + angleScore * 0.6f;
if (totalScore > bestScore)
{
bestScore = totalScore;
bestTarget = col.transform;
}
}
}
return bestTarget;
}
}
2.2.2 相机混合控制
public class LockCamera : MonoBehaviour
{
public Transform target;
public float rotationSpeed = 5f;
public float positionLerpSpeed = 3f;
void LateUpdate()
{
if (target != null)
{
// 平滑旋转
Quaternion targetRotation = Quaternion.LookRotation(
target.position - transform.position);
transform.rotation = Quaternion.Slerp(
transform.rotation, targetRotation,
rotationSpeed * Time.deltaTime);
// 位置跟随
Vector3 idealPosition = CalculateIdealPosition();
transform.position = Vector3.Lerp(
transform.position, idealPosition,
positionLerpSpeed * Time.deltaTime);
}
}
Vector3 CalculateIdealPosition()
{
// 基于角色背后偏移量计算
return player.position - player.forward * 3f + Vector3.up * 1.5f;
}
}
3. 大规模战斗场景优化技巧
3.1 实体管理优化
3.1.1 分帧更新系统
public class BatchUpdateSystem : MonoBehaviour
{
private List<Enemy> activeEnemies = new List<Enemy>();
private int updatesPerFrame = 10;
void Update()
{
int count = Mathf.Min(updatesPerFrame, activeEnemies.Count);
for (int i = 0; i < count; i++)
{
int index = (Time.frameCount + i) % activeEnemies.Count;
activeEnemies[index].UpdateLogic();
}
}
}
3.1.2 LOD分级策略
graph TD
A[战斗实体] --> B{距离玩家}
B -->|<=5m| C[高精度模型]
B -->|5-15m| D[简化骨骼动画]
B -->|>15m| E[代理表示]
3.2 渲染优化方案
3.2.1 GPU Instancing材质
// Shader示例
UNITY_INSTANCING_BUFFER_START(Props)
UNITY_DEFINE_INSTANCED_PROP(float4, _ColorArray)
UNITY_DEFINE_INSTANCED_PROP(float, _HealthRatio)
UNITY_INSTANCING_BUFFER_END(Props)
void surf(Input IN, inout SurfaceOutputStandard o)
{
o.Albedo = UNITY_ACCESS_INSTANCED_PROP(Props, _ColorArray).rgb;
o.Emission = lerp(float3(1,0,0), float3(0,1,0),
UNITY_ACCESS_INSTANCED_PROP(Props, _HealthRatio));
}
3.2.2 可见性剔除优化
public class OcclusionCullingManager : MonoBehaviour
{
public Camera mainCamera;
public float checkInterval = 0.2f;
IEnumerator Start()
{
while (true)
{
Plane[] planes = GeometryUtility.CalculateFrustumPlanes(mainCamera);
foreach (var enemy in EnemyManager.Instance.Enemies)
{
bool visible = GeometryUtility.TestPlanesAABB(
planes, enemy.GetComponent<Renderer>().bounds);
enemy.SetLODLevel(visible ? LODLevel.High : LODLevel.Low);
}
yield return new WaitForSeconds(checkInterval);
}
}
}
3.3 网络同步优化
3.3.1 兴趣管理系统(AOI)
class AreaOfInterest:
def __init__(self, cell_size=10):
self.cells = defaultdict(set)
self.cell_size = cell_size
def update_entity(self, entity_id, position):
cell_x = int(position.x / self.cell_size)
cell_z = int(position.z / self.cell_size)
self.cells[(cell_x, cell_z)].add(entity_id)
def get_nearby_entities(self, position, radius):
result = set()
cells_in_radius = radius // self.cell_size
center_x = int(position.x / self.cell_size)
center_z = int(position.z / self.cell_size)
for x in range(center_x - cells_in_radius,
center_x + cells_in_radius + 1):
for z in range(center_z - cells_in_radius,
center_z + cells_in_radius + 1):
result.update(self.cells.get((x,z), set()))
return result
3.3.2 状态压缩同步
public class NetworkEnemy : NetworkBehaviour
{
[SyncVar(hook = nameof(OnHealthChanged))]
private ushort compressedHealth;
private void OnHealthChanged(ushort newValue)
{
float realHealth = newValue / 65535f * maxHealth;
UpdateHealthDisplay(realHealth);
}
[Command]
public void CmdTakeDamage(float damage)
{
currentHealth -= damage;
compressedHealth = (ushort)(currentHealth / maxHealth * 65535);
}
}