Im trying to work out the best method to organise the code for a specific game character.
There are at least 2 main sets of functions, movement and actions
I dont really want both of these in my single class cos A, its getting hard to read and B, i might have alternative types of character that share movement but have different actions.
Do I :
A- make a bse class with the movement functions and then derive a new class with the actions
or B- make the 2 classes seperate scripts that end up as seperate components on a gameobject
with A: all vars/functios are considered local to the object, since they are just one extended class
with B: the 2 classes can talk via class pointers but can hide functions/vars and provide interfaces for neatness and stability
Whats the general idea? I feel unity is aiming for the B option, but im not sure
B… definitely B. If all else fails throw more scripts at it. This is akin to the AI scripting that I am doing. I have one script that is bascially a gas pedal and a steering wheel, and the other uses pointers in it to control pressing the gas and the steer. the AI knows what all it needs to accomplish and it uses the car as a tool to get there.
Yeah I know that, and thats essentially option A
What im interested to know is which option is perhaps ‘best’ considering both unitys design and the seperation/component nature of what im looking at
If you have multiple monsters, for example, it might be better to just make them via inheritance. The obvious advantage is you will have fewer script to maintain, which leads to fewer errors. You would still apply the lowest level script to the object, so it would still be an aggregate game object with mesh renderers, scripts, transforms, etc.
Having just gone through refactoring a bunch of stuff myself I’d say - use Inheritance (A) where you are extending base functionality and Components (B) where you are adding separate functionality. Use interfaces to define how they talk to each other.
Example: AI in one Component, Pathfinding in another, weapon calculations in another. That way you can mix and match. For example Any type of AI (friendly, monster, robot) can coexist with any Pathfinding mechanism, and can carry and use any kind of weapon.
Avoid ‘getting clever’ and overloading one particular class to do all things.
Unity made a revolution with component-based concept so you should better use it Or else - you’ll get the class expansion (the number of classes grows exponentially with each new ‘feature’).
thanks pak, the functionalities you mention are almost exactly what im setting out. IN my case they might end up all being on a single gameobject type, so i could do them via inheritance, but as people (dkozar too) are pointing out if i do need to recombine them later then component model is the way to go… Im just oldschool c++ oop all teh reference pointers in component based stuff makes me woozy
I’m still learning and dug up this thread during my research. The above example seems strange to me.
Why can I not add a color variable to Monster base class? If I add an AngryMonster component to a Gameobject, I can set the color variable in the Unity inspector. If I add a FunnyMonster component, I can also set the color variable in the Unity inspector.
Of course, if there is more differentiation between BlueAngry and RedAngry than just the color, this won’t be sufficient. But if so, you will need additional components in the component based design as well.
I just feel like it makes more sense to use inheritance when the components largely depend on one another. For example, you can’t just throw a Mood component on a rock or an inventory item. The Mood component will most likely require a Monster component (or possibly a Friend component or similar). Then you will need to make these components properly talk to each other. It seems like a bigger hassle than using inheritance?
I’ve been down both paths. Composition beats inheritance. Here is a random thought dump in no particular order.
Talking to other classes is no big deal if you properly encapsulate. Use SerialiseField to expose variables to the inspector. Keep everything private. Have some very narrowly defined interfaces for interaction. Use GetComponent as needed, and cache the references.
Controlling dependencies between components is much less of a maintenance issue the controlling massive inheritance chains.
In many cases you can actually use some inheritance, in the abstract base classes or interfaces to control you dependencies. An AI component might require a type of Movement component. Movement could be a bunch of different components that all share an interface or abstract base.
Document your dependencies with RequiresComponent. Then only access those components that you have specifically declared dependencies for.
Keeping your dependencies one directional also helps. In the example above mood can know about colour, but colour should not know about mood.
Sticking with the example. Let’s say that mood requires some kind of creature in order to function. But that creature could be a monster, an ally or a neutral animal.
I now can’t use RequireComponent(typeof(Monster)) because the mood component would also work with component Ally or component Animal.
My main problem is with figuring out how to make components communicate properly without interlinking them so much that the entire point of using components becomes moot. Is there any written or video material on this kind of stuff?
In this example I’d make animal, ally and monster inherit from the same base class, or implement a common interface. That way you can use requires component again.
In reality monster is too high level a class for this structure, you’d go with a bunch if smaller components.