ARPG 游戏战斗系统设计详解

ARPG 游戏战斗系统设计详解

ARPG(Action Role-Playing Game,动作角色扮演游戏) 的战斗系统需要兼顾 操作性、打击感、技能组合、AI 交互 等多个方面。
本指南将详细解析 ARPG 战斗系统的核心要素、设计思路与优化方案,适用于 Unity、UE4 及自研引擎开发。


1. ARPG 战斗系统的核心要素

1.1 战斗核心机制

  • 即时战斗(Real-Time Combat):无回合制,玩家实时控制角色进行攻击、闪避、技能释放等操作。
  • 技能系统(Skill System):角色拥有不同的技能,支持连招、冷却、消耗资源(如 MP、能量)。
  • 动画驱动(Animation-Based Combat):攻击、技能、闪避等动作依赖动画系统,可能包含 Root Motion。
  • 碰撞检测(Hit Detection):使用 碰撞体(Hitbox)或 追踪射线(Raycast) 进行伤害判定。
  • 敌人 AI(Enemy AI):敌人有攻击、闪避、寻路等行为,可能包括状态机或行为树(Behavior Tree)。
  • 属性与数值(Stats & Attributes):角色的 HP、MP、攻击力、防御力、暴击率等数值影响战斗效果。

2. 战斗系统架构

2.1 主要模块

模块 功能
角色控制(Character Controller) 处理玩家输入、移动、攻击、技能释放
动画系统(Animation System) 角色动画驱动攻击、技能、受击、闪避
技能系统(Skill System) 管理技能释放、冷却、组合
伤害计算(Damage System) 计算攻击伤害、暴击、防御、Buff
碰撞检测(Hit Detection) 使用 Hitbox、Raycast 进行伤害判定
敌人 AI(Enemy AI) 控制敌人行为(巡逻、攻击、闪避)
战斗 UI(Combat UI) 显示 HP、MP、技能冷却等状态

3. 角色控制与动画系统

3.1 玩家角色控制

  • 输入映射(Input Mapping)
    • 轻攻击(Light Attack)左键 / X
    • 重攻击(Heavy Attack)右键 / Y
    • 闪避(Dodge)空格 / B
    • 技能释放(Skill)Q/E/R
    • 锁定目标(Lock-On)Tab
  • 移动与旋转(Movement & Rotation)
    • 使用 Character ControllerRoot Motion 控制角色移动。
    • 锁定系统(Lock-On System) 允许玩家锁定敌人,自动调整摄像机。

3.2 动画系统

  • 动画状态机(Animation State Machine)
    • IdleWalk/RunAttackSkillDodgeHitDeath
    • 通过 动画事件(Animation Event) 触发攻击判定。
  • Root Motion vs. 物理控制(Physics-Based Movement)
    • Root Motion:动画驱动移动,适用于精准连招。
    • 物理控制:代码控制移动,适用于自由战斗。

示例(Unity Animator)

animator.SetTrigger("Attack");

示例(UE4 动画蓝图)

void AMyCharacter::PlayAttackAnimation()
{
    PlayAnimMontage(AttackMontage);
}

4. 伤害判定与碰撞检测

⚔ 4.1 碰撞检测方式

方式 优点 缺点
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);
    }
}

5. 技能系统

5.1 技能数据结构

字段 作用
技能名称(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;
};

5.2 技能释放流程

  1. 检查冷却时间(Cooldown)
  2. 消耗 MP / 体力
  3. 播放动画 + 触发 Hitbox
  4. 生成特效(VFX + SFX)
  5. 执行技能逻辑(伤害、Buff)
  6. 进入冷却状态

示例(C++ 技能释放)

void AMyCharacter::UseSkill(FSkillData Skill)
{
    if (CurrentMana < Skill.Cost || IsCooldown) return;

    CurrentMana -= Skill.Cost;
    PlayAnimMontage(Skill.Animation);
    StartCooldown(Skill.Cooldown);
}

