OOP vs Component Based Architectural Design

Hi Guys,

I come from Unreal, hail! I’ve been with C++ and UnrealScript for 2yrs and am well used to OOP architecture.

It looks like from what I can find online Unity uses a component based design for code. It doesn’t have any code hierarchy architecture.

With that in mind… How do you design code for large professional projects, with a lot of class inter-relation without a structured hierarchy?

I can only find short tutorials on creating Unity features. Not any on professional code design.

Any ideas on best practice?

Thanks

I just found this:

…However open topic here for any suggestions on grouping generic functions component based :slight_smile:

With the component model you might have one core class that knows about the possible components. For example a player class (always present) that looks to see if there’s a jetpack class (and knows to use that instead of regular movement when jumping, for example).

Typical damage effects could be a component you temporarily add on top of an actor object. Set something on fire by applying the Fire script, which looks for a health component and ticks it down over time, then removes itself. The health component takes care of removing the object if it dies.

With AI you just make a movement component that makes it do stuff every update, instead of inheriting from some type of generic movement script. Flying, swimming, running enemies would all be different.

There’s also the game manager-based approach, which could work for some types of games. Then every object has components completely unaware of each other, and the manager accesses them as needed. Useful for more abstracted games like strategy.

1 Like

I think you may not understand precisely what OOP and Component-based design means. They are not mutually exclusive, even if sometimes they do clash.

OOP is a language paradigm: http://en.wikipedia.org/wiki/Object-oriented_programming
Component-based architecture is a “is a branch of software engineering” (whatever that means): http://en.wikipedia.org/wiki/Component-based_software_engineering

You can do Component-based architecture in OOP… And you can do Component-based architecture without OOP.

OOP is a way to build a logical hierarchy of classes, while components is a way of aggregating the different behavior of an objects. Note that component structure are not exactly “visible” in the code, while a hierarchy of classes is.

Let’s be clear that class != object. A class is the definition of what will become an object.

For example, not every object in the world has a visual, a collision, and so on. From what I remember on my time on Unreal 2.x, Unreal is not “pure” OOP in that aspect. Since Unity is using language like C#, you can build your own hierarchy of classes. Polymorphism is simply a too big feature to not have it around.

http://www.openchord.org/wordpress/2011/09/unity-and-the-component-model/ is a rather diminutive view on what could be done.

It is just one way to see it. Personally, I would go:

Component → NPC
NPC has a “Behaviour” parameters;

  • Object → NPCBehaviour → Animal Behaviour → Cat Behaviour → Kitten Behaviour
    And it also may have the parameter which handles motion and skeleton;
  • Object → Motion → Quadruped

I assume that “NPC” has enough code that is shared by all NPC, such as communication, path finding, inventory, health, and so on.
That “Kitten” is exactly the same behaviour as a “Cat”, but may only attack other kitten and never deals damage.
I also assume that all quadruped control their skeleton in a fairly similar way.

The question I would ask is, does “Young Animal Behaviour” contains enough generic code for any type of animal to warrant a reference instead of a hierarchy?

So

GameObject
    |-> Visual
    |-> Collider
    |-> NPC
         |-> Kitten Behaviour
         |-> Quadruped

When you tried to split up a behaviour into too many separated component, you get communication problem as each pieces may need to talk to each other. If I remember right, the question you should ask yourself is “Is X a part of Y, or X is Y?” Is there real benefice in splitting something in smaller part?

Just my 2 cents…

Exactly. There’s more than one way to skin a model.

Its just jargon bingo. It all winds up as Spaghetti in the end.

2 Likes

You can use both together quite nicely.

i have no idea what that means… all my c# is object orientated

Yes, C# doesn’t give you the option, everything in it is an object. However, it’s not the case of all OOP language. For example, you can code in C++ (the non-managed version) without any objects.

What many people fail to realize is, OOP is only a language paradigm, and in some case it may influence your final code design. However, it should never be a limitation. For example, I knew someone who so strongly believed in OOP in every sense of the term, that he would never use any static class and would frown on singleton, because it goes somewhat against the notion of “objects”.

A language is a collection of tools and paradigms. You can choose which one you use and when you use them. If you want to use a screw with a hammer, it’s up to you, even if I’ll think you’re a moron. When you’ll pull that screw out, you might rip out more of your code with it.

All in all, there’s thousands different ways of doing thing in code. However, some will be longer to write, and some will be harder to maintain. Some will give a quick short-term result, but will take longer to expand, while some other will take a lot longer initially, but will flow out quickly in the end.

After a while, I’ve come to notice the pitfall Unity tends to push coders towards. For example, many tends to compartmentalize their code within multiple components, making it very hard to maintain, both in data and in code. Many completely forget the existence of ScriptableObject or even object derived from System.object, which both have pros and cons versus MonoBehaviours. Or worse, some projects I have seen, the coders enforced a strong code-driven approach, to the point that doing anything new or any changes always involved coding.

However, the worst I have seen, some less experienced coder completely forget the notion of hierarchy or polymorphism. I have seen a project where every class only derived from MonoBehaviour! I can partially understand the issue. Serialization of polymorphic class in Unity is no walk in the park. It took us a while to implement a framework that would give designers complete ability to create instances of a derived class from the type of a field, from within the inspector.

Well, it does have hierarchy, it just doesn’t use it heavily.

