Managing game scripts - advice needed.

Hi guys,

I’m wondering what folks opinions are on managing the various game scripts they have. How you reference variables or functions between scripts.

In my game, I’ve got multiple scripts, each handling a different aspect of the game (one for save/load, one for actor handling, one for conversation handling, one for navmesh/pathfinding, etc.).

To communicate between these scripts, I’ve got a “god” gameObject with one of each of these scripts attached and a “god” script, which has static variables pointing to each of the scripts and a static variable pointing to itself.

This means I can get variables or call functions from these other scripts via;
god.ah.whatever (); (for actor handler)
god.path.findPath ( to, from ); (for pathfinding)
and such…

I’ve also only got an Update() and OnGUI() function in the god script (and none of the others) which calls all of the other Update()-like and OnGUI()-like functions in these other scripts in the order I want them called.

Mostly I’m just unsure whether this is a sensible way to handle this stuff - I can see it getting a bit unruly.

What methods for handling these sort of things do you use or recommend?

Add to the mix above static non-monobehaviour scripts that work from the project tab and it’s pretty close to my method. It all comes down to what works for you.

This is pretty easy. Diviner is right but has not given you an example which is kinda confusing if you have never done it before.

So lets say we have a Core.js:

var playerHealth = 0;
var playerAmmo = 0; // So on...

Then you have the Player.js:

var playerHealth = 100;
var playerAmmo =  20; // It probably best to name then localAmmo and localHealth so you dont get mixed up.

So now we got both of them set-up. Let’s say the core leeches the information and then saves it somewhere like in playerPrefs.

To do this we will have to edit the Player.js and change it to this:

static var playerHealth = 100;
static var playerAmmo = 20;

For now we don’t need a function in Player.js because all its doing is keeping this information. You can add the functions to it. So stuff like player statuses and stuff… (Check below for my PlayerStatus.js script)

Now in the Core.js we add this:

//Below the variables

function Start()
{
   playerHealth = Player.playerHealth;
   playerAmmo = Player.playerAmmo; // See the "Player." this is referring to the Player.js script.
}

Now on start up you should be able to see that the Core.js script has inherited the values once your in-game. Now this will only work once because its in the Start() function. But this can get quite laggy if you put this in the Update() function. What I suggest you do is this:

var updateTimer = 1.0;

function Start()
{
    InvokeRepeating("updateInformation", 0, updateTimer);
}

function updateInformation()
{
   playerHealth = Player.playerHealth;
   playerAmmo = Player.playerAmmo; 
}

So now every 1 second the function updateInformation is called and we get a value update just like we would in the Start() function. This is very effective and you should bring the time down to 0.5 seconds for a smooth update. Usually this function would get called every 0.0333 seconds or frame. So we can how much longer it takes to update this information and this allows a smooth running game if you are to add more functions.

Hmm, that sounds like a pretty dodgy implementation to me as the values, which represent the same thing, are kept in two different locations and only synced periodically.

Surely it’d be easier (and more foolproof) just to link directly to the static var and have anything that alters it directly alter the static var value?

i.e. Core.js with

static var playerHealth : int = 100;
static var playerAmmo : int = 20;

and Player.js with (as a very rough example)

function takeDamage ( amount : int ) {
	Core.playerHealth -= amount;
}
function shoot () {
	Core.playerAmmo -= 1;
}

Agreed that that seems like a pretty obtuse approach. I see no benefit there, just an unnecessary extra step.

Sure, that would work but if you read it write, I’m optimizing it. You don’t need to know this values every frame thus wasting Processing speed. In your example there you are not calling the function at any point? I promise you that the stuff I write for you is fail proof or I would not waste my time writing such a huge example :slight_smile:

Where exactly is he accessing those values every frame?

I’m not syncing values every update. I’m not sure where in any of the stuff I’ve posted you’ve got the idea that I am.

They just sit there - in one static var each - and are changed/accessed as required by whatever script wants them by directly referencing the static var.

I simply don’t see the point of keeping the values in two places, especially if they represent the same thing but are not always synced.

The question I asked is how do you handle references to scripts that interact with each other. Static self-referencing var in each script or one master controller script or [other options here], etc.

