Component-based design for maximum code re-usability -- suggestions please

Hello everyone. Debated putting this in the scripting section… but I have no programming questions necessarily. I just want to pick people’s brains about maximizing Unity’s component based design paradigm.

I’m not a formally trained programmer. What I know, I’ve picked up over years of self-learning. My apologies if this question sounds “noobish”, but there are indeed people on here far far FAR more experienced than me who may be able to provide some jewels of knowledge.

I’ve come to love Object Oriented programming langauges (C# in particular, Java is also great). My problem now that I am using Unity… is that I tend to cling to my old patterns of designing class hierarchies. So far it’s worked well enough. I’m more than able to pull off a good deal of things using Unity… and quite quickly. My main concern is that my code is rarely flexible enough to easily plug into other games/projects that I am working on…without of course some odd copy/paste/modifications.

Currently I’m developing a few things for the community to use… and I want to maximize their flexibility/re-usability in a multitude of projects so that users around the Unity community actually find them useful and easy to use. My main concern at the moment is that I am horrible for creating tight coupling amongst classes. This coupling makes my code frameworks a lot less usable to someone who isn’t me (aka the designer). I just want to ask if you guys/gals have any suggestions on how to truly maximize the use of component based architecture.

My current challenge is a Cube-Based Strategy board (think Final Fantasy Tactics) framework that I am working on. I have a good deal of it working, but when I look at my code, I realize how difficult it will be for a user who wants to make a type of game like this, to use my package with their own code. I would much rather provide a solid set of simple components that allow the user to customize what they are creating, rather than providing prefabs constructed with a rather complex class hierarchy attached.

Anyways I’m rambling… what is the best way to create components that can easily be used across multiple projects? Thanks in advance! All advice is appreciated.

Well the key to object oriented coding is to be very “object oriented” ;). Class based systems are nice, but a better approach to Unity is group things by use. If you are making a health script make a single script with everything included. Always included “getters/setters” ex: health.getHealth() health.setHealth(100); etc. Also code in all important functions yourself , for this example addHealth() and subtractHealth() would be a necessity. Probably documenting each item in a separate API would do well. No one wants to scroll through all the code to see how things work. It all must be self contained and function easily and flexibly with use of its getters/setters. So the player can drag the health script onto any object and the object can now have any other object access its .subtractHealth(double value) or itself can access it as well. This allows the player to choose whether its the object with the health script to update damage or have a remote object apply damage to the object. An example would be an electric fence applying damage to the object instead of the object registering its touching an electric fence and then damaging itself. This would allow the player to program the electric fence to do all the work so each object that could possibly collide with it wouldn’t have to be separately programmed.

First, being a programmer, I take exception to part of what you say, but not all of it. I’ll explain by dissection.

Agreed. Usually your best “reusable” components will be ones that are things commonly used, like a door control trigger, a network connection script, just a very generic and common piece of a game.

This is where things start getting “icky” for my reading. First, there’s some scripts that you have to accept that you will always have to custom-code for a game, that will never be fully reusable. An “Entity” setup is one such code - in one game, you might be a spaceship with regenerating energy shields. In another game, you might be a Knight with HP, Max HP, agility, and strength.

Second, Get/Setters are a big no-no in real object-oriented programming (like the kind we game developers do). The whole point of OOP is to protect variables with functions, as well as create game pieces which are reusable.

If you are using a Get/Set with a value, you probably need it to be public, so you’re not calling a function which wastes CPU cycles.

Agreed, a good programmer is a lazy programmer, but a good programmer takes the time to design things beforehand so that the laziness comes naturally. Besides, a “TakeDamage” or “GetHealed” function for good and proper reasons (i.e. cheating in a multiplayer game, as well as flexibility issues) should not be a get/setter. You can have a basic health system that looks like:

var hp : int;
var maxhp : int;

var damageFX : GameObject;
var healingFX : GameObject;

function TakeDamage( amount : int ) : void
{
  Instantiate( damageFX, transform.position, transform.rotation );

  hp -= amount;
  if( hp < 0 ) { hp = 0; }
}

function GetHealed( amount : int ) : void
{
  Instantiate( healingFX, transform.position, transform.rotation );

  hp += amount;
  if( hp > maxhp ) { hp = maxhp; }
}

We really aren’t “setting” anything, except in the event that we need to clamp the HP variable…and that’s done inside the function, where an external source can’t see it. Best of all, it’s still easy. Fast-forwarding to your electric fence…

var damage : int = 50;

function OnTriggerEnter( who : Collider ) : void
{
  who.SendMessage( "TakeDamage", damage, SendMessageOptions.DontRequireReceiver );
}

Now, this brings up a point to good code - it should be inherently readable. If we can’t have at least a vague idea of what something is supposed to do by just taking a few minutes and reading the code straight down, that code needs to be revised. In Computer Science, like so many other disciplines, most often the simplest solution is the best.

And to take that a step further, you can have prefabs sprinkled over the place - clones of the base object. Or a special “Engineer” enemy can go around, find places it likes, build an electric fence there, then move on to another choice spot. A well-designed object - which is what you’re saying - saves a lot of time.

I completely agree with you. Your example getters/setters above are exactly what I had in mind. Perhaps my wording could have been better. You articulated it perfectly.

In this regard I was more or less thinking of using them for private functions to help keep code clean, readable and omit duplicate code. The simple health script does not need them, but I am sure there are scripts where getting and setting of variables might require some calculation or modification to other ares of the script. I am sorry, I should have been more explicit with what I meant. Also, I have made such a simple health script and it works just as yours with different function names. the setHealth() does check to make sure its not over a max health value. It seems in my haste to reply I had forgotten to be more specific. Thank you for clarifying the best practices!

Oh and before I forget. If you are writing scripts, do not forget to add comments! Comments are great for being able to quickly and easily look at any code and get a better idea just how things work. It also allows the end user to more easily edit your code knowing just how it functions so they can tailor your code to fit their needs. As stated above, there is no clear catch all case except for certain applications.

Thanks for the replies guys.

I found an interesting blog post earlier tonight that might be useful for anyone who’s looking into this topic a little deeper (as I am attempting to do now).

http://gameprogrammingpatterns.com/component.html

For very simplistic examples, I definitely see how a component can accomplish something quite easily. For instance an HP system is quite easy to pull off… you just attach a “Health” component to your gameObject character… give it a Damage(int amount) and Heal(int amount)… and then have it Broadcast a message from it’s root gameobject “Die” when 0 HP is reached. Things like this make a lot of sense… for me where it starts to get really fuzzy is when you are designing a complex Game Agent…

Take for instance a Final Fantasy Tactics character. (Sorry to rehash this game over and over, but it’s the easiest way to portray my design troubles).

If for instance you have a level where there are two opposing sides… the player’s units, and the enemy units. Some sort of “Turn Master” must control the battle, and trigger each character’s turn. I’ve currently done this by attaching a “Turn” component to the currently active game unit. At this point the unit must be rendered differently so it’s clear which unit’s turn it is… (could be another component?), it needs to display a GUI of available actions (Think Move, Act, Wait… and the Act menu bit needs a sub menu of all available abilities on the unit). The user then needs to provide input… and then the unit acts upon this. If it were only a single action it would be easy, but in my case I’d like an easy way for the user to define how many actions can be taken… for instance Move and then Act–>Attack. I’d also like to provide flexibility of the GUI. This way people who use the package can easily create custom units…the mage in my game may have a fireball under “Black Magic”, but someone else may want to easily define “Earth Magic” and have some sort of GrowGrass spell. (Terrible example, but you get the point).

I have a gut feeling a component based design is the way to go, but I want to ensure I’m designing components for maximum re-usability. I can envision how I’d code this… but I’m having trouble seeing how to provide a solid code base so that users can easily extend it for their own purposes.

Maybe I’m trying to make my code TOO reusable, and make it too easy on users who want to use my system… but I’d like to know of articles or advice on the best practices to create reusable components.

1 Like

Thanks for the link.

There are lots of books on the subject in general, but not as many good ones on game architecture. Found this one years ago, a good read on subject (and many more other things too).

There was a presentation on that topic at one of the previous Unite conferences.

http://unity3d.com/support/resources/unite-presentations/techniques-for-making-reusable-code

It essentially boiled down to keep your classes small with a clear purpose, and code for interfaces.

As far as your turn based game goes, and many other game types, that function isn’t best really implemented by attaching a ‘turn’ component to a a player. That seems sort of a kludge.

Such functionality is usually driven with a state machine inside a centralized ‘game manager’ singleton class. It knows who all the players are, has cached references to them, who’s turn it is and it’s in charge.

In terms of GUI with submenus as the like, as it’s not the usual event driven paradigm but more of an immediate mode you usually use some fashion of state machine for them as well. Someone recently pointed me towards a blog showing how to use delegates to further rid a GUI of massive if-then/switch statements.

