App Events are a decoupling mechanism used in the Kanda SDK to separate core systems from UI and other high-level systems. They represent significant occurrences in the application lifecycle that require attention from the app or user.
Overview
When an event occurs, an entity is created in the scene with an AppEvent component and relevant metadata components. This approach is similar to how Netcode for Entities handles RPC commands.
Key Components
AppEvent
The AppEvent struct is a marker component used to identify entities that represent app events:
public struct AppEvent : IComponentData
{
}
Event Data Components
Each type of app event has its own data component. For example, the ClientDisconnectEventData component is used when a client disconnects:
public struct ClientDisconnectEventData : IComponentData
{
public NetworkStreamDisconnectReason Reason;
}
Registering App Events
The AppEventUtils class provides a helper method to create app events:
var myEventEntity = AppEventUtils.RegisterAppEvent<MyEventData>(ecb, myEventData);
Handling App Events
To handle an App Event, downstream systems should query for entities with the AppEvent component and the specific event data component. After processing the event, the entity should be deleted to prevent duplicate handling.
Example: Creating a Client Disconnect Event
The MonitorDisconnectClientSystem demonstrates how to create an App Event when a client disconnects:
public partial struct MonitorDisconnectClientSystem : ISystem
{
public void OnUpdate(ref SystemState state)
{
var ecb = new EntityCommandBuffer(Allocator.Temp);
AppEventUtils.RegisterAppEvent(
ecb,
new ClientDisconnectEventData
{
Reason = connectionState.ValueRO.DisconnectReason
});
}
}
Example: Handling a Client Disconnect Event
Here's an example of a system that handles the ClientDisconnectEventData app event and then deletes the entity:
[UpdateInGroup(typeof(PresentationSystemGroup))]
public partial struct HandleClientDisconnectEventSystem : ISystem
{
[BurstCompile]
public void OnCreate(ref SystemState state)
{
state.RequireForUpdate<AppEvent>();
state.RequireForUpdate<ClientDisconnectEventData>();
}
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
var ecb = new EntityCommandBuffer(Allocator.Temp);
foreach (var (disconnectData, entity) in SystemAPI.Query<RefRO<ClientDisconnectEventData>>()
.WithAll<AppEvent>()
.WithEntityAccess())
{
HandleDisconnect(disconnectData.ValueRO.Reason);
ecb.DestroyEntity(entity);
}
ecb.Playback(state.EntityManager);
}
private void HandleDisconnect(NetworkStreamDisconnectReason reason)
{
string message = $"Disconnected from server. Reason: {reason}";
UIManager.ShowPopup(message, new []
{
new UIButton("Quit", () => Application.Quit()),
});
}
}
Best Practices
- Use App Events for significant occurrences that require high-level system or UI responses.
- Keep event data components small and focused on essential information.
- Handle events in downstream systems and remember to delete the event entity after processing.
By using App Events, you can maintain a clean separation between core systems and UI or other high-level systems, leading to more modular and maintainable code.