I think your question is an excellent one. Basically…when you have many scripts or objects that all need to communicate with each other (or maybe one to many), how do you design this?
So, maybe it’s like you said in your first post.
You have a player, with its own script.
You have a pathfinding script, with its own script. It needs to know about all players/npcs in the game, buildings, whatever.
You have a save game script, which needs to know about player data and such.

What is a -good- way to design this, without creating a maintenance or performance nightmare?

With the pathfinding script, I would think it would need to know about all of your npcs, in order to control them. So effectively, each npcs should TELL the path finder about its existence.

So your pathfinder would be a single script that controls all npcs that it knows about. You could do this by creating an empty gameobject in your hierarchy, and add the path finding script as a component. Then have a reference in your npc scripts to that gameobject or the pathfinder script. When they start(), they could tell the pathfinder about their existence.
Couple of ways you could do this, and again, this approach is assuming the pathfinder just needs to know about your npcs, and that they don’t control much.

Or, you could just use the static class/singleton approach. There are some gotchas with using static classes…but I believe if you mostly use them as utility classes (like Mathf). If you wanted to have multiple pathfinding scripts, like a Cowardly AI or a MeleeAI or a RangedAI behaviors, you’d have to really think this through. But if you only needed one pathfinding script, EVER, yeah why not? But this thread is about communication, not as much about singleton/design patterns :slight_smile:

Basically, my approach would be to separate things into two groups:

  1. Controllers or Systems - Pathfinding, game saver, menu system, etc.
  2. Things that are controlled (entities)

Npcs and players are entities. They are controlled by the human on the end, or the pathfinding/ai controller. They also have data that is saved. Health, position, that sort of thing.

The controllers need to know about the entities. The entities don’t -really- need to know about the controllers, not really. All they need to do is when they run Start(), they need to tell the controllers…hey, here is a reference to me. From now on, you know about me. GameSaver, anytime you are told to save the game, you know me, and all my buddies, and the npcs, whatever, save our data. Do you thing, after I exit start() and tell you that I exist, I don’t care anymore. I’ve got my hands full responding to player keypresses and jumping around. So in the npc script Start() method, it might do this: ScriptController.AddNpc(this);

That way, you keep each thing only responsible for a very targetted function. Other than letting the controllers know that they exist, npcs and the player don’t have to worry about saving games, or pathfinding. It just happens, all they have to do is make sure that when they start, they tell the controllers a reference to them. The player should only be worried about player stuff, not all the other crap that happens in a game.

I hope this is helpful…and maybe someone else can point out some other suggestions, or flaws in my thought process. I’m sorta new at the game dev thing, but I do have good business programming experience, so take it for what it’s worth.

(As far as a singleton vs just giving everything a reference to other script components…I don’t know that I have a hard and fast rule (yet). If I have a class that like Mathf, and I know I won’t ever have more than one for math functions, yeah…make it a singleton or a static class. If it’s something I want to see details about in the inspector, I’d probably just create a gameobject in the hierarchy and attach the script to that gameobject, and drag to variable references in my prefabs.)

Again, I think you have a great question, I’d love input from others on this subject. I would love to see different approaches given a name, with some basic examples and discussions on why an approach is good, pros and cons, etc.

Anyone want to start an article on Unity Game Design Patterns? :slight_smile:

I flip between a “global God object maintaining static references to everything” and “yeah, you guys go figure out what you need.” I think after five full project cycles with Unity (now on six and seven) I have got the team to settle on the “statics where it makes sense everybody else look for the FindObjectByTag in the Awake/Start functions” balance. Sometimes I’ll catch someone making everything they can see a Singleton and everything referencing everything else through a bunch of “Instance” variables at which point they get playfully slapped. :slight_smile:

Also, for quick prototypes, nothing fancy or optimal. For big projects, more central controllers tracking instances of stuff.

It’s a great question, and there is no definitive “best answer” just many heuristics you can use to see if what you are cooking tastes like how you expected it to.

I have an eBook I am creating called “12 Hot Tips For Unity That Only the Pros Use” which could easily be expanded to “13 Hot Tips” :slight_smile: Or a collaborative article for Game Developer Magazine/Develop. I’m up for it. Anybody else? We could whip it out by end of January so it makes the April or May issue.

Thanks for your insights guys, especially your big post jc :slight_smile:

