Prefab workflow and "managing"

I’m about to decide how to manage my prefabs in my game consistently and (hopefully) “future proof”. Thus I would like to discuss some “best practices” and advantages / disadvantages for some workflows regarding prefabs. As preparation I watched Code Monkey’s introduction to prefabs. And I must say that I’m an ECS noob and thus can’t really see advantages and disadvantages of different methods. And since this video is 9 months old maybe in the meantime better options are available (Subscenes)?
So I hope this discussion will help some ECS “noobs” to find a proper workflow for them in the many different possibilities.

So the aim of this thread is to discuss how to get prefabs properly (the intended way) into ECS worlds and be able to spawn them from there. When working with MonoBehaviors I had a custom poolmanager which knew every prefab in the game and I could spawn stuff from there (I work mostly with procedural generation and distribution). So I would like to have some kind of “manager” which knows every prefab and which the systems could order to spawn stuff. For example when a projectile is fired or a planet shall be placed.
When I say “prefab” I mean mostly the art side of things (models, textures, particle systems). I like to place them “under” an entity which has the game logic components.

Methods to convert prefabs:
A) Store it in an IComponentData with a [GenerateAuthoringComponent] on a GameObject with a ConvertToEntity script.
Pros:
easy and least verbose, “direct” way
Cons:
Runtime conversion, probably slow

B) Store it on a MonoBehavior which implements IConvertGameObjectToEntity.
Pros:
more controll with manual conversion, but usefull for what?
Cons:
much boilerplate code.
Runtime conversion, probably slow

C) On a MonoBehavior which implements IDeclareReferencedPrefabs and IConvertGameObjectToEntity.
Pros:
more controll with manual conversion, but usefull for what?
Cons:
much boilerplate code.
Runtime conversion, probably slow

D) Implement a GameObjectConversionSystem to “hook” into the conversion.
only mentioned in the video but not properly explained.

E) Subscenes (are not mentioned in the video).
Pro:
Editor Conversion, fast (playmode), recommended way AFAIK
Cons:
Harder to work with in Editor? Access via subscenes. Must be present in scene hierarchy instead of the project view.

Methods to “access” those prefabs:
S) A field in an IComponentData with [GenerateAuthoringComponent].
Cons:
requires a foreach over a single entity.

T) A static field in a (converted) component.
Pros:
No Entities.Foreach to access it.
Cons:
static messing up Chunk utilization?

U) Singleton
Cons:
Chunk utilization? Is better support for them to be expected?
Only one prefab component allowed?

V) Blob asset
Only mentioned in the video. Not explained properly.

For my special usecase, a “global” spawn manager which knows all possible prefabs, I tend towards conversion method E) (subscenes, not sure how to organize that) and I would mix access types T) and U) (a singleton with a static field for each prefab type). Is this viable?

questions:
So which of those methods do you use and why?
Do you see more advantages or disadvantages for specific ones?
Are there other possibilities not mentioned here?
Which method do you think will “survive” DOTS evolution? Or are they all equally valid and here to stay? (I know this is speculative).
What about extensibility through mods. So when modders wan’t to bring additional content in the game how can it be referenced?
How do these methods play together with the archetype system?
How does this allow “setting” values during spawn (positions for projectiles, color for laser, scale for planets)? I would like to have a method to spawn each type with proper (default) parameters. Can these be static methods in a system which are called from the generation system? Or is this not “data driven” enough?
How does this play together with texture atlases? When some of the models share parts of the same texture. Is this handled gracefully by Unity under the hood?
Which method is preferable for “hybrid” entities which also have a parallel GameObject and are synched?
How could an “automatic” way be achieved? I mean simply dropping a prefab into an array and it gets available in ECS without changing code.
Does someone create prefabs directly in ECS (as Archetype for example)? How can assets like models and textures be handled this way?
Is this way desirable at all or is this a dead end? How do you handle prefab workflow?

I know this is a large post and it’s asking many questions. But as a “noob” in ECS I fell pretty overwhelmed by those different methods to do the same thing. And since documentation still su…, eh lacks, I thought I ask here. And if there are good suggestions this could be useful for many people trying their hands on ECS. And maybe some of the “authorities” are willing to give some insight into future plans for prefab workflow.
So I hope some of you are willing to share your experiences. Thanks in advance.

1 Like

A combination of D & E can allow you to fetch the asset containing the GameObject prefabs, run conversion on the container and all the prefabs inside it so they become entity prefabs, and add it to the subscene without needing to touch the Hierarchy.

I have a custom implementation for option U which compacts singletons into a couple of entities and does not use EntityQueries. That’s what I would use for this workflow.

