Unreal-ActionRoguelike的技术拆解

斯坦福大学有一个关于Unreal 游戏开发的课程,看起来挺不错的。我下载了这个课程的源码,准备通过琢磨该源码,了解下常用游戏功能以及蓝图与 C++的交互合作方式。

课程内容

  • Third-person Action Character Movement
  • Action System(similar to Gameplay Ability System in design)
    • Dash Ability (Teleporting via projectile)
    • Blackhole Ability
    • Magic Projectile Attack
    • “Thorns” buff (reflecting damage)
    • Burning Damage-over-time effect
  • AttributeComponent (Holding health etc.)
  • SaveGame System for persisting progress of character and world state.
  • Heavy use of Events to drive UI and gameplay reactions.
  • Mix of C++ & Blueprint and how to combine these effectively.
  • GameplayTags to mark-up Actors, Buffs, Actions.
  • Multiplayer support for all features
  • GameMode Logic
    • EQS for binding bot/powerup spawn locations.
    • Bot spawning system (bots cost points to spawn, gamemode gains points over time to spend)
    • DataTable holds bot information
    • DataAssets to hold enemy configurations
  • Asset Manager: Async loading of data assets
  • Async loading of UI icons
  • AI
    • Minion AI with Behavior Trees (Roam, See, Chase, Attack, Flee/Heal)
    • C++ Custom Behavior Trees Nodes
    • EQS for attack/cover locations by AI Powerups
  • Powerup pickups to heal, gain credits/actions. UMG
  • Main menu to host/join game
  • UI elements for player attributes and projected widgets for powerups and enemy health.
  • C++ Localized Text

文件结构

环境配置

让 C++代码跑起来

几个疑问

代码中的 A 前缀和 S 前缀分别代表什么?

Third-person Action Character Movement

Action System

Dash Ability (Teleporting via projectile)

Blackhole Ability

似乎是蓝图中通过 RadialForce 实现该技能,然后在 C++中进行用户输入按键和技能的绑定。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// Called to bind functionality to input
void ASCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);

PlayerInputComponent->BindAxis("MoveForward", this, &ASCharacter::MoveForward);
PlayerInputComponent->BindAxis("MoveRight", this, &ASCharacter::MoveRight);

PlayerInputComponent->BindAxis("Turn", this, &APawn::AddControllerYawInput);
PlayerInputComponent->BindAxis("LookUp", this, &APawn::AddControllerPitchInput);

PlayerInputComponent->BindAction("PrimaryAttack", IE_Pressed, this, &ASCharacter::PrimaryAttack);
// Used generic name 'SecondaryAttack' for binding
PlayerInputComponent->BindAction("SecondaryAttack", IE_Pressed, this, &ASCharacter::BlackHoleAttack);
PlayerInputComponent->BindAction("Dash", IE_Pressed, this, &ASCharacter::Dash);
PlayerInputComponent->BindAction("PrimaryInteract", IE_Pressed, this, &ASCharacter::PrimaryInteract);

PlayerInputComponent->BindAction("Sprint", IE_Pressed, this, &ASCharacter::SprintStart);
PlayerInputComponent->BindAction("Sprint", IE_Released, this, &ASCharacter::SprintStop);

PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &ACharacter::Jump);
}

void ASCharacter::BlackHoleAttack()
{
ActionComp->StartActionByName(this, "Blackhole");
}

感想

基于组件的设计思想很重要,到处都在应用。

资料

课程主页:

https://courses.tomlooman.com/p/unrealengine-cpp?coupon_code=COMMUNITY15

项目代码:

https://github.com/tomlooman/ActionRoguelike