Parent with Child Components; How do I get a vehicle with the connected wheels?

TLDR; How do I get a component with the connected child components?

I’m creating a vehicle system using Hybrid ECS. I need the vehicle engine to manipulate the wheels. So far the only way was to save the vehicle parent Entity index with each wheel and use the entity manager to retrieve it. This caused slow down and I couldn’t multithread it. :frowning:

How can I A. return the vehicle with all of the wheels or B. return a single wheel with the parent vehicle?

Basically, I’m trying to either:
use this in the ComponentSystem

    public struct MyVehicles
    {
        [ReadOnly] public ComponentDataArray<VehicleEngineData> engines;
        public ComponentDataArray<WheelData> wheels; // I need this to return all wheels from this vehicle
 
        public readonly int Length;
    }
 
    [Inject] private MyVehicles vehicles;

or use this in the JobComponentSystem

public struct MyVehicleJob: IJobProcessComponentData<VehicleEngineData, WheelData>
{
    public void Execute([ReadOnly]ref VehicleEngineData v, ref WheelData w)
    {
        //Do awesome stuff with Vehicle and all connected wheels...
    }
}

I could create a ComponentArray with the ComponentSystem containing a list of the wheels but I feel like that defeats the purpose of using ECS, plus if I decide to move to Pure ECS once physics are implemented that may not work.

Any help would be greatly appreciated. :slight_smile:
I almost never use the forums, because I can normally figure things out - but since ECS is still pretty new, there aren’t many tutorials and how-tos. If this answered hopefully it will help other devs.

Instead of the EntityManager, you need to use the ComponentDataFromEntity class which can be used in jobs.

E.g. In the ComponentSystem that iterates your wheels, you would have

public struct MyWheels
{
    public ComponentDataArray<WheelData> wheel;
}

[Inject] ComponentDataFromEntity<VehicleEngineData> vehicleEngines;

void onUpdate()
{
    for each wheel
        WheelData wheel = ...
        VehicleEngineData ved = vehicleEngines[wheel.VehicleEntity];
}

It’s a random access lookup to get the VehicleEngineData component from another Entity.

The other alternative is to use a shared VehicleEngineData component on each wheel.
Then for a given engine, you would get 4 contiguous wheels.
I’ve no idea which of these scenarios would be more optimal for your situation though. It probably depends on how many cars you’ve got.

2 Likes

Thanks a million. I’ll try both of the suggested methods. However, the alternative method using a shared component…

public struct WheelDataComponent: ISharedComponentData
{
    public WheelData                  wheel;
    public VehicleDataComponent       vehicle;
}

This wouldn’t work with the JobComponentSystem, right? I think, in the end, I am trying to make sure I use multithreading as much as possible since raycasting is my main bottleneck.

SharedComponentData is not available to jobs afaik.