#Scriptable Objects, Prefabs and Instancing

1 messages · Page 1 of 1 (latest)

drifting frost
#

New to Dots
I'm used to serializing everything in the editor, using Prefabs, Scriptable Objects, having them set up, stored and then loading them at runtime when needed and instancing them if needed when needed

For example, having Scriptable Objects (as spawncards) which hold prefabs due to how there's the baker and how it exists, and subscenes, do I have to do anything about object instancing? Is it not possible? Can I instance a sole prefab directly at runtime, or do I have to put it in a subscene, and then instance the subscene?
Can I have a normal prefab, with components, which just so happens to have a ECS authoring component and instance it at runtime or does it have to be already aprt of the scene? Right now, Cameras don't have a ECS version, so you have to create a Camera object and wire it up with an authoring component, making it a hybrid of ECS and traditional gameobjects. I use cinemachine, so I have two different camera types, and instance them at runtime, as the brain is already part of the scene.

For scriptable objects, stuff like items, skills, all the data related to them.
This is used at runtime to evaluate what has to happen, and inherance is used widely to define behaviors
BUT since they are a managed object, I have no idea how to handle it with dots, I thought of probably making a IComponentData, making it serializable and using it in a Scriptable Object, then putting it in Authoring.
I don't see a way to getting around making it unmanaged and getting rid of inherance, so I don't know if its worth it to make it part of ECS, and this circles back to the question if I can make a prefab/gameobject/entity? mixed up with standard monobehaviors....

Kinda a weird thread, there's not a clear focus / question being made and it's more about general information, when compared to a standard unity instancing / deleting workflow, and scriptable objects usage, at least that's what I think

bold ginkgo
#

I suggest breaking down this big "question" into a detailed bullet list. Ask specific questions so people can help you better.

#

For examples:

  • How do I do X?
  • Is there an alternative to Y?
  • etc.
#

Btw, in general, I can say that ECS requires a specific form of runtime data to operate. And these data could be prepared beforehand by IBaker+Subscene, or at runtime by ISystem/SystemBase. Each have its own pros and cons. (For me I use both, depends on the situation.)

#

For GO prefabs, you can use IBaker to convert them into Entitys and store them in a blob asset if you prefer centralized management.

#

Think of blob assets as a kind of scriptable object, but with more restrictions.

#

If you prefer runtime conversion, then you will have to make some systems to do this on your own. IBaker won't work at runtime. But you can create blob assets at runtime, no problem though.

#

Once you have the Entitys, you can instantiate them at runtime, it's somewhat similar to instantiating GO prefabs.

#

Another point is, Unity does provide necessary authoring and runtime mechanism for some components, but not all of them. Camera and Cinemachine are one of those that aren't supported yet.

#

For them, you have to use the hybrid approach. But remember that, ECS must control GOs, not the other way around.

#

For me, I use a combination of unique ID and dictionary to manage these GOs and to map them with their Entity counterpart. Then I make some systems to transfer data from ECS to these GOs.

#

About the later part of your question, from this point:

For scriptable objects, stuff like items, skills, all the data related to them.

#
  • Do you really need inheritance?
  • Can you just see them as data?
  • Can you break them down into unrelated data pieces?
#

You should think of behaviours in the relation to their required data. That way you can get rid of inheritance.

calm dirge
#

Which requiers advanced knowledge and is in no way a mainstream approach

#

Blob assets are only meant to store unchangable data. Entities can't be stored there from baking.

bold ginkgo
#

It was meant for Prefab entity which shouldn't change, I suppose?

calm dirge
bold ginkgo
#

Oh, that's what I don't expect. Thanks. For me I didn't use blob asset to store them actually. I collect these prefab entities at runtime and build a hashmap from there.

calm dirge
drifting frost
# calm dirge ECS has no inheritance - only composition. I suggest to just go over tutotials o...

Yeah been using the tutorials and using the dots implementation of https://github.com/Unity-Technologies/CharacterControllerSamples as reference since it's the package I am using (since I'm extremely used to this dev's previous kinematic character controller package that didn't use dots)

GitHub

Sample projects for the Unity.CharacterController package - GitHub - Unity-Technologies/CharacterControllerSamples: Sample projects for the Unity.CharacterController package

drifting frost
#

Since In all the code i've referenced isn't used / i haven't noticed - caught - a way to use it

drifting frost
#

So say, I can probably make a component that tracks the entity created, and that component destroys the entity when the component (and in translation, gameobject) gets destroyed?
Something like

DisposeEntityOnDestroy : MonoBehaviour
  Entity entity
  EntityManager entityManager //(or world)

  OnDisposed
    entityManager.Destroy(entity)



SomeWackySystem
  Entity entity = entityManager new entity
  entity.addComponent(new DisposeEntityOnDestroy(){entity = entity, entityManager = entityManager})

Or is this way too hacky and potentially ilegal

#

