Class: USystem
class SYSTEMS_API USystem
: public UObject;
Reflection-enabled
Specifiers:
- Abstract
- EditInlineNew
Base class for unit of work over some data.
Architecture book page explains more in depth systems.
System's job is to process data. Usually it involves performing queries over game world and/or resources.
This is only one of few ways of system representation, used mostly in case your system has to cache some internal state or has to perform some logic on system initialization phase, which is not possible in case of for example lambda systems.
Example
UCLASS()
class EXAMPLE_API ULogBirdsNumberChangeSystem : public USystem
{
GENERATED_BODY()
public:
virtual void Run(USystemsWorld& Systems) override;
UPROPERTY()
uint32 LastCount = 0;
};
void ULogBirdsNumberChangeSystem::Run(USystemsWorld& Systems)
{
Super::Run(Systems);
if (Systems.ComponentsDidChanged<UBirdComponent>() == false)
{
return;
}
const auto Number = static_cast<int>(Systems.Query<UBirdComponent>().Count());
const Difference = Number - this->LastCount;
this->LastCount = Number;
if (Difference > 0)
{
UE_LOG(LogTemp, Warning, TEXT("Added %i birds"), Difference);
}
else if (Difference < 0)
{
UE_LOG(LogTemp, Warning, TEXT("Removed %i birds"), -Difference);
}
}
Methods
-
AdvancedRun
public: virtual void AdvancedRun( USystemsWorld& Systems, const FName& Mode, const TObjectPtr<UObject>& Payload );
Override to run system work logic in special mode triggered .
This method is called by
USystemsWorld::Process
. See alsoUSystem::Run
.Here user can perform system logic in special mode, like for example systems dispatcher gets request to run systems in network rollback/rollforth mode so systems that support rollback/rollforth can go back in time and re-simulate their part of the game state.
Arguments
-
Systems
USystemsWorld& Systems
Reference to systems world that triggers this system run.
-
Mode
const FName& Mode
Name of the mode system wants to run in (default mode is
None
). -
Payload
const TObjectPtr<UObject>& Payload
Additional payload provided from systems dispatcher that contains extra data for given run mode.
-
-
Cleanup
public: virtual void Cleanup( USystemsWorld& Systems );
Override to cleanup system (its internal state).
This method is called by
USystemsWorld::Cleanup
, right before systems world is scheduled to removal.Here user can perform cleanup of this system internal state, or free acquired resources.
Arguments
-
Systems
USystemsWorld& Systems
Reference to systems world that triggers this system cleanup.
-
-
Init
public: virtual void Init( USystemsWorld& Systems );
Override to initialize system (setup its internal state).
This method is called by
USystemsWorld::SealAndInitialize
, right after systems world is setup and sealed by the user.Here user can perform initialization of this system internal state, or do something useful with systems world (for example initialize some resources). At this stage systems world does not yet have registered any of world components so any query will yield no results.
Example
UCLASS() class BOIDS_API UBoidsMovementSystem : public USystem { GENERATED_BODY() public: virtual void Init(USystemsWorld& Systems) override; private: TReceiverChannel<FMovementStep> MovementStep = {}; }; void UBoidsMovementSystem::Init(USystemsWorld& Systems) { Super::Init(Systems); auto* GameEvents = Systems.Resource<UGameEvents>(); if (IsValid(GameEvents)) { this->MovementStep = GameEvents->MovementStep.Receiver(1); } }
Arguments
-
Systems
USystemsWorld& Systems
Reference to systems world that triggers this system initialization.
-
-
Run
public: virtual void Run( USystemsWorld& Systems );
Override to run system work logic (perform queries on world components and resources).
This method is called by
USystems::AdvancedRun
when systems dispatcher gets request for default mode run.Here user can perform system logic, usually performs single task such as apply velocity accumulated by other systems on actor location, or perform actors AI tasks, or kill actors that has 0 or less health - whatever work you want to do make sure it's not monolithic, rather make it small, like don't do multiple things at once - always divide work to small data processing work units. Split bigger tasks between multiple systems and use components/resources/channels to share data between systems.
Example
UCLASS() class BOIDS_API UBoidsMovementSystem : public USystem { GENERATED_BODY() public: virtual void Run(USystemsWorld& Systems) override; }; void UBoidsMovementSystem::Run(USystemsWorld& Systems) { Super::Run(Systems); const auto* BoidsSettings = Systems.Resource<UBoidsSettings>(); if (IsValid(BoidsSettings) == false) { return; } const auto TimeScale = BoidsSettings->TimeScale; const auto DeltaTime = Systems.GetWorld()->GetDeltaSeconds() * TimeScale; for (auto& QueryItem : Systems.Query<UVelocityComponent, UBoidComponent>()) { auto* Actor = QueryItem.Get<0>(); const auto* Velocity = QueryItem.Get<1>(); const auto Position = Actor->GetActorLocation(); Actor->SetActorLocation(Position + Velocity->Value * DeltaTime); } }
Arguments
-
Systems
USystemsWorld& Systems
Reference to systems world that triggers this system run.
-
Documentation built with Unreal-Doc
v1.0.8 tool by PsichiX