I don’t have time to write an essay answering all your other questions at the moment.

1 Like

@DreamingImLatios so to read between the lines here you would recommend a GameObject in a Sub Scene that holds references to all the prefabs?

AFAIK the only hint we have from Unity about the “correct” way to do this right now is this method, since this is how they do it in their samples. But for the record this definitely doesn’t (or shouldn’t if you’re doing it correctly) involve any runtime conversion. Doing it this way gives you canonical entity versions of your prefabs, which you can use to instantiate from at runtime.

To be clear you would be instantiating from entity prefabs at runtime, not gameobject prefabs.

That being said, I’m not a fan of this method, it’s very indirect and annoying. I would hope once we have a better method of converting scriptable objects/assets we could also use that for converting prefabs instead*.*

1 Like

@Sarkahn_1 I do not see “the point” of using IDeclareReferencedPrefabs. There is no way to access this list outside of the Convert() function.

If I have a spawn system and I want OnCreate() to set a private variable m_Prefab, what good is that list if I cannot reference it to set my prefab which will be used on OnUpdate()?

Instead why not create a GameObject in a Sub Scene which has as many Authoring Components as there are prefabs I want to reference?
PrefabCollection

  • AsteroidAuthoringComponent
  • PlayerAuthoringComponent
  • BulletAuthoringComponent

Each component is just:

[GenerateAuthoringComponent]
public struct AsteroidAuthoringComponent : IComponentData
{
public Entity Prefab;
}

I can then

var asteroidComponent = GetSingleton()
var m_Prefab = asteroidComponent.Prefab;

I guess I am missing how IDeclareReferencedPrefabs is meant to be helpful or used if I want to programmatically spawn prefabs.

This approach no longer works either: https://discussions.unity.com/t/802963/4
For some reason the PrefabCollection GameObject does not “convert” in a Sub Scene (to trigger adding the buffer data) without adding the “ConvertToEntity” component to the GameObject (?! I thought everything in a subscene is converted to an entity?!)

What do you imagine “Prefab” is referring to in this scenario, in the editor? You need some way to get the converted prefab in the first place - that’s what DeclareReferencedPrefab is for - it lets you signal to Unity what assets you need converted. Then you can use conversionSystem.GetPrimaryEntity inside the convert method (if you’re using a IConvertGameObjectToEntity) on your GameObject prefab to get the converted entity prefab and assign it to the “Prefab” variable on your singleton component.

The samples demonstrate this setup, I suggest you copy the sample and mess around with it to get an idea of how it works if it’s still not clear.

Sarkahn sorry for being dense but it is referring to the prefab I drag onto the component into the editor?

Thank you for the heads up in the sample I will give it a shot although it does not have a “Sub Scene” so I am concerned that it will not apply.

EDIT: Screenshot because I believe I was being unclear:
6675886--764710--upload_2020-12-31_16-14-47.png
System that programmatically spawns Asteroids:

public class TestingCreateAsteroidSystem : SystemBase
{
protected override void OnCreate()
{
RequireSingletonForUpdate<AsteroidAuthoringComponent>();
}

protected override void OnUpdate()
{
m_Prefab = GetSingleton<AsteroidAuthoringComponent>().Prefab;
EntityManager.Instantiate(m_Prefab);
}
}

This works great, I am wondering why this isn’t “it” for spawning prefabs? It’s simple enough and does what it needs to do. No use of IDeclareReferencedPrefabs…

2 Likes

Hahah, I had no idea this actually works. Normally an “Entity” field in a script would do nothing in the editor - as in it wouldn’t show up in the inspector and would not let you drop a gameobject in. Apparently “GenerateAuthoringComponent” does something behind the scenes to make this work and it does correctly convert a prefab. I have to imagine it’s basically doing what I described above behind the scenes, but yeah - good to know.

I guess if you need to do anything more complicated than setting fields on your entity during conversion then you’re stuck using IDeclareReferencedPrefabs though.

1 Like

Lol, I was as surprised as you are!

Okay phew… I am not taking crazy pills and it does seem like IDeclareReferencedPrefabs is useless in the context of programmatically spawning prefabs.

Yes, for the specific workflow the OP desired.

IDeclareReferencedPrefabs tells GameObjectConversion that the particular object referenced needs to be converted into an Entity prefab. It is necessary for this.

Sorry DreamingImLatios but if you don’t mind could you explain why it is necessary? I am not using IDeclareReferencedPrefabs at all and I am able to spawn my entities and they work as expected.

It’s necessary if you need to convert a prefab in an IConvertGameObjectToEntity script.

1 Like

Ahhhh, thank you @Sarkahn_1 !