6. 敌人 AI(Enemy AI)

6.1 AI 逻辑

  • 巡逻(Patrol):在特定区域巡逻。
  • 追踪(Chase):检测到玩家后追击。
  • 攻击(Attack):靠近玩家后进行攻击。
  • 闪避(Dodge):躲避玩家攻击。

示例(UE4 行为树 AI)

void AEnemyAI::OnSeePlayer(APawn* Player)
{
    BlackboardComponent->SetValueAsObject("Target", Player);
    AIController->MoveToActor(Player);
}

7. 伤害计算

7.1 计算公式

Damage = (BaseDamage + WeaponDamage) * (1 + Strength / 100) - TargetArmor;

7.2 伤害类型

  • 物理伤害(Physical Damage)
  • 魔法伤害(Magic Damage)
  • 暴击伤害(Critical Damage)
  • Dot 伤害(持续伤害,如中毒)

示例(UE4 伤害计算)

float FinalDamage = BaseDamage * DamageMultiplier;
Target->TakeDamage(FinalDamage, DamageEvent, GetController(), this);

8. 结论

ARPG 战斗系统的核心:

  1. 角色控制 & 动画驱动
  2. 碰撞检测(Hitbox / Raycast)
  3. 技能系统(冷却、伤害、特效)
  4. 敌人 AI(巡逻、攻击、闪避)
  5. 伤害计算(数值系统)

合理设计战斗系统,使其既具有流畅的操作感,又能提供深度的策略性!


ARPG 战斗日志系统实现

在 ARPG 游戏中,战斗日志(Combat Log) 主要用于:
记录战斗事件(攻击、技能、伤害、暴击、闪避等)
调试战斗系统(检测数值计算是否正确)
UI 显示反馈(玩家可查看战斗详情)
多人战斗同步日志(用于 PvP、团队战斗)

本指南将介绍 战斗日志的架构设计、数据结构、存储方式(本地/网络)、UI 显示,适用于 Unity / UE4 / 自研引擎


1. 战斗日志的核心组成

模块 作用
CombatLogManager 负责管理、记录战斗日志
CombatLogEntry 具体的战斗日志数据结构
CombatLogStorage 存储战斗日志(内存 / 文件 / 网络)
CombatLogUI 负责在 UI 上显示日志

2. 战斗日志的数据结构

2.1 结构设计

一个战斗日志通常包含:

  • 时间戳(Timestamp):记录事件触发的时间
  • 事件类型(EventType):攻击、技能、暴击、闪避、治疗等
  • 攻击者(Attacker):施加伤害的对象
  • 目标(Target):受到影响的对象
  • 伤害数值(Damage):最终计算的伤害值
  • 附加效果(Effects):是否暴击、是否触发 Buff、是否闪避

2.2 C++ 结构体(UE4)

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 的攻击

2.3 C# 结构体(Unity)

[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;
    }
}

3. 战斗日志管理器

3.1 UE4 版(C++)

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, "暴击");

3.2 Unity 版(C#)

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, "暴击");

4. 战斗日志存储

4.1 存储在本地(文件存储)

UE4 版

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);
}
Unity 版

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);
}

5. 战斗日志 UI 显示

5.1 UI 组件

组件 作用
TextMeshPro(Unity)/ UTextBlock(UE4) 显示日志内容
ScrollView / ScrollBox 允许滚动查看日志
Clear Button 清空日志

5.2 Unity UI 更新

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();

6. 结论

功能 实现方式
战斗日志数据结构 FCombatLogEntry(UE4) / CombatLogEntry(Unity)
日志管理器 记录 & 维护战斗日志
日志存储 内存存储 / 文件存储
日志 UI 显示 TextMeshPro(Unity) / UTextBlock(UE4)

战斗日志系统不仅用于调试,也可以增强玩家体验(PvP 复盘、战斗回放)。
结合 UI 和文件存储,可以让战斗日志更具交互性和可读性!

你可能感兴趣的:(Unity引擎,游戏)