It’s good to know I’m not too far off the beaten track.

The stuff I’m working on is probably way below the complexity of the things you’re on about, but I don’t really want to start developing bad habits.

@Farfarer you’re more than welcome, hopefully my thoughts on this issue are useful and correct :slight_smile:

@Justin, some tips on overall game project organisation and design with Unity would be a huge service to the community. If nothing else, some explanations on different approachs, “Why would I use this approach?”, “Why would I not use this approach?”, and pros and cons would be awesome. I’m talking about doing things like FindGameObject vs using a static class vs a singleton vs dragging scripts to variables in the inspector.

I think the best way to show these would be in actual projects, which could be the tricky part. It means someone having a project where they can demonstrate the usefulness of these approaches. But maybe simple projects could be created to do just that.

I can honestly say…only fairly recently have I begun to really see the power of Unity’s component based approach, and how much it can simplify overall game design. Not just with the built in Unity components, but my own as well, and making them all work together.

please dont do this

this is how i work also. Going from oop to using components had me a lil confused at first, since opp is how i made games for YEARS. now, I use a singleton where its needed, a “main” game object/script that has access to other things here, and some inheritances there, and whatever else that i can do to make the code readable, easier to use, and easy to debug.

its about using the proper tool for the problem…and not one tool will work for every job.

Quite so. Make it readable. Make it easy for someone else to follow the threads of what you are doing and what happens.

SendMessage vs event delegates is another area of contention.
A manager that tracks object instances for a particular object type or just spawning an object with a particular tag and let Unity worry about it.
Cache a component reference or just get it when you need it.
FindObjectByName vs FindObjectByTag.
Does this need to be a behaviour or is it a class? (Same sort of question as when you ask “is this a struct or is this a class?”)
Composition vs Aggregation. Is-a vs has-a.
How small is too small for a behaviour? Should this single behaviour perform two related functions or should it be two related behaviours that pass messages?
Is this a prefab or a game object (answered by number of instances and lifetime and life cycle of object).

So I guess I should read up on what SendMessage/event delegates, methods/behaviours are and the difference between them.

I use delegate events for pretty much all cross-system messaging, unless it’s something performance critical then I allow myself to reference things directly by exposing public fields but doing so pretty much seals that code’s fate, you’ll never ever use it again outside of that project.

Everything is so much easier to re-use if it’s loosely coupled. You can take a player controller from one game and drop it in another and it’ll not toss out millions of errors. You just need to make stuff listen to the events it’s sending out or adjust some event broadcasters so it’s getting the right info to work and you’re done, even porting things from one type of event system to another is fairly trivial. Trying to do that form a past game/prototype/co-workers-home-project that has a heap of hard coded references to global statics is my idea of a nightmare. It’s not just outgoing static references you need to fix, there’s probably heaps of other systems directly feeding info that too. Yucky.

Also, have a look here, it’s a bit outdated now but the underlying principals are sound:

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

I’ve been reading up on this some more - googling the technical terms - and I think the method I’m using is mostly fine for the project I’m working on. Turns out I’m already using a lot of them, just not knowing what they’re called :stuck_out_tongue:

Reading some more, it seems that a good way I could improve it (especially for re-useability) is to have a bit more work go into class interfacing functions. So rather than direct references to specific values within my singleton classes, write class-specific get/set value functions so I can easily alter the data structures that go in and out of them, depending on what the project needs, rather than the scripts relying on the other classes internal structure being just so.

Anyway, thanks for the nods in various directions. It’s stuff I’ll keep in mind in future.

I’ve recently started using the singleton pattern to connect my various managers. I’m now in love with the design pattern so here’s an example, in its simplest JS form, for readability:

//GameManager.js
public [B]static[/B] var Instance:GameManager = null

function Awake()
{
    Instance = (Instance == null) ? this : Instance ;
}

public function DoStuff()
{
    //dostuff;
}

//SomeScript.js
GameManager.Instance.DoStuff();

In the example, the first GameManager to be Awake() will set himself up as the Instance variable. From there, any script can access the static variable, hence the GameManager itself. It allows direct communications between instance components as if the whole class was static. Lovely!

For more info, the singleton pattern should be detailed in OOP documents. I believe there’s even an example on UnifyCommunity.