Like the system manages the creation of entities, but there on the hybrid entities manage themselves whenever they die

drifting frost
#

Like, at all

calm dirge
drifting frost
# bold ginkgo - Do you really need inheritance? - Can you just see them as data? - Can you bre...

Do you really need inheritance?
The only way I can think of breaking inheritance is moving all the "base data" of a skill into an Interface, then have the different specializations around in each struct
It's more about I can make multiple different behaviors for skills but I should be able to have a common Type to handle all the data in a single place

Can you just see them as data?
I mean, most of them are just data, and some of them have unique behavior, which gets instanced as its own class and then executed from a monobehavior, which could be said it's also "just data" because of them being instanced and getting all the required stuff passed by parameter?
My main concern is more about the unmanaged types, since scriptables can just hold anything, though I guess I can somehow try turning them into blob references...?

Can you break them down into unrelated data pieces?
Can try to, but I won't know until i've done a real attempt

drifting frost
# calm dirge blobs are just read only unmanaged data

read only directly from the disk or at runtime? Can I just create a different version of a blob at runtime when instancing them?
Like, the "read only from disk" would require me defining new everything already in the editor and pack them in the build, and then those will never get edited, and from runtime is well, maybe a comparison with read only array where you initialize the array with any data you want but then you cannot touch the array itself would be valid?
Not sure if I explain myself

drifting frost
#

Okay that makes more sense

calm dirge
#

their goal is so you create them at bake time

#

serialize

#

and then desserialize in same format

drifting frost
#

Wait so from memory but you cannot do it at runtime of the game because baking only happens in editor

calm dirge
#

no, you create blobs at runtime

#

but it's best to just load ready data

drifting frost
#

well yeah serialization is best but I wanna know my options and specifications and stuff, for whenever that is not possible or there's something that benefits more from being done while playing

#

searching the web there's not much stuff on how to make ESC hybrid stuff

calm dirge
#

regarding your inheritance problem:
Ecs is all about composition and data.
So instead of ITransform, you will just have Transform struct.

And to create behaviour you mix components:
so with ihneritance you'd have ZombieTransform.
But in Ecs you'll have ZombieComponent together with Transform component and system will operate on query of entities, that contains both to do logic that ZombieTransform was doing.

drifting frost
#

So any of the components ZombieComponent Transform wouldn't have any reference member / field to the other, and instead as they live within the same entity you can write the "MonoBehaviour" that would treat that logic as a system with one of those queries that make sure the entity has the components you require

calm dirge
drifting frost
#

I haven't seen this in docs or any code, but are nested queries ie get component data of T, then inside the foreach get component data of Y a thing that exists that you can do? It kinda sounds like a dumb question, dunno

drifting frost
#

So you have a query of component data of T, you do inside your stuff with component data of T, and inside of there you do another foreach for component data of Y, so do all the logic related to T and if the entity that has T also has Y inside, you also do logic related to Y
Instead of having two queries duplicating code (one query for just T, and another for T and Y, the second which has duplicated code from the first query to handle T)

calm dirge
#

things for that are implemented differently

#

in short - no you don't do nested queries

drifting frost
#

So how is such situation implemented? Maybe have a Job Handle (never used them yet?) and call it in both queries?

drifting frost
#

For example, the character system handling character data, and then as characters can have optional data, lets say, a health pool, it also treats the health pool, if that exists

calm dirge
#

you only do queries that exactly match what components are required

drifting frost
#

So if I have to do something like that there's probably something im designing wrong

calm dirge
#

yes

drifting frost
#

So instead of having a flow of, for example

  • Update Character
    • If has health,
      • update health
        - If health is zero, kill character (the reason why this is nested)

A more proper approach would be

  • Update Character
  • Update Health
  • Update Character & Health
    • If health is zero, kill character
calm dirge
#

so for example

#
  1. SomeAbstractDealDamageSystem - adds damage entries to target's DamageBuffer (list).
  2. DamageApplicationSystem - applies damage to Health, minus armor and etc.
  3. DeathSystem - checks if Health is below 0, if so sets Dead to true.
drifting frost
#

I'd just have to figure out how to implement different types of deaths and their repercussions, since characters and healths are meant to be decoupled- Imagine having a destructable block in the environment, that's not a character

#

So about gameobject instancing, which is something I mentioned, how would I go around coupling / pairing up entities with prefab instances?

#

Characters aren't meant to be part of the (sub)scene(s), after all, they spawn in

calm dirge
#

ExplodeOnDeathComponent with Dead component

#

boom

drifting frost
#

And then i'd have to manually write each component and behaviour in the system

#

wack.....

calm dirge
#

similiar to game objects

#

you can just have

#

InstantiateOnDeath

#

which will reference entity prefab

#

you don't care what components it'll have

#

except transform

#

(so it spawns on dead entity)

drifting frost
#

So having a prefab with an authoring component and instancing it normally is fine? it would add the related authoring entity to the system?

calm dirge
#

no

drifting frost
#

No wait that goes back to the baker question

calm dirge
#

you bake entities

#

and store entity reference

drifting frost
#

Shit, so it's something to like having models manually placed in a world so they are pre-cached and whenever you change environments they are already in memory? Like, TF2 did this with the orange box console releases where the main menu was dustbowl and behind the camera there was all the sentries and character models and weapons and stuff

calm dirge
#

huh?

drifting frost
#

kinda a bad example
so i'd have to make a sub-scene and store that subscene in my project, and then load subscene, then select the gameobjects from there?

calm dirge
#

not game objects

#

entities

drifting frost
#

Well, entities

#

I have absolutely no idea how to do this with addressables

calm dirge
#

you don't

#

entities are managed by content management

#

which is somewhat of a clone of addressables

#

but much simpler

drifting frost
#

a third asset system????

calm dirge
#

yes

drifting frost
calm dirge
#

dw, if you do ecs project

#

you don't use anything else

drifting frost
#

why didn't i see anything about this in the manual.................

drifting frost
#

well the idea was to have at least a hybrid project...... i don't know about a full fledged ecs game.....

calm dirge
#

look

#

ecs from dots is like a new engine

#

you have backwards compatibility, since it runs in parallel

#

but making mix of game objects and entities - is likely to be much harder than pure ecs project

#

you will still use game objects (for example for vfx, audio, maybe animations)

#

but from within ecs world

#

not vice versa

drifting frost
#

the initial idea for me was to put the most expensive systems, like movement, characters and AI, in ECS, and then the rest would be up in the air

calm dirge
#

you'd be bottlenecked by cost of moving data between game objects and entity world

drifting frost
#

So everything has to be through authoring

calm dirge
#

Authoring is a process of making data for entity baking

#

I think you missuse the term

drifting frost
#

I probably do

#

-okay so everything has to be through a ISystem or a SystemBase

#

would be the proper way to say it

calm dirge
#

are you trying to say that everything should be entities?

drifting frost
#

There's just some data which I literally cannot turn into structs, for example state machines, which rely entirely on inheritance

calm dirge
#

if you already have existing project - don't bother with ecs

#

just try to use jobs and burst

#

conversion of existing projects is a nice way to waste a lot of time

drifting frost
#

Well it's a project I already had started, but I didn't have an actual game / gameplay

#

And, yeah, spent the last week doing stuff with ecs

#

because I already had a somewhat data-oriented approach, avoiding bloating prefabs with components and stuff

calm dirge
drifting frost
#

well other than what I already replaced they weren't really set in place yet, the classes were just already defined, some of them with written logic and methods and that's all

bold ginkgo
#

The components come from GameObject world will have only 2 uses:

  1. Provide authoring data for baking systems.
  2. Provide a presenter mechanism for the entity world (hybrid approach for things that don't have ECS alternative yet). For example, I'm relying on SpriteRenderer just to show 2D sprites because there is no DOTS 2D solution that fits my need yet.
#

There are some unique 2D animations made with Spine and we can only use them in GameObject world. So there will be some prefabs with components from the Spine runtime library. But they are there to show only. They won't ever interact with any other gameobjects.

#

Most of my gameplay logic are written in ECS.

drifting frost
#

So as long as they are "self-contained" and do not touch on the lifetime of the entity its fine

drifting frost
calm dirge
bold ginkgo
#

I have to transfer data from the entities to their GO presenters. However, I limit the cases where I need data from GO world transferred back into the ECS world.

#

In general, I design the code so the data transferring is mostly 1 way: ECS => GO.

#

I'm not really sure if the word "self-contained" is correct to descibe this.

#

But GO will not interact with Entity, not transfer data to Entity.

#

But Entity can transfer data and interact with GO in a limited way, to reduce the rate of bottleneck.

calm dirge
#

basically, the only way for entities to communicate with GO in somewhat performant way - transforms

bold ginkgo
#

The only cases where I need to read data from GO are inside some initialization systems.

calm dirge
#

thanks to IJobParallelForTransform

#

aaaand, that's it

bold ginkgo
calm dirge
#

and just copy it

#

while instead of internal CompanionLink use your own managed icd

sacred fractal
#

After reading Issue's suggestion, I thought I'd take a look at parallelizing my own "entity->go transform sync system" and noticed that the entities version takes a lookup on LocalToWorld without passing readonly=true even though the IJobParallelForTransform only ever reads from it (right?). https://github.com/needle-mirror/com.unity.entities/blob/4687de6a32cbcd99443282806fa6393f1ab1ca35/Unity.Transforms.Hybrid/CompanionGameObjectUpdateTransformSystem.cs#L170

localToWorld = GetComponentLookup<LocalToWorld>(),

Any reason why it would be done like this or just an oversight forgetting to pass readonly=true?