http://xeophin.net/en/blog/2011/01/03/how-wrestle-down-guis-unity-3d

First of all, thank you for those links. The delegate GUI method is really cool, not sure why I never considered that before! As for the Unite presentation… I watched this ages ago, this is a perfect time to rewatch. Maybe I’ll understand it in a different light.

As for your suggestions… I do indeed have a “BattleMaster” at the moment which has all mobiles registered to it, and calculates their turn order and executes their turns one by one. When it decides who’s turn it is, it attaches this “Turn” component which then signals the GUI to appear and to take a Movement + an Action, or just a Wait, at which point the turn ends, and the BattleMaster is communicated this… and removes the Turn component, and adds it to the next Mobile who’s turn it now is.

I have never considered a state machine to accomplish this. That is definitely an interesting concept and I think I’ll explore that a bit as it might help demuddle my code. The only thing that makes me shy away from the state machine method is that I’d like to allow users of this package to dictate what their own “Turn” consists of… rather than play by any state machine rules I set. From what I know of state machines they are rather specific to how they are defined and often lack flexibility. Would a component based approach not allow a user to simply use a custom “Turn” component to change things to their liking? I suppose the same argument could be made for using their own Turn State machine as well…

Definitely some great things to think about here. If there’s anymore advice from anyone please do post. This is all good stuff.

Cheers!

I think I contemplated getting this one before, I should definitely look into it again. Thanks for the link :smile:

I asked a similar question on UnityAnswers:http://answers.unity3d.com/questions/24609/game-architecture-best-practices
I didn’t really come to a final conclusion but the information provided their helped guide me in the right direction.

I started out replacing all inheritance with components and using [RequireComponent(typeof(OtherClass))]. This was good in that it Unity took care of dependencies, I could just drag the ‘concrete’ class on to an object and all the required components would automatically get added. Another benefit was it allowed mixins without dealing with the dreaded diamond. The downside was communication between these components. If it were a base class I could make a member protected and access it quite easily, whereas with components I had to expose it via a public interface and use GetComponent(). Another issue is the Update order of components, you cannot rely on which order your components will get Update called, which means if one sets a property another depends on, it may not be updated prior to being used. Unity provides ‘LateUpdate’ but that is only a halfway solution because if you have a third component and you need to guarantee the execution order of all them you’re back in the same boat. Composition also makes polymorphism more difficult, I can’t have a reference to a base object and get varying behavior based on virtual function overrides.

I have since have refactored many of these classes into self contained components. For example I have a ‘Destructable’ component; it records the HP of an object, takes damage, and fires off it’s ‘destroyed’ delegate as a callback when HP equals zero. Other components ‘require destructable’, they FindComponent in Start() and assign their delegate, there is no need to store a reference to it or find it later.

I still have plenty of inheritance as well though. For example all weapons inherit from WeaponBase which manages cooldowns and other shared behaviour, then WeaponBase inherits from ItemBase which is what is stored in the inventory, and bought and sold to the vendor. Also many of the classes which do not inherit from MonoBehaviour are in some inheritance hierachy.

In OO it always best to favor composition over inheritance, and in my experience this is even more important in Unity. The component system makes composition really easy. I think that component based design requires a slightly different mind set to OO, moving more toward a ‘has a’ than ‘is a’ type relationships between objects.

It’s also worth mentioning that I found refactoring parts of components into new smaller components is really easy, I think this is good because it allow you to experiment a bit, rather than a big up front design which is required for a clean inheritance hierarchy.

I have a tiny question also… When I try to design my own classes I tend to run into the paradox that if I want to access the transform or gameobject of the object this class is attached to, I cannot because my class derives from too basic a class (Object), but if I use a class that DOES allow me to access the properties of the game object that class is attached to, then it creates an instance of the class in the Editor.

My workaround was to include a Parent member and to manually assign the gameobject to the member of the class that is already available in it’s inspector view… It seemed rather redundant but I couldn’t figure out another way. Of course the ‘DontShowInEditor’ might be an option but that would be more of a hack than anything else. What is the smallest base class that can access the gameObject but does not need to create an instance of itself? For instance, i do not need every HP and MP and SP and XP and LP of every object in my world to have a Transform…

For instance, I create a Health class that contains all it’s little members and methods and whatever else.

Now I create a PlayerStats.js file and inside that I create:

