Systems – Arma Reforger
Jump to navigation
Jump to search
Lou Montana (talk | contribs) m (Fix phrasing) |
Lou Montana (talk | contribs) m (Fix example) |
||
Line 69: | Line 69: | ||
float timeSlice = GetWorld().GetTimeSlice(); | float timeSlice = GetWorld().GetTimeSlice(); | ||
foreach (FooComponentcomp : | foreach (FooComponentcomp : m_aComponents) | ||
{ | { | ||
comp.Update(timeSlice); | comp.Update(timeSlice); | ||
Line 95: | Line 95: | ||
{ | { | ||
if (!m_aComponents.Contains(component)) | if (!m_aComponents.Contains(component)) | ||
m_aComponents.Insert(component); | |||
} | } | ||
Line 104: | Line 104: | ||
} | } | ||
</enforce> | </enforce> | ||
Revision as of 17:08, 10 January 2024
A System is a standalone piece of code or process that takes care of one specific operation.
For instance, if entities are capable of shooting and reloading, one system should handle the shooting logic, while the other should handle the reloading logic.
The idea behind splitting the logic into multiple systems is as follows:
- Clear Operations Order - with one glance at where the systems are registered, it is possible to see right away how and when they are run
- Logic Separation - rather than doing everything each system is only responsible for one specific feature/operation
- Parallelisation - grouping allows for potential easy parallelisation engine-side
- depending on what the other places in the code do, thanks to separating the logic it is vastly easier to manage parallel code execution
- rather than processing things in the ABC ABC ABC ABC order, it is easier to change order and process all As before moving to Bs and Cs (AAAA BBBB CCCC)
- Performance - because the engine needs to search through the hierarchy when updating components/entities, whereas Systems prevent doing so.
Template
Systems in script are automatically registered and nothing more needs to be done but to override the GetSystemPoint() method in order to define where the system will be updated.
Component
class TAG_FooComponent : ScriptComponent
{
void Update(float timeSlice)
{
Print("Update FooComponent each frame");
}
protected void ConnectToFooSystem()
{
World world = GetOwner().GetWorld();
SCR_FooSystem updateSystem = SCR_FooSystem.Cast(world.FindSystem(SCR_FooSystem, ESystemPoint.Frame));
if (!updateSystem)
return;
updateSystem.Register(this);
}
protected void DisconnectFromFooSystem()
{
World world = GetOwner().GetWorld();
SCR_FooSystem updateSystem = SCR_FooSystem.Cast(world.FindSystem(SCR_FooSystem, ESystemPoint.Frame));
if (!updateSystem)
return;
updateSystem.Unregister(this);
}
}
System
class TAG_FooSystem : GameSystem
{
protected ref array<SCR_FooComponent> m_aComponents = {};
override protected ESystemPoint GetSystemPoint()
{
return ESystemPoint.Frame;
}
override protected void OnUpdate()
{
float timeSlice = GetWorld().GetTimeSlice();
foreach (FooComponentcomp : m_aComponents)
{
comp.Update(timeSlice);
}
}
override protected void OnDiag(float timeSlice)
{
DbgUI.Begin("SCR_FooSystem");
DbgUI.Text("Items: " + m_aComponents.Count());
if (DbgUI.Button("Dump active components"))
{
foreach (SCR_FooComponent comp : m_aComponents)
{
Print(comp.GetOwner(), LogLevel.ERROR);
}
}
DbgUI.End();
}
void Register(SCR_FooComponent component)
{
if (!m_aComponents.Contains(component))
m_aComponents.Insert(component);
}
void Unregister(SCR_FooComponent component)
{
m_aComponents.RemoveItem(component);
}
}
Current Limitations
- No replication - there is no replication involved in Systems for now. If RPC or replicated properties are needed, use entities/components
- Script only - a scripted system can only reference another scripted system, not an engine one
- No cycle setting - there is currently no way to define a system's period (e.g tick only every x seconds instead of each frame)