Entity component architecture : want to split big entity -> hard to refactor

90 Views Asked by At

In the first step of development, I design Car and AI as 1 entity.
It works nice (pseudo code):-

for(every entity that is "racing car"){
    //^ know type by using flag 
    //   or iterate special component (e.g. "RacingCarComponent")
    Entity entity=...
    AI* ai=get<AI>(entity);
    ai->setInformation(...) 
}
for(every entity that is "bicycle"){
    Entity entity=...
    AI* ai=get<AI>(entity);
    ai->setInformation(...)   //the info is very different from "racing car"
}

Later, I want a new feature : switch in-out Driver (which effect AI).
I split the entity as shown in the following diagram :-

enter image description here

The above code will be updated to be :-

for(every entity that is "racing car"){
    Entity entity=...
    AttachAI* aiAttach=get<AttachAI>(entity);    //<-- edit
    aiAttach->ai->setInformation(...)            //<-- edit
}
for(every entity that is "bicycle"){
    Entity entity=...
    AttachAI* aiAttach=get<AttachAI>(entity);    //<-- edit
    aiAttach->ai->setInformation(...)            //<-- edit
}

Problem

It works nice both before and after the change, but it is hard to maintain.

If there are N types of vehicle in version1 e.g. truck, motercycle, plane, boat, rocket,
I will have to edit N*2 lines of which potentially have already scattered around many .cpp.

Main issue : If I forget to refactor any code, it will still compile fine.
Problem will appear in only run-time.

In real life, I face such issue whenever new design wish to divide an entity into many simpler entities.
The refactoring is always just adding another one indirection.

Question

Suppose that in version1, I don't expect that I will want to switch in/out Driver.
Is it possible to prevent the problem? How?

1

There are 1 best solutions below

1
On

I may be mistaken, but it seems as though you may be looping through all of the entities multiple times, checking a condition. I am not exactly sure about c++ syntax, so please bear with me:

for (entities as entity) {
  info = null;

  //Check type to get specific info
  if (type is a "racing car"){
    info = "fast car";
  } 
  elseif (type is a "bicycle") {
    info = "rad spokes";
  }

  //If we found info, we know we had a valid type
  if (info isnt null) {
    aiAttach = get(entity);
    aiAttach->ai->setInformation(info);
  }
}

I'm not sure if the get function requires anything specific for each type. In my pseudocode example, I assume we are only sending the entity and not something type specific. If it does, an additional variable could be used.