var HP : myStats;
var MP : myStats;
function something() : int
{}

Now let’s say I want to make my HP reference something(). For this, HP will need to have a reference to the PlayerStats component but if I have 50 characters in the scene and each one has 5 stats and each weapon in the game has 5 stats, that would mean my Heirarchy would be filled up with thousands of objects… How can I allow my classes to access the game object without needing an instance of my class to be created every time I say HP = new myStats(); ?

Thanks in advance

Very informative thread, thanks. I’ve really started to use delegates and events a lot to avoid the Update() unpredictablity issue.

So far I have my game actor in a single base Entity that inherits from Monobehavior. I have child classes (EntityVehicle, EntitySquad) that extend these, classic OO.

I then have my other classes/components, some of which inherit from MonoBehavior (mostly so I can watch them in the editor) and some of which don’t. These don’t have Update() on them (though they may have Awake() ), but interact with my main Entity by use of delegates and events or by having my Entity invoke my own Update-like methods on these helper components. I can do this explicitly or by using delegates. Delegates are pretty much great for this type of stuff, if occasionally a little hard to untangle.

@mrDude - I don’t understand your question exactly. Any object that is created needs to be instantiated, whether it shows up in the Editor or not. What are you trying to avoid?

Instantiation is what I am trying to avoid. I don’t really know how better to explain myself :frowning:
When I say

class myClass extends Object{}

var myObjects : myClass[];

function Start()
{
myObjects = new myClass[100];
}

I now have 100 objects I can use. All virtual, all in memory. But if I do this:

class myClass extends GameObject {}

var myObjects : myClass[];

function Start()
{
myObjects = new myClass[100];
}

Now I have 100 objects in the Hierarchy view. Now if I have 10 objects each with this script I have a 1000 items in the Hierarchy. I don’t want THAT… The question is: Which base class is the lowest base class I can extend from to be able to access the gameObject from my classes without having to create an instance of MY class in the inspector.

Wait, here is a good way for me to express myself better:
I just want my class to be a member of a component, not a gameObject of it’s own… but I still want it to be able to access the gameObject… Is that possible at all?

Everything in Unity is a gameObject that is the base class that all subclasses are part of. Lights are gameObjects, particles are gameObjects. Terrain is a special game object. At least that’s how I understand it.

In scripting you can write the script (which can act like a class) and attach it to any game object you wish to have that functionality. So if you have a health “class” script you should write the script and drag it onto the object in the hierarchy OR in the assets folder for a prefab. So if you have a generic enemy prefab, you can write the health script and attach it to the prefab objects you add to the scene/hierarchy will have health functions as they all have the health script attached. You simply write the script for whatever and attach it to the gameObject. By being attached to the gameObject the script immediately has access to all other components attached to the gameObject it is attached to.

Here is an example script I think will be helpful. This is a simple flashlight script I modified that I found on the forums. I am sorry I forget the original author right now, if you recognize it as yours please feel free to make it known.

var flashlightOn : boolean = false;
var soundOn : AudioClip;
var soundOff : AudioClip;
var onIntensity = 5.0;
var offIntensity = 0.0;

function Update () {
   //Checks if the F key is down and whether the boolean is on or off.
   if(Input.GetKeyDown(KeyCode.F)  flashlightOn == false){
   
   AudioSource.PlayClipAtPoint(soundOn, light.transform.position);
   flashlightOn = true; //If the f key is down and the boolean is false, it sets the boolean to true.
   light.intensity = onIntensity;
   
   } else {
   
   if(Input.GetKeyDown(KeyCode.F)  flashlightOn == true) {
   
   AudioSource.PlayClipAtPoint(soundOff, light.transform.position);
   flashlightOn = false;//If the f key is down and the boolean is true, it sets the boolean to false.
   light.intensity = offIntensity;
      }
   }
   
}

If you notice it references a light object in which it references that light objects intensity value.

light.intensity = offIntensity;

You can add a light to the player and add this script to the player and instantly the script finds the light attached to the player that it is attached to and can access all of its modifiable attributes.

I hope this helps out. Or maybe I misunderstood you.

EDIT: As soon as I get time, I will upload an example health script and accompanying GUI script to draw a basic health bar on screen. This will show how two classes interact on the same object. And maybe even how to reference other objects scripts as well. My University has just started up again so it may take a while before I can complete it.

MakerOfGames:
I’m afraid you do misunderstand me.

