Skip to main content
added 353 characters in body
Source Link

I've been scouring information on Entity-Component-System designs for weeks to try to figure out how to implement it in C++, and there are lots of wonderful explanations for different aspects of it, but the one thing everybody seems to overlook in examples is how you actually access whatever the data members are in a specific derived Component class when all you have is a list of base class pointers in your Entity. I'm still new to programming in general, so if that's something that's "common knowledge," it's not common enough for all levels of skill.

The only way I can think of is to have a virtual function that returns an enum for the type of component and then cast it to that, but that seems like a hack job, and I can't help but feel like there must be a better way.

Edit: This is what I'm trying to accomplish:

//incomplete pseudocode

class DerivedComponent1 : public BaseComponent
{
  int a;
  int b;
}


class DerivedComponent2 : public BaseComponent
{
  string str;
  float c;
  float d;
};


class Entity
{
  vector<BaseComponent*> components;
};


class System
{
  void init()
  {
    entityInstance.components.push_back(derivedComponent1Instance);
    entityInstance.components.push_back(derivedComponent2Instance);
  }

  void doTask()
  {
    //access derived class members somehow
    entityInstance.components[0]->accessDerivedComponent1Members();
    entityInstance.components[1]->accessDerivedComponent2Members();
  }
};

This is in a system for a video game where an Entity can have zero or one of each type of component, like a health amount or a transform, and a System will only act on an entity that owns the specific components it needs to do its task, so behavior is customized by giving the Entity the correct Components for the desired behavior. The only way I can think of to do itaccess the component data is to add an enum with the component type and make doTask() something like this:

//incomplete pseudocode

enum ComponentType
{
  Derived1,
  Derived2
};


void System::doTask()
{
  DerivedComponent1* derived1;
  for(auto i : entityInstance.components)
  {
    if(i->getComponentType()==ComponentType::Derived1)
      derived1 = dynamic_cast<DerivedComponent1*>(i);
  }

  .
  .
  .

}

but my understanding is that if your code has to rely on casts, then it's probably bad code. My question is if there's a better way to do it.

I've been scouring information on Entity-Component-System designs for weeks to try to figure out how to implement it in C++, and there are lots of wonderful explanations for different aspects of it, but the one thing everybody seems to overlook in examples is how you actually access whatever the data members are in a specific derived Component class when all you have is a list of base class pointers in your Entity. I'm still new to programming in general, so if that's something that's "common knowledge," it's not common enough for all levels of skill.

The only way I can think of is to have a virtual function that returns an enum for the type of component and then cast it to that, but that seems like a hack job, and I can't help but feel like there must be a better way.

Edit: This is what I'm trying to accomplish:

//incomplete pseudocode

class DerivedComponent1 : public BaseComponent
{
  int a;
  int b;
}


class DerivedComponent2 : public BaseComponent
{
  string str;
  float c;
  float d;
};


class Entity
{
  vector<BaseComponent*> components;
};


class System
{
  void init()
  {
    entityInstance.components.push_back(derivedComponent1Instance);
    entityInstance.components.push_back(derivedComponent2Instance);
  }

  void doTask()
  {
    //access derived class members somehow
    entityInstance.components[0]->accessDerivedComponent1Members();
    entityInstance.components[1]->accessDerivedComponent2Members();
  }
};

The only way I can think of to do it is to add an enum with the component type and make doTask() something like this:

//incomplete pseudocode

enum ComponentType
{
  Derived1,
  Derived2
};


void System::doTask()
{
  DerivedComponent1* derived1;
  for(auto i : entityInstance.components)
  {
    if(i->getComponentType()==ComponentType::Derived1)
      derived1 = dynamic_cast<DerivedComponent1*>(i);
  }

  .
  .
  .

}

but my understanding is that if your code has to rely on casts, then it's probably bad code. My question is if there's a better way to do it.

I've been scouring information on Entity-Component-System designs for weeks to try to figure out how to implement it in C++, and there are lots of wonderful explanations for different aspects of it, but the one thing everybody seems to overlook in examples is how you actually access whatever the data members are in a specific derived Component class when all you have is a list of base class pointers in your Entity. I'm still new to programming in general, so if that's something that's "common knowledge," it's not common enough for all levels of skill.

The only way I can think of is to have a virtual function that returns an enum for the type of component and then cast it to that, but that seems like a hack job, and I can't help but feel like there must be a better way.

Edit: This is what I'm trying to accomplish:

//incomplete pseudocode

class DerivedComponent1 : public BaseComponent
{
  int a;
  int b;
}


class DerivedComponent2 : public BaseComponent
{
  string str;
  float c;
  float d;
};


class Entity
{
  vector<BaseComponent*> components;
};


class System
{
  void init()
  {
    entityInstance.components.push_back(derivedComponent1Instance);
    entityInstance.components.push_back(derivedComponent2Instance);
  }

  void doTask()
  {
    //access derived class members somehow
    entityInstance.components[0]->accessDerivedComponent1Members();
    entityInstance.components[1]->accessDerivedComponent2Members();
  }
};

This is in a system for a video game where an Entity can have zero or one of each type of component, like a health amount or a transform, and a System will only act on an entity that owns the specific components it needs to do its task, so behavior is customized by giving the Entity the correct Components for the desired behavior. The only way I can think of to access the component data is to add an enum with the component type and make doTask() something like this:

