ARPG(Action Role-Playing Game,动作角色扮演游戏) 的战斗系统需要兼顾 操作性、打击感、技能组合、AI 交互 等多个方面。
本指南将详细解析 ARPG 战斗系统的核心要素、设计思路与优化方案,适用于 Unity、UE4 及自研引擎开发。
模块 | 功能 |
---|---|
角色控制(Character Controller) | 处理玩家输入、移动、攻击、技能释放 |
动画系统(Animation System) | 角色动画驱动攻击、技能、受击、闪避 |
技能系统(Skill System) | 管理技能释放、冷却、组合 |
伤害计算(Damage System) | 计算攻击伤害、暴击、防御、Buff |
碰撞检测(Hit Detection) | 使用 Hitbox、Raycast 进行伤害判定 |
敌人 AI(Enemy AI) | 控制敌人行为(巡逻、攻击、闪避) |
战斗 UI(Combat UI) | 显示 HP、MP、技能冷却等状态 |
左键 / X
右键 / Y
空格 / B
Q/E/R
Tab
Idle
→ Walk/Run
→ Attack
→ Skill
→ Dodge
→ Hit
→ Death
✅ 示例(Unity Animator)
animator.SetTrigger("Attack");
✅ 示例(UE4 动画蓝图)
void AMyCharacter::PlayAttackAnimation()
{
PlayAnimMontage(AttackMontage);
}
方式 | 优点 | 缺点 |
---|---|---|
Hitbox(碰撞体) | 精确,可匹配动画 | 需要手动调整 Hitbox |
Raycast(射线检测) | 适用于远程攻击 | 可能误伤未命中敌人 |
Trigger(触发器) | 适合范围技能 | 精度较低,可能误判 |
✅ 示例(Unity - Hitbox 检测)
void CheckHit()
{
Collider[] hitEnemies = Physics.OverlapSphere(attackPoint.position, attackRange, enemyLayers);
foreach (var enemy in hitEnemies)
{
enemy.GetComponent().TakeDamage(damage);
}
}
✅ 示例(UE4 - 碰撞体检测)
void AMyCharacter::OnAttack()
{
TArray HitActors;
AttackCollider->GetOverlappingActors(HitActors);
for (AActor* Actor : HitActors)
{
Actor->TakeDamage(AttackDamage, DamageEvent, GetController(), this);
}
}
字段 | 作用 |
---|---|
技能名称(Name) | 技能的名称 |
伤害(Damage) | 造成的基础伤害 |
冷却时间(Cooldown) | 释放后的等待时间 |
消耗(Cost) | MP / 体力消耗 |
技能类型(Type) | 近战、远程、AOE |
特效(VFX/SFX) | 视觉 / 音效表现 |
✅ 技能数据结构(C++)
USTRUCT(BlueprintType)
struct FSkillData
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FString Name;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
float Damage;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
float Cooldown;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
float Cost;
};
✅ 示例(C++ 技能释放)
void AMyCharacter::UseSkill(FSkillData Skill)
{
if (CurrentMana < Skill.Cost || IsCooldown) return;
CurrentMana -= Skill.Cost;
PlayAnimMontage(Skill.Animation);
StartCooldown(Skill.Cooldown);
}
✅ 示例(UE4 行为树 AI)
void AEnemyAI::OnSeePlayer(APawn* Player)
{
BlackboardComponent->SetValueAsObject("Target", Player);
AIController->MoveToActor(Player);
}
Damage = (BaseDamage + WeaponDamage) * (1 + Strength / 100) - TargetArmor;
✅ 示例(UE4 伤害计算)
float FinalDamage = BaseDamage * DamageMultiplier;
Target->TakeDamage(FinalDamage, DamageEvent, GetController(), this);
ARPG 战斗系统的核心:
合理设计战斗系统,使其既具有流畅的操作感,又能提供深度的策略性!
在 ARPG 游戏中,战斗日志(Combat Log) 主要用于:
✅ 记录战斗事件(攻击、技能、伤害、暴击、闪避等)
✅ 调试战斗系统(检测数值计算是否正确)
✅ UI 显示反馈(玩家可查看战斗详情)
✅ 多人战斗同步日志(用于 PvP、团队战斗)
本指南将介绍 战斗日志的架构设计、数据结构、存储方式(本地/网络)、UI 显示,适用于 Unity / UE4 / 自研引擎。
模块 | 作用 |
---|---|
CombatLogManager | 负责管理、记录战斗日志 |
CombatLogEntry | 具体的战斗日志数据结构 |
CombatLogStorage | 存储战斗日志(内存 / 文件 / 网络) |
CombatLogUI | 负责在 UI 上显示日志 |
一个战斗日志通常包含:
USTRUCT(BlueprintType)
struct FCombatLogEntry
{
GENERATED_BODY()
UPROPERTY(BlueprintReadOnly)
float Timestamp;
UPROPERTY(BlueprintReadOnly)
FString EventType;
UPROPERTY(BlueprintReadOnly)
FString AttackerName;
UPROPERTY(BlueprintReadOnly)
FString TargetName;
UPROPERTY(BlueprintReadOnly)
float Damage;
UPROPERTY(BlueprintReadOnly)
FString Effects;
FCombatLogEntry()
: Timestamp(0), Damage(0), EventType("Unknown"), Effects("None") {}
};
✅ 示例日志
[12:30:45] 玩家A 使用【火球术】对 敌人B 造成 300 伤害(暴击)
[12:30:46] 敌人B 使用【挥砍】对 玩家A 造成 120 伤害
[12:30:47] 玩家A 闪避了 敌人B 的攻击
[System.Serializable]
public struct CombatLogEntry
{
public float Timestamp;
public string EventType;
public string Attacker;
public string Target;
public float Damage;
public string Effects;
public CombatLogEntry(float timestamp, string eventType, string attacker, string target, float damage, string effects)
{
Timestamp = timestamp;
EventType = eventType;
Attacker = attacker;
Target = target;
Damage = damage;
Effects = effects;
}
}
UCLASS()
class MYGAME_API UCombatLogManager : public UObject
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadOnly)
TArray CombatLogs;
void AddLogEntry(FString EventType, FString Attacker, FString Target, float Damage, FString Effects)
{
FCombatLogEntry NewEntry;
NewEntry.Timestamp = FPlatformTime::Seconds();
NewEntry.EventType = EventType;
NewEntry.AttackerName = Attacker;
NewEntry.TargetName = Target;
NewEntry.Damage = Damage;
NewEntry.Effects = Effects;
CombatLogs.Add(NewEntry);
UE_LOG(LogTemp, Log, TEXT("[%f] %s 对 %s 造成 %f 伤害 (%s)"),
NewEntry.Timestamp, *Attacker, *Target, Damage, *Effects);
}
};
✅ 示例调用
CombatLogManager->AddLogEntry("技能攻击", "玩家A", "敌人B", 300, "暴击");
using System.Collections.Generic;
using UnityEngine;
public class CombatLogManager : MonoBehaviour
{
public List CombatLogs = new List();
public void AddLogEntry(string eventType, string attacker, string target, float damage, string effects)
{
CombatLogEntry newEntry = new CombatLogEntry(Time.time, eventType, attacker, target, damage, effects);
CombatLogs.Add(newEntry);
Debug.Log($"[{newEntry.Timestamp}] {attacker} 对 {target} 造成 {damage} 伤害 ({effects})");
}
}
✅ 示例调用
combatLogManager.AddLogEntry("技能攻击", "玩家A", "敌人B", 300, "暴击");
void SaveLogToFile()
{
FString LogFilePath = FPaths::ProjectSavedDir() + "CombatLog.txt";
FString LogContent;
for (const FCombatLogEntry& Log : CombatLogs)
{
LogContent += FString::Printf(TEXT("[%f] %s 对 %s 造成 %f 伤害 (%s)\n"),
Log.Timestamp, *Log.AttackerName, *Log.TargetName, Log.Damage, *Log.Effects);
}
FFileHelper::SaveStringToFile(LogContent, *LogFilePath);
}
using System.IO;
public void SaveLogToFile()
{
string logFilePath = Application.persistentDataPath + "/CombatLog.txt";
string logContent = "";
foreach (var log in CombatLogs)
{
logContent += $"[{log.Timestamp}] {log.Attacker} 对 {log.Target} 造成 {log.Damage} 伤害 ({log.Effects})\n";
}
File.WriteAllText(logFilePath, logContent);
}
组件 | 作用 |
---|---|
TextMeshPro(Unity)/ UTextBlock(UE4) | 显示日志内容 |
ScrollView / ScrollBox | 允许滚动查看日志 |
Clear Button | 清空日志 |
using UnityEngine;
using TMPro;
public class CombatLogUI : MonoBehaviour
{
public TextMeshProUGUI logText;
private CombatLogManager logManager;
void Start()
{
logManager = FindObjectOfType();
UpdateLogUI();
}
public void UpdateLogUI()
{
logText.text = "";
foreach (var log in logManager.CombatLogs)
{
logText.text += $"[{log.Timestamp}] {log.Attacker} 对 {log.Target} 造成 {log.Damage} 伤害 ({log.Effects})\n";
}
}
}
✅ 每次战斗事件发生时,自动更新 UI
logManager.AddLogEntry("普通攻击", "玩家A", "敌人B", 100, "无");
combatLogUI.UpdateLogUI();
功能 | 实现方式 |
---|---|
战斗日志数据结构 | FCombatLogEntry (UE4) / CombatLogEntry (Unity) |
日志管理器 | 记录 & 维护战斗日志 |
日志存储 | 内存存储 / 文件存储 |
日志 UI 显示 | TextMeshPro (Unity) / UTextBlock (UE4) |
战斗日志系统不仅用于调试,也可以增强玩家体验(PvP 复盘、战斗回放)。
结合 UI 和文件存储,可以让战斗日志更具交互性和可读性!