Combat Flow

This article briefly introduces the attack and defense process in the GCS combat system to help you better utilize GCS.

Cover.GCS
A

Author

Author

Created: Apr 15, 2025Updated: Apr 14, 2026

Table of contents

Combat Flow

CombatFlow is a UObject , and each combat system component can specify a CombatFlow. You should inherit the built-in GCS_BaseCombatFlow and override the relevant functions to implement your custom logic, or reference existing CombatFlow and create a new one.

Handling Attribute Changes

As mentioned in the Gameplay Attribute part, The AttributeSystemComponent forwards all attribute change callbacks to the CombatFlow for processing. Therefore, you only need to override HandleGameplayEffectExecute.

战斗(攻防)系统.004
How to handle attribute changes and what kind of attack results to produce is entirely determined by your own game mechanics, while the default implementation provides common mechanics found in soul-like games.

Generating Attack Results

After processing attribute changes in HandleGameplayEffectExecute, you should convert the information from that process into attack results based on your game logic and register them with the combat system component.

战斗(攻防)系统.005
For example, after handling IncomingDamage, you should construct the relevant information into an AttackResult structure and register it with the combat system. TaggedValues includes some information generated during this process, such as "actual changed health." You can also customize this here.

Customizing Combat Flow

Attackers can initiate different attack requests, but each target may have a different "handling" for each attack request. You can implement different attack handling processes by customizing GCS_CombatFlow and configuring different CombatFlow classes on the CombatSystemComponent.

For example, if an arrow is shot at an enemy, it should typically trigger a hit reaction. However, if your enemy is very large and you do not want them to react, you can specify a different CombatFlow without needing extensive if/else checks at the attacker level.

When to Use Completely Different Combat Flows?

  1. You don't want a dog to deflect your attack.
  2. You don't want a gigantic boss to fall over just because you scratched its foot.
  3. You don't want a building to dodge your attack.

Access Attack Request in the Combat Flow

The attack request itself is passed through the GameplayEffectContext in different processes, meaning you can access various information configured in the attack request at any time. For instance, you can retrieve the attack request object via the context and access its associated attack definition.

战斗(攻防)系统.010

Good to Know

  • The attack request is an instantiated UObject, meaning it is not created at runtime but is created in the editor and stored on disk, which is the secret to its efficient network transmission.
  • The attack request is of type Const, meaning it can only store static data for game logic use, and you should not modify it during gameplay.
  • If you define a variable of type AttackRequest in Blueprints, you will see that it allows you to inline create an instance and save it with the outer asset.
战斗(攻防)系统.011
战斗(攻防)系统.012

Attack Results

Whenever CombatFlow processes an attack, it generates an attack result and records it in the combat system component, synchronizing it with the client over the network.

When a combat result is generated, GCS triggers different combat feedback based on its content, such as playing hit reactions or generating visual effects through gameplay cues.

Handling Attack Results

In CombatFlow, you can configure different AttackResultProcessors (attack result processors) in a data-driven manner to handle different attack results accordingly.

战斗(攻防)系统.014
战斗(攻防)系统.015

You can refer to the GCS_BaseCombatFlow Blueprint to understand the specific usage.

Built-in Attack Result Processors

Send Gampelay Event

This one allows you to send different gameplay events to attacker/victims based on attack results.

战斗(攻防)系统.016

You can also use TagQuery to route different logic.

For example: only trigger BlockHit when the attack results's source tags have Blocktag. Only trigger hit reaction when attack results's source tags have Hittag.

Custom Attack Result Processors

For example: You can write a "Dmage Statistics Processor" which keeps track of received damage to other log systems.