I want to add links to child components to a prefab so things can be configured at runtime.
The thing is this means adding a monobehaviour to every instance of this prefab.
Surely with DOTS it’s possible to add just the data needed e.g. in a Struct or Component that can be stored with a prefab.
Then when I instantiate lots of these prefabs I will only need one Monobehaviour manager or system to configure them.
So can I add data to a prefab using DOTS?
Side note: I don’t think Scriptable Objects quite fits the bill for this as it’s a lots of references per prefab not a few configuration styles that can be used across lots of entities.
In any ECS, you never hold links to components directly; but instead you always just have links to entities. At runtime, you can retrieve the component you’re looking for on that entity
I’m not 100% sure I understand the use case, but:
[GenerateAuthoringComponent]
public struct TestComponent : IComponentData
{
public Entity ChildA;
public Entity ChildB;
}
If you have this in your project, it’ll generate a “TestComponentAuthoring” that you can put on your prefab, and the “ChildA” and “ChildB” fields will allow you to hold references to child Entities that you can assign in the inspector. Let’s say you need to initialize collider parameters on those child entities, you’ll just go do a “GetComponent(testComponent.ChildA)” and change its data
That defeats the object of the data driven approach as instead of having thousands/millions of prefabs in scene where I have direct references to their relevant components at runtime.
I would have the overhead of thousands/millions of Get Component calls.
Something I can get around with a standard Monobehaviour component and reference parameters.
I think I would need an example use case in order to better answer this
But maybe what you’re looking for is BlobAssets: basically the same thing as ScriptableObjects, but their reference can be stored inside ECS components
You have prefabs with N game object elements which at runtime you want to be able to change via code.
Monobehaviour approach: Add a class to each element that stores references to the elements and components you want to interact with.
At runtime with a Manager class loop through changing/tweaking the components as needed stored in a container.
Just Monobehaviour comes with a lot of baggage and all I need is a struct/class that can be added to a prefab and accessed at runtime and edited via the ide.
I thought DOTS or Hybrid DOTS would be easily capable of doing this by now?
Even so it’s a function call with a fixed time that I will probably be calling millions of times. When I just need a reference to the component/gameobject.
The approach to solving this in ECS might look different from the approach you described (which is an approach designed specifically for OOP)
But the implementation of it will depend on your exact precise use case. For example: will you need to apply changes to all components of all prefabs at the same time, or just all components of a specific prefab, or specific components of multiple prefabs? Will they all get the same changes, or will they each have their specific changes? At what frequency will those changes happen? etc…
we really need the specifics of what you want this to accomplish
Burst has a tendency to not differentiate between the two.
I know what he is asking for. He just wants an IComponentData on the root of his prefab that stores references to children entities with specific components. And then he wants to run a system across this component and scatter a bunch of initialization data across a bunch of instantiated entities. So he just needs an IConvertGameObjectToEntity to wire up the component on the prefab, and then a runtime system with an Entities.ForEach and a whole bunch of CDFEs with NativeDisableParallelForRestriction. He’s somehow hung up on the overhead of a “function call” when more likely his bottleneck is going to be the random accesses and potential false sharing.
Anyways, I do this sometimes when runtime-initialized data is tightly coupled. It is as fast as you would expect for a scatter op.
When I was talking about specifics, I was thinking of a game where you have a bunch of cars belonging to different teams. At some point, Team A purchases an upgrade, and you want to apply a new set of data to all cars & all wheels that belong to TeamA (let’s pretend TeamA has 1000 cars). You could do:
Get all the data you want to apply in a struct “myNewData”
Schedule a job that iterates on all “Car” + “Team” components
if teamA, write new data to car component using “myNewData”
Schedule a job that iterates on all “Wheel” + “Team” components
if teamA, write new data to wheel component using “myNewData”
Perhaps use some strategy to group same teams by chunk & only do the team check once per chunk (team is shared component?)
If GetComponent would truly be called “millions of times” , then trying to do something like this could be worth it I think (I’m assuming that might have been hyperbolic, but still… let’s say “thousands of times”)
But maybe some other scenarios don’t lend themselves as nicely to filtering by archetype. Or maybe depending on the amount of cars & component types affected, there would be a threshold under which the CDFEs approach would actually perform better