I’m afraid that will not work for my purposes. I don’t have a simple “Health” script. I have a complex Stats system that can itself be broken down into numerous classes. Using your example I would have to drop one instance of my script on the model to act as HP then another instance of my script to act as MP and so on and so forth and after I have dropped my script onto the object 8 times, I then need to create a new script that has place holders for each of those scripts and drag each one of those components onto the relevant place holders and then write all my functions in the last script to call the functions in the first 8 scripts via the stored references to each component…

Now recall that my my stats script makes use of additional classes also. If I write them as “scripts” then, for each of the 8 components I just dragged onto the object, I will also have to drop an instance of each subclass and then modify the stats class to hold references to the subclasses and drag the subclasses to the place holders in the components linked to the main object… Then I need to repeat this entire process for the subclasses of the subclasses…

Comparing an object that has 112 scripts dragged onto it and an object with a single script that looks like this:

Saying: HP.add(10) is sooooo much simpler than dragging 112 script onto an object and dragging references from each to each and trying to keep track of which belong to which. heaven forbid you get bored and make a mistake somewhere along the line…

I want to have something be available in the inspector but NOT be an entity. From what I have read, this is not possible using the Object base class. I then read that Scripts should derive from MonoBehavior, not Object, and although that gives me access to Invoke, it des not, however give me access to gameObject… So basically, it seems what I want to do is NOT possible, but perhaps someone knows of another class I can derive from that I am simply not aware of…

[example time]

class baseStats Extends Object
{
private var min : float;
private var max: float;
private var val: float;

function setMin(to:float) {}
function setMax(to:float) {}
function setValue(to:float) {}
function getValue() : float {}
}

class subClass Extends Object {

var stat : baseStats[];
// 0=base, 1=upgrade, 2=temporary boost, 3 = planned upgrade, 4 = actual value

function takeDamage(howMuch: float) { }
function Depleted() : boolean {  }
}

class MyPerfectClass Extends Object
{
var HP: subClass;
var MP : subClass;
var LP : subClass;
var Sword : subClass;
var LeftShoulderPad : subClass;
...
...
var rightToeThirdJointSecondPad: subClass;
var Level : int;

function TakeDamage()
{
...
HP.takeDamage(x);
Sword.takeDamage(x/3);
...

if (HP.Depleted())
    gameObjet.SendMessage("Die",true);
}

}

That last line of code… That is the problem…

What you ask is beyond my knowledge in scripting. But as far as I am aware, you are correct in that what you want is not possible. I would probably put all stats into a stat script. Break it up into only a few scripts. One that holds all the stat rules and modifiers. One script containing all stat variables that a player could have and methods to modify them. And lastly a class that uses both. It would call the rule script for something like levelUp() and then levelUp would modify the playerStats to hold the new values. Something like that is the only way I can think of how to do it. This way only one script runs and it can reference the rules(you can have an object dedicated to containing the rules script so its not on each object in the game) and modify the player data. Although this idea probably isn’t of much help.

btw: I will still make a basic scripting tutorial in hopes to better explain object reference and interactivity. I know I wanted a better scripting reference when I was learning so I will still write that up for new scripters.

Thanks for the attempt, mate. As it is, my entire thing is working and I can do what I want to do, the only catch is that I have to do this:

class myPerfectClass Extends Object
{
var parent : GameObject;

function TakeDamage()
{
...
HP.takeDamage(x);
Sword.takeDamage(x/3);
...

if (HP.Depleted())
    parent.SendMessage("Die",true);
}

}

and in the main Component I have to do this:

var AllStatData : myPerfectClass;

function Start()
{
AllStatData = new myPerfectClass();
AllStatData.parent = gameObject;
}

I was looking for a way to avoid that last line of code, is all… Aww well… so be it :slight_smile: Again, thanks for trying

Not sure about UnityScript, but in C# you could make a constructor that takes parent as an arg:
AllStatData = new myPerfectClass(gameObject). Doesn’t really save much though.

Hi,

I think it’s also good to realize a lot of these scripts are “Behaviors” that modify a class (GameObject… etc). With this perspective you can think composition, thinking composition a lot of the scripts start making sense. Instead of locking yourself into the class model which does suite “is a” relationships, the composition perspective represents “has a”.

The single act of dragging a “Script” onto a Scene GameObject automatically says GameObject “has a… Behavior”.

You will find that class structures work well when creating “nouns” such as components being added to the hierarchy pane or as children of a GameObject.

This was just a quick response to the original post.

Mike