//incomplete pseudocode

enum ComponentType
{
  Derived1,
  Derived2
};


void System::doTask()
{
  DerivedComponent1* derived1;
  for(auto i : entityInstance.components)
  {
    if(i->getComponentType()==ComponentType::Derived1)
      derived1 = dynamic_cast<DerivedComponent1*>(i);
  }

  .
  .
  .

}

but my understanding is that if your code has to rely on casts, then it's probably bad code. My question is if there's a better way to do it.

Added an example
Source Link

I've been scouring information on Entity-Component-System designs for weeks to try to figure out how to implement it in C++, and there are lots of wonderful explanations for different aspects of it, but the one thing everybody seems to overlook in examples is how you actually access whatever the data members are in a specific derived Component class when all you have is a list of base class pointers in your Entity. I'm still new to programming in general, so if that's something that's "common knowledge," it's not common enough for all levels of skill.

The only way I can think of is to have a virtual function that returns an enum for the type of component and then cast it to that, but that seems like a hack job, and I can't help but feel like there must be a better way.

Edit: This is what I'm trying to accomplish:

//incomplete pseudocode

class DerivedComponent1 : public BaseComponent
{
  int a;
  int b;
}


class DerivedComponent2 : public BaseComponent
{
  string str;
  float c;
  float d;
};


class Entity
{
  vector<BaseComponent*> components;
};


class System
{
  void init()
  {
    entityInstance.components.push_back(derivedComponent1Instance);
    entityInstance.components.push_back(derivedComponent2Instance);
  }

  void doTask()
  {
    //access derived class members somehow
    entityInstance.components[0]->accessDerivedComponent1Members();
    entityInstance.components[1]->accessDerivedComponent2Members();
  }
};

The only way I can think of to do it is to add an enum with the component type and make doTask() something like this:

//incomplete pseudocode

enum ComponentType
{
  Derived1,
  Derived2
};


void System::doTask()
{
  DerivedComponent1* derived1;
  for(auto i : entityInstance.components)
  {
    if(i->getComponentType()==ComponentType::Derived1)
      derived1 = dynamic_cast<DerivedComponent1*>(i);
  }

  .
  .
  .

}

but my understanding is that if your code has to rely on casts, then it's probably bad code. My question is if there's a better way to do it.

I've been scouring information on Entity-Component-System designs for weeks to try to figure out how to implement it in C++, and there are lots of wonderful explanations for different aspects of it, but the one thing everybody seems to overlook in examples is how you actually access whatever the data members are in a specific derived Component class when all you have is a list of base class pointers in your Entity. I'm still new to programming in general, so if that's something that's "common knowledge," it's not common enough for all levels of skill.

The only way I can think of is to have a virtual function that returns an enum for the type of component and then cast it to that, but that seems like a hack job, and I can't help but feel like there must be a better way.

I've been scouring information on Entity-Component-System designs for weeks to try to figure out how to implement it in C++, and there are lots of wonderful explanations for different aspects of it, but the one thing everybody seems to overlook in examples is how you actually access whatever the data members are in a specific derived Component class when all you have is a list of base class pointers in your Entity. I'm still new to programming in general, so if that's something that's "common knowledge," it's not common enough for all levels of skill.

The only way I can think of is to have a virtual function that returns an enum for the type of component and then cast it to that, but that seems like a hack job, and I can't help but feel like there must be a better way.

Edit: This is what I'm trying to accomplish:

//incomplete pseudocode

class DerivedComponent1 : public BaseComponent
{
  int a;
  int b;
}


class DerivedComponent2 : public BaseComponent
{
  string str;
  float c;
  float d;
};


class Entity
{
  vector<BaseComponent*> components;
};


class System
{
  void init()
  {
    entityInstance.components.push_back(derivedComponent1Instance);
    entityInstance.components.push_back(derivedComponent2Instance);
  }

  void doTask()
  {
    //access derived class members somehow
    entityInstance.components[0]->accessDerivedComponent1Members();
    entityInstance.components[1]->accessDerivedComponent2Members();
  }
};

The only way I can think of to do it is to add an enum with the component type and make doTask() something like this:

//incomplete pseudocode

enum ComponentType
{
  Derived1,
  Derived2
};


void System::doTask()
{
  DerivedComponent1* derived1;
  for(auto i : entityInstance.components)
  {
    if(i->getComponentType()==ComponentType::Derived1)
      derived1 = dynamic_cast<DerivedComponent1*>(i);
  }

  .
  .
  .

}

but my understanding is that if your code has to rely on casts, then it's probably bad code. My question is if there's a better way to do it.

Source Link

How do you actually access the data of individual components in an Entity-Component-System design? (C++)

I've been scouring information on Entity-Component-System designs for weeks to try to figure out how to implement it in C++, and there are lots of wonderful explanations for different aspects of it, but the one thing everybody seems to overlook in examples is how you actually access whatever the data members are in a specific derived Component class when all you have is a list of base class pointers in your Entity. I'm still new to programming in general, so if that's something that's "common knowledge," it's not common enough for all levels of skill.

The only way I can think of is to have a virtual function that returns an enum for the type of component and then cast it to that, but that seems like a hack job, and I can't help but feel like there must be a better way.