A Comprehensive Guide to Generating Entity Prefabs at Runtime in Unity ECS
Rathod Ketan
Posted on October 7, 2024
In Unity’s Entity Component System (ECS), generating entity prefabs at runtime is a powerful feature that allows dynamic creation of game objects during gameplay. While traditional Unity uses GameObject.Instantiate to achieve this, Unity ECS takes a different approach by using the EntityManager class and its Instantiate method. This guide will cover the basics of runtime prefab generation in Unity ECS, along with example code to implement it.
Key Differences: Standard Unity Prefab vs ECS Prefab
In standard Unity, prefab instantiation involves creating a script to access the prefab from the Project window and then calling Instantiate to spawn it. In Unity ECS, the process is similar but handled in a more modular way. Prefabs are converted to entities through a baking process and structured using ECS components. The prefab can then be instantiated at runtime using the EntityManager.Instantiate method.
Baking the Prefab into ECS Entities
In Unity ECS, a baker class is required to convert a prefab GameObject into an ECS entity. Below is an example of the GeneratePrefabAuthoring class that does this conversion:
public class GeneratePrefabAuthoring : Baker<GeneratePrefab>
{
public override void Bake(GeneratePrefab authoring)
{
var entity = GetEntity(authoring, TransformUsageFlags.Dynamic);
AddComponent(entity, new GeneratePrefabStruct()
{
prefab = GetEntity(authoring.prefab, TransformUsageFlags.Dynamic),
});
}
}
In this code, we pass the GeneratePrefab MonoBehaviour class into the GeneratePrefabAuthoring baker, which converts the prefab into an ECS-compatible entity using GetEntity. This is stored in the GeneratePrefabStruct.
Structuring Prefab Data for ECS
We now need a struct to hold our prefab data once it’s converted to an entity. Here’s the GeneratePrefabStruct:
public struct GeneratePrefabStruct : IComponentData
{
public Entity prefab;
}
This struct is designed to store the entity reference of our prefab so it can be accessed and instantiated at runtime.
Instantiating Entities at Runtime Using Unity ECS
To instantiate entities at runtime, Unity ECS uses the EntityManager.Instantiate method within a system. The system queries the prefab data and instantiates the entity. Below is an example of how to implement this system using ISystem
public partial struct GeneratePrefabSystem : ISystem
{
void OnUpdate(ref SystemState state)
{
foreach (var prefab in SystemAPI.Query<RefRW<GeneratePrefabStruct>>())
{
var newPrefab = state.EntityManager.Instantiate(prefab.ValueRW.prefab);
}
}
}
In this code, we’re using a foreach loop with SystemAPI.Query to access the GeneratePrefabStruct. The RefRW provides read-write access to the prefab data, allowing us to instantiate it with the EntityManager.Instantiate method.
Using RefRW and RefRO
Unity ECS provides two access types when querying entities: RefRW and RefRO. As their names suggest, RefRW grants read and write access, while RefRO allows read-only access. This gives you the flexibility to optimize performance depending on whether you need to modify the data or not.
- RefRW (Reference Read-Write): Grants read and write access to the queried entity data.
- RefRO (Reference Read-Only): Grants read-only access, useful for improving performance when no modifications are needed.
Code Implementation Recap
By now, we have everything in place for runtime entity instantiation:
- Baking the Prefab – We use GeneratePrefabAuthoring to convert the prefab GameObject into an entity.
- Storing the Prefab – GeneratePrefabStruct stores the converted entity.
- Instantiating the Prefab – GeneratePrefabSystem instantiates the prefab at runtime using EntityManager.Instantiate.
Complete Code for Generating Entity Prefabs in Unity ECS
// GeneratePrefab MonoBehaviour class to access prefab from storage
public class GeneratePrefab : MonoBehaviour
{
public GameObject prefab;
}
// GeneratePrefabAuthoring class to bake prefab into ECS entity
public class GeneratePrefabAuthoring : Baker<GeneratePrefab>
{
public override void Bake(GeneratePrefab authoring)
{
var entity = GetEntity(authoring, TransformUsageFlags.Dynamic);
AddComponent(entity, new GeneratePrefabStruct()
{
prefab = GetEntity(authoring.prefab, TransformUsageFlags.Dynamic),
});
}
}
// Struct to store prefab data
public struct GeneratePrefabStruct : IComponentData
{
public Entity prefab;
}
// System to instantiate prefab at runtime
public partial struct GeneratePrefabSystem : ISystem
{
void OnUpdate(ref SystemState state)
{
foreach (var prefab in SystemAPI.Query<RefRW<GeneratePrefabStruct>>())
{
var newPrefab = state.EntityManager.Instantiate(prefab.ValueRW.prefab);
}
}
}
Wrapping Up
In this guide, we’ve covered how to generate entity prefabs at runtime in Unity ECS using EntityManager.Instantiate. The process involves baking the prefab into an entity, querying the ECS world, and finally instantiating the prefab dynamically. By understanding the differences between standard Unity prefab instantiation and ECS, and leveraging features like RefRW and RefRO, you can build more scalable and performant Unity games.
Posted on October 7, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.