As a general rule of thumb, “composition is better than inheritance”, and this is generally the principle that the GameObject/Component design of Unity follows. Rather than having different types of GameObjects, GameObjects can contain different combinations of Components. The Components give the GameObject its functionality, and ideally each component should do one thing and one thing only.

If you’re heavily into OOP then this is a bit hard to get your head around at first. It took me a while, but the more experience I got with it the more I liked it.

Made me laugh, cause I think often it is true.Best intentions and all…

How smart programmers write stupid code.

I disagree. It will become chaotic, only if you let it happen. It’s a constant ongoing war between order and chaos.

I think you just summed up 90% of my work, fighting between order, chaos and sanity.

Special for this issue component-based architecture assume to have a broadcast messaging, in Unity this is implemented by SendMessage() method. As result, it’s not necessarily to have a link to other components - just send broadcast message and if gameobject has a suitable component it will get it.
But if you want to be sure if recipient is exist and message will be delivered, you can use SendMessageOptions.RequireReceiver parameter of SendMessage() method, or [RequireComponent] attribute and get component by GetComponent<>() method (but I suppose it could make coupling a little stronger)

This technique allow to break links between components, and make them are totally independent. If my InputControllerComponent call SendMessage(“GoForward”) - doesn’t matter what components gameobject have - KittenBehaviour or BirdBehaviour, if it have GoForward() method it will go forward.

1 Like

I think LightStriker is quite right: the component-based approach that is heavily favored in Unity tends to lead to rather poor architecture in big games. It doesn’t have to be that way, but it often is; to make a good clean architecture, with a separation between model and view that allows for robust testing, AI, etc., requires discipline and hard work. Conversely, just throwing all your game state into the scene graph is the quick easy path.

This is exactly what I was getting at in my “Are Unity components the Dark Side?” thread.

Personally, I’ve decided to go ahead and embrace the Dark Side when working with my boys, especially on small projects. We have a big library of components now that we can just snap together in myriad ways to make a game very quickly. This gets them quick feedback and gratification, and makes the whole process fun, which is the most important thing for them right now. And, as Patico suggests, we use a broadcast system to avoid any tight coupling between the components (though we don’t use SendMessage, preferring instead a broadcast/receive system of our own design).

In my own more serious projects, though, I’m keeping a strict separation between model (game state) and view (scene graph). I write the model classes first, using test-driven development, and keep my view and controller (i.e. glue code) as thin as possible. This avoids the nightmarish spaghetti that comes when you mix state and display together in a large game. Coming from a strong OOP background, Nigey, it sounds like this approach might sit well with you too.

As this thread is about good practice for huge code bases, you can exclude SendMessage and any other string based call. There are a lot of topics you can discuss, but string based calls are just a bad idea if you want to have maintainable code. You can easily produce hard to spot errors. First, you can have a typo for the string and the same is true for the method you want to call. And good luck for the next refactoring when you want to rename a method.
If you make it solid, you find those issues at compile time already and you won’t have any issues with refactoring.

I know that MonoBehaviour was implemented like that, it still doesn’t make it a better idea. Anyone who ever made a type in something like OnCollision… or whatever method knows exactly what I mean. This could easily be avoided with a solid design.

To me, SendMessage is a hack to try to patch an horrible disease, not a cure.

“KittenBehaviour” could be a parameter of your component and it would be a far more solid approach without any string calling.

public class NPC : MonoBehaviour
{
    public NPCBehaviour behaviour; //Put the kitten behaviour derived class in there.
}

Well with all these different answers it looks like I have my work cut out for me. So all in all, it’s pretty difficult to structure massive projects in a clearly understandable segmented fashion.

Looking through the (massive) list of answers, there’s a few different views. Some people just think it is messy so why bother. A few more think there’s several methods to organise large projects clearly. Some think you just need fight through it and try to keep it organised.

What I’m taking from this so far, is that it is actually very easy to make messy spaghetti code that becomes reliant upon having a code/scene relationship. I guess the best option for a large design is to write it out on paper first (as stupid as that sounds). For me atleast, if it’s a large project I like to create a full design of the entire project and make allowances for changes in paper design and then create all the game objects in alignment with the design theory I’ve written. So atleast I have in my head the way I want the overview of it to be done. For me if I can segment everything clearly in my head then I’m able to change and modify everything cleanly. Like creating a clean workspace.

So the best way to do this is to try and make the classes by clean separate components, with or without a main attached class that recognises what components are attached to the object and work from that?

What I have found in my SHORT time in Unity (keep in mind here guys I am here to learn, I’m no master and wont pretend to be) is that it’s easy to start writing code that directly relates to what is in the scene at the time, and not what is in the project, meaning it’s all too easy to tie up unnecessarily objects by code in the scene, so it’s less clean when writing new levels with new features and more individual tasks than the less generic ones of each level.

It looks like the best way to get organised code is to either create generic classes that segmentally (a real word lol?) make up the gameobjects you want. Then create prefabs with all the code attached, mix and matching the different classes each one needs, and try to make them as generic as possible, while needing to subclass more specific features of the generic ones. Or perhaps even a controller class that attaches different components runtime instantiated gameobjects?

Keep in mind this theory is very different to what I’m used to.

Thanks for the many responses by the way guys. It’s something that since I’ve started Unity, is something that is the most immediate thing to know (imo), but something that I’ve never seen mentioned comprehensively in any tutorials.

Teach me master. :smile: