Game.Rendering.MarkerIconSystem
Assembly: Game
Namespace: Game.Rendering
Type: class MarkerIconSystem
Base: GameSystemBase, IDefaultSerializable, ISerializable
Summary:
MarkerIconSystem is an ECS system responsible for creating, updating and removing the small selection/follow markers (notification icons) that appear over selected or followed entities in the game. It tracks two marker types (Selected and Followed), creates marker entities from configured prefabs, animates their appearance/disappearance when configured, and adjusts marker positions to avoid visual overlap using Burst‑compiled jobs and Unity's job system. The system also implements simple serialization of its active marker entity references so marker state survives save/load.
Fields
-
private Entity m_SelectedMarker
Holds the entity ID of the currently active "selected" marker (the marker that indicates the player's selection). Entity.Null when none exists. -
private Entity m_FollowedMarker
Holds the entity ID of the currently active "followed" marker (the marker attached to the camera-followed entity). Entity.Null when none exists. -
private Entity m_SelectedLocation
The entity representing the location component used for the selected target (used to detect when the underlying location changes). -
private Entity m_FollowedLocation
The entity representing the location component used for the followed target. -
private EntityQuery m_ConfigurationQuery
Query used to fetch icon configuration singleton data (IconConfigurationData). Used to read marker prefabs, animation durations and other configuration. -
private EntityQuery m_IconQuery
Query used to iterate existing Icon components (excluding Deleted and Temp) when checking for overlapping icons. -
private CameraUpdateSystem m_CameraUpdateSystem
Cached reference to the CameraUpdateSystem in the same World. Used to obtain camera position/rotation and followed entity. -
private ToolSystem m_ToolSystem
Cached reference to the ToolSystem in the same World. Used to obtain the currently selected entity and selection index. -
private TypeHandle __TypeHandle
Internal struct that holds type handles and component lookups required by the jobs. It is initialized during system creation for fast access in jobs. -
private struct Overlap
(nested)
Small helper struct used by the overlap detection job to pair two entities involved in an overlap. -
private struct FindOverlapIconsJob
(nested, BurstCompile)
IJobChunk job that scans Icon components to detect icons that are close to the selected/followed target locations and enqueues overlaps into a NativeQueue. -
private struct UpdateMarkerLocationJob
(nested, BurstCompile)
IJob job that dequeues overlap results and updates the Icon component positions for selected/followed markers. It computes offsets using PrefabRef and NotificationIconDisplayData to resolve stacking radius and avoid overlaps. -
private struct TypeHandle
(nested)
Holds EntityTypeHandle, ComponentTypeHandles and ComponentLookup objects used by the jobs; assigned during OnCreate/OnCreateForCompiler.
Properties
- (none public)
Constructors
public MarkerIconSystem()
Default constructor (preserved). The system initialization occurs in OnCreate/OnCreateForCompiler.
Methods
protected override void OnCreate()
Initializes the system after construction. Caches references to ToolSystem and CameraUpdateSystem, and initializes the EntityQueries:- m_ConfigurationQuery = IconConfigurationData singleton query
-
m_IconQuery = query for Icon components (excludes Deleted and Temp) This is where the system prepares to respond to selection/follow state changes.
-
protected override void OnUpdate()
Main update loop executed each frame. Responsibilities: - Reads the currently selected entity from m_ToolSystem and the followed entity from m_CameraUpdateSystem.
- Attempts to resolve world positions/locations for those entities via SelectedInfoUISystem.TryGetPosition.
- Ensures that selection and follow markers don't both point at the same UI location inappropriately (clears one if they refer to the same).
- Updates or creates markers via UpdateMarker and RemoveMarker calls.
-
If any markers are active and there is a valid active camera controller, calls AdjustLocations(...) to schedule overlap detection & position adjustment jobs.
-
private void UpdateMarker(ref Entity marker, Entity target, MarkerType markerType, float3 position, bool skipAnimation)
Ensures a marker entity exists and is pointed at the correct target. If the target entity has an Owner component and an Icon, it resolves to the owner entity. If no marker exists it creates one via CreateMarker. If a marker exists but its Target component's m_Target differs, updates the Target component. -
private void RemoveMarker(ref Entity marker, bool skipAnimation)
Removes a marker entity. If the configuration singleton is missing or skipAnimation is true, the marker is immediately tagged Deleted. Otherwise, the method either flips an existing Animation component to a MarkerDisappear animation (reversing timer) or adds an Animation component with the configured disappearance duration to play the marker disappearance animation before deletion. After scheduling removal, it sets the marker reference to Entity.Null. -
private Entity CreateMarker(Entity target, float3 position, MarkerType markerType, bool skipAnimation)
Creates a new marker entity based on IconConfigurationData's configured prefabs (selected/followed marker prefabs). The created entity: - Uses the archetype from the NotificationIconData for the chosen prefab.
- Is assigned a PrefabRef to the marker prefab entity and an Icon component (with default priority and flags).
- Is given a Target component pointing at the target entity.
- Is marked DisallowCluster to avoid clustering logic.
- Optionally adds an Animation component for "MarkerAppear" when skipAnimation is false, using duration from configuration.
Returns the created marker entity, or Entity.Null if configuration is missing.
-
public void Serialize<TWriter>(TWriter writer) where TWriter : IWriter
Serializes the current active markers by writing m_SelectedMarker and m_FollowedMarker to the writer. Used to persist which marker entities were active across saves. -
public void Deserialize<TReader>(TReader reader) where TReader : IReader
Deserializes saved marker entity references into m_SelectedMarker and m_FollowedMarker. Also resets m_SelectedLocation and m_FollowedLocation to Entity.Null. Note that after load, the system will revalidate and potentially recreate/update markers as needed. -
public void SetDefaults(Context context)
Resets the system's runtime state. Sets m_SelectedMarker, m_FollowedMarker, m_SelectedLocation and m_FollowedLocation to Entity.Null. Called when creating defaults for serialization contexts (new game, reset state). -
private void AdjustLocations(float3 selectedLocation, float3 followedLocation, float3 cameraPos, float3 cameraUp)
Schedules the two jobs that detect overlapping icons and update marker positions: - Creates a NativeQueue
used to transfer overlap results between jobs. - Schedules FindOverlapIconsJob over the m_IconQuery in parallel to detect icons that are spatially close to the selected/followed positions.
- Schedules UpdateMarkerLocationJob which dequeues overlap results and updates the Icon component positions for the selected and followed markers, applying offsets computed from PrefabRef and NotificationIconDisplayData (uses a cluster radius calc).
-
Ensures proper JobHandle dependency chaining and disposes the NativeQueue after the jobs complete.
-
private void __AssignQueries(ref SystemState state)
Internal/compile-time helper that initializes queries used by the generated code. (Called from OnCreateForCompiler.) -
protected override void OnCreateForCompiler()
Compiler-time hookup: calls __AssignQueries and assigns the job TypeHandle handles via __TypeHandle.__AssignHandles(ref state). Required for generated code paths in the ECS implementation. -
(Nested job methods)
FindOverlapIconsJob.Execute(...) and UpdateMarkerLocationJob.Execute() contain the actual Burst‑compiled logic described above: - FindOverlapIconsJob compares squared distances between Icon.m_Location and the two marker target locations and enqueues Overlap entries when within a small threshold (0.01f).
- UpdateMarkerLocationJob computes offset heights based on icon priority and display data (interpolated radius) and sets Icon.m_Location for the two markers so they stack visually above other icons.
Usage Example
// Typical mod code: obtain or create the system instance in your world.
var world = Unity.Entities.World.DefaultGameObjectInjectionWorld;
var markerSystem = world.GetOrCreateSystemManaged<Game.Rendering.MarkerIconSystem>();
// The MarkerIconSystem runs automatically each frame to manage selection/follow markers.
// You can reset its runtime state (for example on a new game or when resetting systems):
markerSystem.SetDefaults(default);
// Note: most marker behavior (creation, removal, animation) is internal to the system and
// driven by ToolSystem (selected entity) and CameraUpdateSystem (followed entity).
Notes and modding tips: - Marker prefabs, animation durations and per-icon parameters come from the IconConfigurationData / NotificationIconData singletons — to change marker visuals or animation timing, edit those configuration prefabs rather than the system code. - AdjustLocations uses Burst-compiled jobs and NativeQueue and schedules them with parallel chunk scheduling — be careful when modifying job inputs/outputs and ensure thread-safety and proper ComponentLookup usage (read-only vs read-write). - The system writes only the marker entity references during serialization; on load the system will revalidate those entity references and re-associate markers with entities if the referenced entities still exist.