Skip to content

Game.Debug.TreeSpawnSystem

Assembly:
Namespace: Game.Debug

Type: class

Base: GameSystemBase

Summary:
This system runs at the start of a new game to procedurally place a batch of tree entities across the terrain. It selects random tree prefabs, samples terrain height, assigns a transform and tree component (state and growth), then creates entities using the prefab archetype. Execution is gated so it only runs for a new game (LoadGameSystem.context.purpose == Purpose.NewGame) and only when there are no existing Tree entities. It allocates a temporary NativeArray of prefab entities and disposes it when done. This is a main-thread, non-jobified setup that creates 5000 trees in a single update.


Fields

  • private LoadGameSystem m_LoadGameSystem
    This references the LoadGameSystem so the TreeSpawnSystem can check the current loading context/purpose (to run only for new games).

  • private TerrainSystem m_TerrainSystem
    Used to fetch TerrainHeightData (with waitForPending: true) so tree positions can have their Y coordinate sampled against the terrain height.

  • private EntityQuery m_Prefabs
    An EntityQuery selecting available tree prefabs (requires TreeData and excludes PlaceholderObjectElement). The system uses this query to pick random prefab entities to instantiate.

  • private EntityQuery m_TreeQuery
    An EntityQuery selecting existing Tree entities. The system checks this to ensure it does not spawn trees when trees already exist.

Properties

  • None

Constructors

  • public TreeSpawnSystem()
    Default parameterless constructor. The system is marked with [Preserve] on lifecycle methods to avoid code stripping.

Methods

  • protected override void OnCreate() : System.Void
    Initializes references to LoadGameSystem and TerrainSystem, creates the entity queries for tree prefabs and existing trees, and calls RequireForUpdate(m_Prefabs) so the system only runs when tree prefabs are available. Marked with [Preserve].

Additional notes: - m_Prefabs uses ComponentType.ReadOnly() and excludes PlaceholderObjectElement. - m_TreeQuery uses ComponentType.ReadOnly().

  • protected override void OnUpdate() : System.Void
    Main spawning logic. Behaviour summary:
  • Returns early unless the load context purpose is Purpose.NewGame and there are no existing Tree entities.
  • Seeds a Unity.Mathematics.Random with (uint)DateTime.Now.Ticks.
  • Retrieves TerrainHeightData from TerrainSystem with waitForPending: true.
  • Converts m_Prefabs query to a temporary NativeArray (Allocator.TempJob) and iterates 5000 times:
    • Picks a random prefab Entity from the prefab array.
    • Reads the prefab's ObjectData component to obtain the archetype for instantiation.
    • Chooses a random XZ position within [-1000, 1000], samples the terrain height for Y, and sets a random Y-rotation.
    • Randomly assigns TreeState (seedling/teen/adult/elderly/dead) using random.NextInt(13) with a weighted mapping, and a random growth byte (0–255).
    • Creates a new entity using the prefab archetype and sets PrefabRef, Transform, and Tree components accordingly.
  • Ensures the temporary NativeArray is disposed in a finally block.

Important implementation details and cautions: - Creates 5000 entities in one update — may cause a noticeable hitch during new-game initialization depending on performance and archetype complexity. - Uses Allocator.TempJob for the NativeArray; it is explicitly disposed in finally. - Random seed uses DateTime.Now.Ticks cast to uint — this is a lossy cast but acceptable here for basic randomness. - The system runs on the main thread and uses EntityManager.SetComponentData / CreateEntity (no parallel instantiation or jobs).

Usage Example

[Preserve]
protected override void OnCreate()
{
    base.OnCreate();
    m_LoadGameSystem = base.World.GetOrCreateSystemManaged<LoadGameSystem>();
    m_TerrainSystem = base.World.GetOrCreateSystemManaged<TerrainSystem>();
    m_Prefabs = GetEntityQuery(ComponentType.ReadOnly<TreeData>(), ComponentType.Exclude<PlaceholderObjectElement>());
    m_TreeQuery = GetEntityQuery(ComponentType.ReadOnly<Tree>());
    RequireForUpdate(m_Prefabs);
}

// When a new game starts and there are no trees, OnUpdate will create ~5000 trees:
// It picks random prefabs from m_Prefabs, samples terrain height, assigns a random TreeState
// and growth value, then creates entities using the prefab archetype.