2
\$\begingroup\$

I've been reading about the SOLID principle and component-based game development. Lots of these posts explain it but don't really give examples on it.

For example, in a hypothetical RPG game, say there's a player class. The class consists of components like Inventory, Movement, and let's say a Roll component. You make the roll component so the player can use it, that's great and it works for the player. Now say that an enemy has the same roll component, how do you implement it? The enemy won't necessarily have the same animation, same roll distance, etc. Do you make a database with roll animations for different enemies? Do you have an animation variable in the enemy's class specifically for the roll component (even though this seems to break the SOLID principle)? Do you make the enemy class override the roll animation? It's specific things like this that I don't understand how to implement.

Another example of the inventory component. What would be responsible for equipping, dropping, or removing items? Do you put it in the inventory component and create messy code with dependency on knowing the owner of the inventory?

Maybe I'm not understanding SOLID or component based programming properly, I'm not sure.

If anyone has specific examples like this they could explain to me, that would be appreciated.

\$\endgroup\$
3
  • 3
    \$\begingroup\$ "let's say a Roll component" What is a "Roll component" supposed to actually do? "What would be responsible for equipping, dropping, or removing items? Do you put it in the inventory component and create messy code with dependency on knowing the owner of the inventory?" Those answers depend entirely on aspects of your design which are not stated. What do you want an "inventory" to mean? What does your game need to do? Always start with the requirements of your game. Never allow code design to dictate requirements to you. \$\endgroup\$ Commented Dec 22, 2018 at 16:44
  • 1
    \$\begingroup\$ Welcome to GDSE. In addition to Nicol Bolas' spot on comment, also keep in mind that programming guidelines like SOLID are only guidelines - there are always exceptions to the rules. Furthermore, it's been my experience that game dev seems to run into these exceptions more often. For instance, globals should be used sparingly, but most every game uses at least a couple somewhere. \$\endgroup\$
    – Pikalek
    Commented Dec 22, 2018 at 19:27
  • \$\begingroup\$ When you are talking about "component-based game programming", are you talking about the Entity - Component - System pattern? \$\endgroup\$
    – Philipp
    Commented Dec 22, 2018 at 19:47

3 Answers 3

0
\$\begingroup\$

You could have each of your components take in entity specific parameters, or load them from entity specific files. If you had an inventory component for instance, and you wanted a shops inventory to be large, you could pass in the number of slots in that components constructor. Then for say a chest entity, you could pass its inventory component a smaller number of slots.

In terms of your roll case I would have a supplementary attribute system in addition to the component system. Attributes are entity specific variables tied to names, much like a Javascript object or a Java Hash-map. Then you could have each entity add its entity specific attribute with a common name. So the player could send Player-Roll-Animation to the attribute 'Roll_Animation', where the enemy could send Enemy-Roll-Animation to the attribute 'Roll_Animation'. Then in your roll component when you want the animation or sound or whatever entity specific action to happen you can say execute 'Roll_Animation'. Each of your entities would react differently to this as they have passed their own specific animations.

\$\endgroup\$
0
\$\begingroup\$

I like how bay jose answered the question and just to add some more off of what he said, I assume you have some OOP understanding. You can create a class for each of the things as listed above and make it very abstracted such as a roll animation, you can have a generic class called something like: HumanoidClass that you can pass a string variable to and store an array of animations. You can then build off of that class by instantiating the class like so:

public HumanoidClass 
{
    //Tip For Generic Classes, don't derive from Monobehavior
    public animation rollAnimation;

    void SetAnimation(string animation)
    {
        this.rollAnimation = animation;
    }
    animation GetRollAnimation() 
    {
        return this.rollAnimation;
    }
}

public EnemyClass() 
{

    public animator anim;

    HumanoidClass humanoid = new HumanoidClass();

    humanoid.SetAnimation("Enemy_Roll_Animation");

    anim.play(humanoid.GetRollAnimation());
}
\$\endgroup\$
0
\$\begingroup\$

Now say that an enemy has the same roll component, how do you implement it? The enemy won't necessarily have the same animation,

You can solve this problem by using Animator Override Controllers. This handy component allows you to replace individual animations in an animator controller without changing the state machine of the controller itself. That means you can have multiple objects with the same animation controller governed by the same parameters but unique animations for certain states of the animator state machine.

same roll distance, etc.

Assuming the roll distance is not governed by the root motion of the roll animation you assigned through the animator override controller, it should be a serialized field of the Roll component.

Another example of the inventory component. What would be responsible for equipping, dropping, or removing items?

The Inventory component would be responsible for keeping track of the content of the inventory, nothing more and nothing less. It would expose certain methods for manipulating the inventory (AddItem(type, count), TryUseItem(type), GetCountOfItem(type) etc.) but calling those methods should be the responsibility of other components. For example, there could be a PlayerInputController which interacts with an inventory on the same gameObject, and there could be a PotionThrowerEnemyAI which also interacts with an inventory on its gameObject.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .