Here is my attempt at setting up a prefab system for ECS. It properly sets up archetypes for all your prefabs and allows you to store any instance data you want for each prefab. It also allows you to easily add batches of components or have prefabs inherit from each other. There is an extra cache miss for each component you add which is not default initialized but in most cases this should hopefully be ok. I thought this might be useful to other people so I’m sharing it here. The full source code can be found here: https://github.com/jseidenz/ecsprefabs
// Setup prefabs
public static class Prefabs
{
public static Prefab Asteroid = new Prefab()
.AddPhysics()
.Add(new Asteroid{})
.Add(new SceneLayer{})
.Add(new CircleSprite{});
public const long SHIP_RADIUS = 4000;
public static Prefab Ship = new Prefab()
.AddPhysics(radius:SHIP_RADIUS)
.Add(new Thruster{})
.Add(new Health{})
.Add(new Gun{})
.Add(new CircleSprite { _Radius = SHIP_RADIUS, _Color = Color.green });
public static Prefab AIShip = new Prefab(Ship)
.Add(new AI{});
public static Prefab PlayerShip = new Prefab(Ship)
.Add(new PlayerInput{});
public const long BULLET_RADIUS = 400;
public static Prefab Bullet = new Prefab()
.AddPhysics(radius:BULLET_RADIUS)
.Add(new SceneLayer{})
.Add(new Bullet{})
.Add(new CircleSprite { _Radius = BULLET_RADIUS, _Color = Color.yellow });
public static Prefab AddPhysics(this Prefab prefab, long radius = 1000)
{
return prefab
.Add(new Position{})
.Add(new Rotation{})
.Add(new RigidBody{})
.Add(new CircleCollider{_Radius = radius});
}
}
// Spawn prefabs
public class Example : ComponentSystem
{
struct Data
{
public int Length;
public ComponentDataArray<Gun> _Guns;
public ComponentDataArray<Position> _Positions;
}
[Inject] Data _Data;
protected override void OnCreateManager(int capacity)
{
InitializePrefabManager.Initialize();
Prefabs.PlayerShip.Spawn()
.Set(new Position{_X = 100, _Y = 100});
}
protected override void OnUpdate()
{
for(int i = 0; i < _Data.Length; ++i)
{
PostUpdateCommands.Spawn(Prefabs.Bullet)
.Set(_Data._Positions[i]);
}
}
}
Thanks for sharing !
To be fully useful, I think you should add some way to spawn prefabs during system Update, for instance using PostUpdateCommands., etc.
Are you aware that you can instantiate a gameobject (prefab) and have it automatically create all the IComponentData-derived components on the ECS side without creating any actual game objects?
See EntityManagerExtensions.Instantiate(this EntityManager entityManager, GameObject srcGameObject)
Also, once an entity has been created, it can be used to instantiate clones in batch, which is vastly more efficient and should be the default for most simulations.
See EntityManager.Instantiate(Entity, NativeArray<Entity>)
@deplinenoise - is there a way for that to work across worlds? IE: Let’s say we have a world with no systems that we use to store prefabs entities in so they go untouched by normal worlds with systems. Or is there a universal way to freeze/exclude an entity in a world from normal processing?
this tread isn’t about game object prefabs this is about pure entities
it is useful to be able to construct and configure entity and store it in some form
and then to instantiate it several times
for example let’s take a bullet in a shooter game, when you spawn it, it’ll fly forward until hit something, and after hitting anything is removed, and when you have a machine gun you have to spawn lots of this bullets, also you bullets may have some default configuration options, like damage, size, speed depending on weapon used to spawn it
great way to do it is to clone a hidden pre-constructed and pre-configured single bullet entity many times (separate for each kind of weapon)
EntityManager.Instantiate is not good for this because original is not hidden (all systems affect original)
EntityArchetype is not good because it do not store default component values not pre-configured (only list of component types)
GameObject is not good because it is not an entity
this is what we are talking about,
not about using game object prefabs
The approach we are probably going to take is to have some kind of default “Inactive” component which is default disabled by all ComponentGroups. You could probably do exactly this manually for the time being.
In my case performance is not a key factor, so i’ve took a different approach:
I’m constricting EntityDefinition objects at startup using chained commands
this object is a container for 1) entity archetype and 2) list of components with defaults
and at runtime i’m constructing entities from this object with one method Spawn()
which adds several PostUpdateCommand-s
Hi,
I am not so good in programming, but I have been working for games using unity 3d,
tried to find a way to translate the below piece of code,
Please help me to translate the below piece of code in ECS
public GameObject pref;
public void CreateObjs()
{
for (int i = 0; i < 10000;i++)
{
Instantiate(pref);
}
}
also there are 2 more components attached with the prefab, Rigidbody and BoxCollider.
Thanks
Is there a way to use it with hybrid ECS? E.g. System that inherited from ComponentSystem is going to create objects on scene from prefab using EntityManagerExtensions.Instantiate. Or it is impossible right now?
this is a very old post, there is a prefab component now to instantiate “pure” entities
if you need a system that creates gemeObject each time you create an entity, you need to write a system for that yourself, there is no ready solution, but there is a way to convert gameobject to entity see New SubScene & ConvertToEntity workflows
Could you tell me how you would write the prefabs on the 1st post using the prefab component?
From what I see it doesn’t allow you to set default values for IComponentDatas
when your entity has a prefab component on it, it is ignored by all systems, but you still can clone it using EntityManager.Instantiate(), all clones receive the exact same set of components as prefab had excluding prefab component which is removed on clone during instantiation.