If you are like me, you like your code documented. At least the important parts. Nothing spoils the day as browsing through hundreds of lines of code in effort to remember what was the original idea behind all that mess. Documentation comments help other people to read your code, ease the maintenance, and, if you do it right, even a decent API reference can be generated from them. So, the time has come to give some shape to my random in-code remarks.
Since I intended to use UnityScript and C#, I wondered what documentation generators (à la javadoc) could be employed. Picking the right choice would allow me to use the correct syntax from the start. I've found [1] that Doxygen is a great option for C#. It supports the standard XML-like syntax as well as its own – shorter and better readable in my opinion –, and it's been here for a while (so it's a really mature tool). For UnityScript, the options are not that great, although the YUIDoc is a solid solution that gets the job done.
Wednesday, 7 August 2013
Friday, 19 July 2013
Handling Errors
What do you think will happen when you throw an exception anywhere in a MonoBehaviour's callback (e.g. Awake(), Start(), Update(), etc.) and never catch it? Well, nothing much. Your callback will return, so the code following after the exception's origin won't get executed, a message will be printed to the log, and that's it. Your application will keep running, all your MonoBehaviours will keep running, and all of your callbacks, including the one that caused the error, will be called again as normal.
If you are like me and prefer to address serious errors in a timely fashion instead of ignoring them, you'll be soon wondering how to change this strange behaviour and stop the execution of your program on a non-recoverable error. After some research, I've found no standard solution, only three workarounds:
Also, you couldn't force 3rd party scripts to use it anyway. The only sound solution seems to be the #3 (see [1] for more details).
What if you wanted to abort?
Considering the
Notice the
If you are like me and prefer to address serious errors in a timely fashion instead of ignoring them, you'll be soon wondering how to change this strange behaviour and stop the execution of your program on a non-recoverable error. After some research, I've found no standard solution, only three workarounds:
- You can wrap every MonoBehaviour callback in a try-catch block and abort on catch.
- You can forgo the standard throwing mechanism altogether and call your own routine, something like
ThrowException(new Exception())
, which will terminate your application. - You can attach a listener to the log and react if an exception is logged. It will work even if the Player log is turned off in Player settings.
class ErrorHandler extends MonoBehaviour
{
static function ThrowException(_exception: Exception)
{
if (exception == null) {
exception = _exception;
}
}
static function HasExceptionHappened(): boolean
{
return (exception != null);
}
static private var exception: Exception;
function Update()
{
if (exception != null) {
Debug.LogException(exception);
exception = null;
Application.Quit();
}
}
}
DoSomething();
if (ErrorHandler.HasExceptionHappened()) return;
DoSomethingElse();
if (ErrorHandler.HasExceptionHappened()) return;
Also, you couldn't force 3rd party scripts to use it anyway. The only sound solution seems to be the #3 (see [1] for more details).
What if you wanted to abort?
Application.Quit()
is great for exiting under normal conditions, but how do you indicate to the outside world that your application didn't finish peacefully? System.Environment.Exit()
doesn't work, neither do System.Environment.ExitCode
, System.Diagnostics.Debug
or System.Diagnostics.Trace
methods. The best bet would be to store the return value into a file or a system registry, where it could be acted upon by an error reporter or whatever running in parallel. Considering the
System.Diagnostics.Debug
and System.Diagnostics.Trace
don't work, asserts are also not available. And the System.Diagnostics.Contracts.Contract.Assert()
is too new to be supported. It's easy to implement your own basic asserts though:
[Conditional("DEBUG")]
static public void Assert(bool _condition, string _message = "")
{
if (! _condition) {
Debug.LogError("Assertion failed: " + _message);
Application.Quit();
}
}
Notice the
“DEBUG”
constant. It is not set by default, and in Unity you cannot use #define
to make pre-processor defines. They are simply ignored. However, you can specify them in “Edit → Project Settings → Player” under “Scripting Define Symbols” for each platform. It is a little clumsy to write and delete them by hand, but the process could be possibly automated by a script (see PlayerSettings.SetScriptingDefineSymbolsForGroup).Friday, 5 July 2013
Fun Fact: Unboxing in UnityScript
Let's write a code snippet in UnityScript that stores integers and strings in an associative array:
Retrieving the int value from the container emits a warning: “BCW0028: WARNING: Implicit downcast from 'Object' to 'int'.” But, since we want to maintain a clean code, how do we downcast explicitly?
This widely spread construct –
We turn to parsing text. Yes, seriously, the advice you'll get from every corner of the Unity community[1] and the only one that seems to work flawlessly so far is to use
It's great we don't have to send it to a Unity server and wait until they parse it for us. Thank you, guys.
At the end of the day, it's a tough decision: Do we live with a log polluted with warnings, or do we parse text back and forth? Do you know of a better option?
By the way, C# has no issues with unboxing. This snippet works as expected:
var container = new Hashtable();
container.Add("property1", 5);
container.Add("property2", "text");
var num: int = container["property1"];
print("num=" + num);
Retrieving the int value from the container emits a warning: “BCW0028: WARNING: Implicit downcast from 'Object' to 'int'.” But, since we want to maintain a clean code, how do we downcast explicitly?
This widely spread construct –
var num: int = (int) container["property1"]
– doesn't work. The operator as
doesn't help neither; it only works for reference types. What do we do? We turn to parsing text. Yes, seriously, the advice you'll get from every corner of the Unity community[1] and the only one that seems to work flawlessly so far is to use
parseInt()
. That means the value is printed to a string, then parsed back basically to the same value, but assigned a different type. All of this is going on in this short line of code: var num: int = parseInt(container[
"property1"
].ToString());
It's great we don't have to send it to a Unity server and wait until they parse it for us. Thank you, guys.
At the end of the day, it's a tough decision: Do we live with a log polluted with warnings, or do we parse text back and forth? Do you know of a better option?
By the way, C# has no issues with unboxing. This snippet works as expected:
var container = new Hashtable();
container.Add("property1", 5);
container.Add("property2", "text");
int num = (int) container["property1"];
Debug.Log("num=" + num);
Tuesday, 2 July 2013
To Singleton or Not To Singleton?
Singleton is a design pattern that ensures there's only one instance of a class at a time. For example, there should be one GameController; it would make no sense to have more of them. The SaveManager and GUI screens would be singletons. In Unity, the general purpose and manager objects will often stand alone and be accessed by many other objects. Does it benefit us to actually make them follow the pattern, or is it enough to simply remember not to create more of them?
Using singletons brings two distinct advantages. One of them is ease of access. Normally, we would have to call the GameController like this:
If it were a singleton, the task would be much easier:
Hence it's more convenient to use and the object is more performance effective to retrieve.
The other benefit is a safety guard. Imagine you have a pause menu script attached to a camera. Later, you want to move it to another object, so you attach it again to that other object, but forget to remove it from the camera. Now you have it twice in the scene, giving you a not that obvious bug – two screens overlapping each other. Singleton allows only one instance, so it would have detected such a mistake immediately, negated its effects and emitted a warning.
A basic (explicitly initialised) singleton implemented in UnityScript would look like this:
As you can see, there's a certain amount of boilerplate code involved. Unless you're a typing monkey, you would soon start to wonder how to separate the pattern and use it universally. In UnityScript, you'd have to employ a hash table to store the instances of children:
Huh, look at the end-usage – really ugly code. Unfortunately, it's a real pain to have to recast constantly. But there's a better solution... Generics! Switching to C# allows us to write the following version of an explicitly initialised singleton:
If we don't need a special initialisation of the child, it could be even simpler. Providing the child has a public parameterless constructor, we could instantiate it lazily, when it's accessed for the first time:
It is all nice and well, but in Unity the MonoBehaviour is our boss. We no longer instantiate objects, so we need to adapt. There's basically no way to prevent creation of several singleton objects. The best we can do is to disable other instances of the same script. The words put into code:
Alas, you would run into a wall if you wanted to extend the MonoChild for some reason. First, you'd have to cast whenever you retrieved the instance, because it's already set to the MonoChild type. Second, you could use only the MonoChild or one of its children, because the singleton instance is inherited by all the descendants and it's enforced to be unique given the same base type (i.e. the MonoChild). This can be worked around by separating the members you want to extend and the implementation of the singleton, utilizing nested classes. We will call the singleton MonoBehaviour a Wrapper and the extendible logic a Payload. Their relationship may be confusing at first, but it's enough to realise that you can derive from a Payload at will, whilst a Wrapper will only envelope the scripts you'll intend to use in the scene and will not be extended further. The following dry example demonstrates the approach:
Here, MonoBaseChild1 and MonoBaseChild2 are actually two separate objects, which logically derive from the MonoBase, are both singletons, and can coexist at the same time.
Of course, sometimes you can end up in a situation when the generic programming is simply not an option. A compiler for a mobile platform may not support certain generic constructs, or you may be limited to the UnityScript. In such cases, beside “baking” the singleton pattern introduced at the beginning, you can also turn to a static class initialised by a MonoBehaviour, or rather a MonoBehaviour that behaves like a static class:
It does not provide an instance (though it may be looked up if need be), but in most cases it's not needed anyway. The only major drawback is invalid accessing of static members before they're initialised or after they're deinitialised. You can either check in each method whether the initialisation has run, which is annoying, or tweak the script's execution order and hope you were careful enough not to call anything too early, which is unsafe. I think the most viable option is to put all data fields in a private nested class and then create a private static instance of it in Awake(). This way a premature access will trigger a NullReferenceException, which is better than nothing. Variables exposed to the editor can then be copied from the outer shell to the internal state when it's created. Like this:
All in all, this should be a provisional solution when no better options are available.
Disclosure: I intentionally omitted releasing static references to make the examples more compact. A final implementation should take care to free all the references as soon as they are not needed, because they block the memory occupied by singleton objects even after the objects are seemingly released. (Well, at least in some cases.)
Using singletons brings two distinct advantages. One of them is ease of access. Normally, we would have to call the GameController like this:
GameObject.Find("GameController").GetComponent.<GameController>().DoSomething();
If it were a singleton, the task would be much easier:
GameController.GetInstance().DoSomething();
Hence it's more convenient to use and the object is more performance effective to retrieve.
The other benefit is a safety guard. Imagine you have a pause menu script attached to a camera. Later, you want to move it to another object, so you attach it again to that other object, but forget to remove it from the camera. Now you have it twice in the scene, giving you a not that obvious bug – two screens overlapping each other. Singleton allows only one instance, so it would have detected such a mistake immediately, negated its effects and emitted a warning.
A basic (explicitly initialised) singleton implemented in UnityScript would look like this:
class SingletonPattern
{
static function GetInstance(): SingletonPattern
{
if (! instance) {
throw new System.Exception("No instance created!");
}
else {
return instance;
}
}
static private var instance: SingletonPattern;
function SingletonPattern()
{
if (instance) {
throw new System.Exception("Only one instance allowed!");
}
else {
instance = this;
}
}
function DoSomething() {}
}
new SingletonPattern();
SingletonPattern.GetInstance().DoSomething();
As you can see, there's a certain amount of boilerplate code involved. Unless you're a typing monkey, you would soon start to wonder how to separate the pattern and use it universally. In UnityScript, you'd have to employ a hash table to store the instances of children:
public class Singleton
{
static public function GetInstance(_type: System.Type): Object
{
var instance = instances[_type];
if (! instance) {
throw new System.Exception("No instance created!");
}
else {
return instance;
}
}
static protected function SetInstance(_instance: Singleton)
{
if (instances.ContainsKey(_instance.GetType())) {
throw new System.Exception("Only one instance of the same type allowed!");
}
else {
instances.Add(_instance.GetType(), _instance);
}
}
static private var instances: Hashtable = new Hashtable();
protected function Singleton()
{
// the instance could be set directly when the object is created,
// but it would limit child's options
// SetInstance(this);
}
}
class SingletonChild extends Singleton
{
function SingletonChild()
{
SetInstance(this);
}
function DoSomething() {}
}
new SingletonChild();
(SingletonChild.GetInstance(SingletonChild) as SingletonChild).DoSomething();
Huh, look at the end-usage – really ugly code. Unfortunately, it's a real pain to have to recast constantly. But there's a better solution... Generics! Switching to C# allows us to write the following version of an explicitly initialised singleton:
abstract public class Singleton<T> where T: Singleton<T>
{
static public T Instance
{
get {
if (instance == null) {
throw new System.Exception("No instance created!");
}
return instance;
}
protected set {
if (instance != null) {
throw new System.Exception("Only one instance allowed!");
}
instance = value;
}
}
static private T instance;
protected Singleton()
{
// the instance could be set directly when the object is created,
// but it would limit child's options
// Instance = (T) this;
}
}
class SingletonChild : Singleton<SingletonChild>
{
public SingletonChild()
{
Instance = this;
}
public void DoSomething() {}
}
new SingletonChild();
SingletonChild.Instance.DoSomething();
If we don't need a special initialisation of the child, it could be even simpler. Providing the child has a public parameterless constructor, we could instantiate it lazily, when it's accessed for the first time:
public class LazySingleton<T> where T: LazySingleton<T>, new()
{
static public T Instance
{
get {
if (instance == null) {
instance = new T();
}
return instance;
}
private set {}
}
static private T instance;
protected LazySingleton()
{
if (instance != null) {
throw new System.Exception("Only one instance allowed!");
}
}
}
class LazyChild : LazySingleton<LazyChild>
{
public LazyChild() {}
public void DoSomething() {}
}
LazyChild.Instance.DoSomething();
It is all nice and well, but in Unity the MonoBehaviour is our boss. We no longer instantiate objects, so we need to adapt. There's basically no way to prevent creation of several singleton objects. The best we can do is to disable other instances of the same script. The words put into code:
abstract public class MonoSingleton<T> : MonoBehaviour where T: MonoSingleton<T>
{
static public T Instance
{
get {
if (instance == null) {
throw new System.Exception("No instance created!");
}
else {
return instance;
}
}
private set {
if (instance != null) {
throw new System.Exception("An instance already exists!");
}
else {
instance = value;
}
}
}
static private T instance;
protected virtual void Awake ()
{
try {
Instance = (T) this;
}
catch (System.Exception) {
Debug.LogError("Attempted to create another instance of '" + typeof(T).FullName + "'!");
Destroy(this);
}
}
}
class MonoChild : MonoSingleton<MonoChild>
{
public void DoSomething() {}
protected override void Awake ()
{
base.Awake();
}
}
MonoChild.Instance.DoSomething();
Alas, you would run into a wall if you wanted to extend the MonoChild for some reason. First, you'd have to cast whenever you retrieved the instance, because it's already set to the MonoChild type. Second, you could use only the MonoChild or one of its children, because the singleton instance is inherited by all the descendants and it's enforced to be unique given the same base type (i.e. the MonoChild). This can be worked around by separating the members you want to extend and the implementation of the singleton, utilizing nested classes. We will call the singleton MonoBehaviour a Wrapper and the extendible logic a Payload. Their relationship may be confusing at first, but it's enough to realise that you can derive from a Payload at will, whilst a Wrapper will only envelope the scripts you'll intend to use in the scene and will not be extended further. The following dry example demonstrates the approach:
abstract public class MonoSingletonWrapper<T> : MonoBehaviour where T: MonoSingletonPayload, new()
{
public abstract class MonoSingletonPayload
{}
static public T Instance
{
get {
if (instance == null) {
throw new System.Exception("No instance created!");
}
else {
return instance;
}
}
private set {
instance = value;
}
}
static private T instance;
protected virtual void Awake ()
{
if (instance != null) {
Debug.LogError("Attempted to create another instance of '" + GetType().FullName + "'!");
Destroy(this);
}
else {
Instance = new T();
}
}
}
abstract class MonoBase<T> : MonoSingletonWrapper<T>.MonoSingletonPayload where T: MonoBase<T>, new()
{
public MonoBase() {}
public abstract void DoSomething();
}
sealed class MonoBaseChild1 : MonoSingletonWrapper<MonoBaseChild1.MonoChild1Payload>
{
public class MonoChild1Payload : MonoBase<MonoChild1Payload>
{
public MonoChild1Payload() {}
public override void DoSomething() {}
}
}
sealed class MonoBaseChild2 : MonoSingletonWrapper<MonoBaseChild2.MonoChild2Payload>
{
public class MonoChild2Payload : MonoBase<MonoChild2Payload>
{
public MonoChild2Payload() {}
public override void DoSomething() {}
}
}
MonoBaseChild1.Instance.DoSomething();
MonoBaseChild2.Instance.DoSomething();
Here, MonoBaseChild1 and MonoBaseChild2 are actually two separate objects, which logically derive from the MonoBase, are both singletons, and can coexist at the same time.
Of course, sometimes you can end up in a situation when the generic programming is simply not an option. A compiler for a mobile platform may not support certain generic constructs, or you may be limited to the UnityScript. In such cases, beside “baking” the singleton pattern introduced at the beginning, you can also turn to a static class initialised by a MonoBehaviour, or rather a MonoBehaviour that behaves like a static class:
public class StaticMono extends MonoBehaviour
{
function Awake()
{
var instances = FindObjectsOfType(GetType());
if (instances && instances.Length > 1) {
// removing the component here would remove all instances of the script,
// which could lead to a potential instability
throw new System.Exception("Created several instances of '" + GetType().FullName + "'!");
}
}
}
class StaticMonoChild extends StaticMono
{
static function DoSomething()
{
something += 5;
print(exposedVarCopy);
}
static private var something: int;
static private var exposedVarCopy: int;
var exposedVar: int;
function Awake()
{
super.Awake();
something = 10;
exposedVarCopy = exposedVar;
}
}
// if it's called before StaticMonoChild.Awake(), the behaviour is undefined
StaticMonoChild.DoSomething();
It does not provide an instance (though it may be looked up if need be), but in most cases it's not needed anyway. The only major drawback is invalid accessing of static members before they're initialised or after they're deinitialised. You can either check in each method whether the initialisation has run, which is annoying, or tweak the script's execution order and hope you were careful enough not to call anything too early, which is unsafe. I think the most viable option is to put all data fields in a private nested class and then create a private static instance of it in Awake(). This way a premature access will trigger a NullReferenceException, which is better than nothing. Variables exposed to the editor can then be copied from the outer shell to the internal state when it's created. Like this:
class StaticMonoSafer extends StaticMono
{
private class InnerState
{
function InnerState(_outer: StaticMonoSafer)
{
something = 10;
exposedVarCopy = _outer.exposedVar;
}
var something: int;
var exposedVarCopy: int;
}
static function DoSomething()
{
state.something += 5;
print(state.exposedVarCopy);
}
static private var state: InnerState;
var exposedVar: int;
function Awake()
{
super.Awake();
state = new InnerState(this);
}
}
// if it's called before StaticMonoSafer.Awake(), NullReferenceException is thrown
StaticMonoSafer.DoSomething();
All in all, this should be a provisional solution when no better options are available.
Disclosure: I intentionally omitted releasing static references to make the examples more compact. A final implementation should take care to free all the references as soon as they are not needed, because they block the memory occupied by singleton objects even after the objects are seemingly released. (Well, at least in some cases.)
Saturday, 29 June 2013
Default Anatomy of a Unity Application
So, you started a new project in Unity. You added your first game objects and scripted their behaviour. Do you think that's it? Your game is ready to run? Well then, hold your horses. There are several core objects you would find in almost every application. And the chances are you will most likely need all of them.
When you create a scene, there's already a camera object – the Main Camera. Without it, you would only see a black screen.
Then there's the GameController – a class that you will write yourself, although it may be named differently. Sooner or later you'll need to keep a global state somewhere – enemies killed, matches won, levels explored... That would be your GameController. Sure, it may be composed of different parts – Stats, Preferences, Progress, Inventory, etc. – but it's a good practice to keep them under one parent object (or implement them as scripts attached to that parent GameObject in some cases). It becomes increasingly useful if you add another scene. The GameController doesn't die with the scene; it exists for the whole duration of the application (i.e. it should be marked with DontDestroyOnLoad()). That also means that the GameObjects attached to it are preserved as well. So if you want to keep anything around at all times, you can (and should) simply attach it to the GameController or any of its children. It might not be possible in rare cases (when the transformation of a persistent object depends on an object that will be destroyed), but otherwise it is a sound solution.
There's a problem, however, with the not destroyable objects in general. You can't just put them into a scene as regular. If you had multiple scenes and switched between them, the persistent objects would duplicate. You could put them into the first scene, which would be loaded on start-up and then never crossed again, and it would work in the final game. During development though, you would often run scenes at random and they would be missing the crucial information that's supposed to always be there. The only solution is to introduce a helper object that will always die with the scene. Upon initialisation it will check if the GameController is present, and if not, it will create it (from a prefab). We can call this watcher GameLauncher and put the global logic that doesn't apply outside the scene under it.
One of such global objects could be GUI. UnityGUI is entirely scripted. That means we can create a number of scripts, one script for each screen, for example, and put them virtually anywhere. But where does it make the most sense? Since we can have many screens, it's certainly more practical to dedicate a separate GameObject for them than to “hide” them in random existing objects. I've seen people attach the scripts to the main camera. It's one possibility. Still, there could be multiple cameras in the scene, they could be nested in other objects – it could become cumbersome to locate a script. Another option is to leave the GUI object freely in the scene. Although, if there were many independent game objects already, it would only add to the clutter. Also, there could be screens available through the whole application, such as pause menu, and the screens specific to a scene, such as HUD. We could signify the difference by attaching one GUI object to the GameController and another to the GameLauncher, which are the pillars that will not move.
When everything else is in place, you'll need to save and load your game state. So there would be a SaveManager, which Unity doesn't provide and which you'll have to implement yourself, too. This is a huge topic and I plan to write more on it later.
When you create a scene, there's already a camera object – the Main Camera. Without it, you would only see a black screen.
Then there's the GameController – a class that you will write yourself, although it may be named differently. Sooner or later you'll need to keep a global state somewhere – enemies killed, matches won, levels explored... That would be your GameController. Sure, it may be composed of different parts – Stats, Preferences, Progress, Inventory, etc. – but it's a good practice to keep them under one parent object (or implement them as scripts attached to that parent GameObject in some cases). It becomes increasingly useful if you add another scene. The GameController doesn't die with the scene; it exists for the whole duration of the application (i.e. it should be marked with DontDestroyOnLoad()). That also means that the GameObjects attached to it are preserved as well. So if you want to keep anything around at all times, you can (and should) simply attach it to the GameController or any of its children. It might not be possible in rare cases (when the transformation of a persistent object depends on an object that will be destroyed), but otherwise it is a sound solution.
There's a problem, however, with the not destroyable objects in general. You can't just put them into a scene as regular. If you had multiple scenes and switched between them, the persistent objects would duplicate. You could put them into the first scene, which would be loaded on start-up and then never crossed again, and it would work in the final game. During development though, you would often run scenes at random and they would be missing the crucial information that's supposed to always be there. The only solution is to introduce a helper object that will always die with the scene. Upon initialisation it will check if the GameController is present, and if not, it will create it (from a prefab). We can call this watcher GameLauncher and put the global logic that doesn't apply outside the scene under it.
One of such global objects could be GUI. UnityGUI is entirely scripted. That means we can create a number of scripts, one script for each screen, for example, and put them virtually anywhere. But where does it make the most sense? Since we can have many screens, it's certainly more practical to dedicate a separate GameObject for them than to “hide” them in random existing objects. I've seen people attach the scripts to the main camera. It's one possibility. Still, there could be multiple cameras in the scene, they could be nested in other objects – it could become cumbersome to locate a script. Another option is to leave the GUI object freely in the scene. Although, if there were many independent game objects already, it would only add to the clutter. Also, there could be screens available through the whole application, such as pause menu, and the screens specific to a scene, such as HUD. We could signify the difference by attaching one GUI object to the GameController and another to the GameLauncher, which are the pillars that will not move.
When everything else is in place, you'll need to save and load your game state. So there would be a SaveManager, which Unity doesn't provide and which you'll have to implement yourself, too. This is a huge topic and I plan to write more on it later.
Tuesday, 25 June 2013
Object vs. Scene Hierarchy
If you've designed some applications before, you've probably got used to certain ways to define their basic structure. When writing traditional system applications, you learn that you have one entry point and you make a main control loop to manage things, and from there it's pretty straightforward. Following the object-oriented programming paradigm, you define objects and link them together in a big, happy, intuitive hierarchy. It is common to structure your logic first and then to think about visualisation, serialisation, and whatever else you need to do with it.
A simple game of flying an air plane might look somehow like this, for the first time in your head (and using class diagram from UML):
The Application is your entry point. It accepts parameters, starts the game logic and supporting subsystems (logging, for example), and quits with an error if something goes terribly wrong. The GameController governs the game control loop. A player interacts with the AirPlane, rendered on screen, that is also affected by the Wind, which acts behind the scenes.
In Unity, however, the control loop is managed for you under the hood[1], the entry points are independent for each game object[2][3], and the editor is geared towards defining what you see in the scene instead of what is going on logically (which is not the same thing). So how do we get from the picture in our head to something akin to Unity that won't be a hell to maintain?
First, forget about the Application; it's already there. GameController will also play a quite different role. In some simple set-ups you won't even need it. Everything else needs to be transposed to Unity, and there are several ways to go about it.
It is important to realise that an object hierarchy is not a scene hierarchy. What we see at the Hierarchy pane in the editor is not the logic structure of our application. If you went and created an Application GameObject, put a MonoBehaviour on it, added a child GameObject named GameController, and so on, so you would have replicated the diagram, it wouldn't have worked. In the scene hierarchy, you link objects' transformations, yet in the object hierarchy (the diagram), you associate objects logically. Imagine, in our example, that the plane belongs to an airport. If we reassign it to another airport in the scene, it gets teleported to another place. Now, if the airport would have been an aircraft carrier ship, which would have moved, we would have been in real trouble. In the object hierarchy, on the other hand, such reassignment does only what we define it to do.
Okay, if nesting GameObjects is such a problem, why don't we bypass them altogether? We could build the object hierarchy depicted on the diagram from ordinary classes that do not derive from the MonoBehaviour. Then let it be instantiated and managed by a MonoBehaviour attached to an arbitrary GameObject. This somewhat reminds me of an MVC approach, of which I'll write a separate article later. Still, in order to draw the air plane and process player's input, we'd have to add another GameObject that would reference (and possibly update) the AirPlane object in our isolated object hierarchy. The same goes for every object that needs to be visualised. In a game, that would be about a vast majority. The number of objects would roughly double, there'd be an overhead of referencing between the associated pairs, it'd be more difficult to work with (classes would become fragmented) and it would hinder fast prototyping changes. You could argue that we had at least spared an unnecessary GameObject for the Wind, which is only simulated and not drawn. The truth is – we had also severed its parameters from tweaking in the editor. As you can see, this approach brings more disadvantages than benefits. Unless you're making a framework, I wouldn't recommend to use it.
The only option that remains is the middle ground – to utilise GameObjects as much as possible, but to organise them under different rules than logic.
Now, there's no need for the Wind to be actually a GameObject. It will not be drawn, so it can be as easily attached as a script to, for example, the GameController. It will lose on some of the aforementioned clarity, however. And there's always the chance someone will come up with a striking idea of how it would be great to visualise the wind in the middle of the project.
Notice how many objects are on equal level. While in a traditional system application the object hierarchy usually resembles a pyramid, descending top down (from the Application object, in our example), Unity forces us to build in reverse. The reason why the pyramids are popular is that it's natural, starting from one entry point, to delegate more complicated tasks to serving objects. The objects on top control the objects directly below them, establishing a strict chain of command. Ideally, the objects below don't even know about anything on top, so inter-dependencies are minimised and thus removing code effects only local changes. This way we divide and conquer. With Unity, every MonoBehaviour script is an entry point of itself. Additionally, any MonoBehaviour can access any other MonoBehaviour at will. Such environment cannot be controlled and originally higher-standing managing objects, such as the GameController, take on a more passive role. There's no more need to “own” instances or update them; it's already provided for. For example, if you were to model a clock, instead of a clock object moving its hand objects you would do better to make the clock hands move on their own and only ask the clock about the time. This way, if you, let's say, later decided to add a clock hand that would display seconds, you wouldn't have to touch the clock object at all. In such set-up we don't need the GameController to reference other objects and update them. It becomes an arbiter that carries a global game state through multiple scene loads and executes general functionality, such as saving or loading data, for instance.
Considering what has been said about the bottom-up structuring, the directions of associations between objects in our diagram will often reverse. Composition will turn into aggregation, as we no longer own objects. Usually, we don't even instantiate or destroy them. An association will look like a plain reference in Unity, which we can pre-fetch and keep for faster access. We can achieve that either by calling the GameObject.Find() method[4] during initialisation, or by assigning an exposed variable in the editor. Both techniques are useful depending on a situation.
Inheritance may prove a little tricky though. Let's say we want to have different types of the AirPlane – a WarPlane and a PassengerPlane. The AirPlane will contain a common logic that has nothing to do with Unity whatsoever. Only the WarPlane and the PassengerPlane will be attached to GameObjects. It's easy to start writing the AirPlane as a simple class, yet the WarPlane and the PassengerPlane need a MonoBehaviour to draw them. So you might go and write a MonoWarPlane that would inherit from the MonoBehaviour and hold the WarPlane. That would in turn require a special kind of wings, which would have their own separate MonoBehaviour to draw them. And just like that you could end up doubling all objects, with all the ills of our second scenario about an isolated hierarchy. The solution is luckily simple, if not always obvious – derive base classes from the MonoBehaviour.
Finally, we can sketch our example application's logic adapted to Unity:
A simple game of flying an air plane might look somehow like this, for the first time in your head (and using class diagram from UML):
The Application is your entry point. It accepts parameters, starts the game logic and supporting subsystems (logging, for example), and quits with an error if something goes terribly wrong. The GameController governs the game control loop. A player interacts with the AirPlane, rendered on screen, that is also affected by the Wind, which acts behind the scenes.
In Unity, however, the control loop is managed for you under the hood[1], the entry points are independent for each game object[2][3], and the editor is geared towards defining what you see in the scene instead of what is going on logically (which is not the same thing). So how do we get from the picture in our head to something akin to Unity that won't be a hell to maintain?
First, forget about the Application; it's already there. GameController will also play a quite different role. In some simple set-ups you won't even need it. Everything else needs to be transposed to Unity, and there are several ways to go about it.
It is important to realise that an object hierarchy is not a scene hierarchy. What we see at the Hierarchy pane in the editor is not the logic structure of our application. If you went and created an Application GameObject, put a MonoBehaviour on it, added a child GameObject named GameController, and so on, so you would have replicated the diagram, it wouldn't have worked. In the scene hierarchy, you link objects' transformations, yet in the object hierarchy (the diagram), you associate objects logically. Imagine, in our example, that the plane belongs to an airport. If we reassign it to another airport in the scene, it gets teleported to another place. Now, if the airport would have been an aircraft carrier ship, which would have moved, we would have been in real trouble. In the object hierarchy, on the other hand, such reassignment does only what we define it to do.
Okay, if nesting GameObjects is such a problem, why don't we bypass them altogether? We could build the object hierarchy depicted on the diagram from ordinary classes that do not derive from the MonoBehaviour. Then let it be instantiated and managed by a MonoBehaviour attached to an arbitrary GameObject. This somewhat reminds me of an MVC approach, of which I'll write a separate article later. Still, in order to draw the air plane and process player's input, we'd have to add another GameObject that would reference (and possibly update) the AirPlane object in our isolated object hierarchy. The same goes for every object that needs to be visualised. In a game, that would be about a vast majority. The number of objects would roughly double, there'd be an overhead of referencing between the associated pairs, it'd be more difficult to work with (classes would become fragmented) and it would hinder fast prototyping changes. You could argue that we had at least spared an unnecessary GameObject for the Wind, which is only simulated and not drawn. The truth is – we had also severed its parameters from tweaking in the editor. As you can see, this approach brings more disadvantages than benefits. Unless you're making a framework, I wouldn't recommend to use it.
The only option that remains is the middle ground – to utilise GameObjects as much as possible, but to organise them under different rules than logic.
- Each object in the diagram should be represented by a GameObject. Those are initially added to the scene as a flat list.
- If an object's position, size, or rotation depends on another object, it should be its child.
- If a number of objects resembles a collection, they should be grouped under a supplementary node that will work as a “container” of sorts.
Now, there's no need for the Wind to be actually a GameObject. It will not be drawn, so it can be as easily attached as a script to, for example, the GameController. It will lose on some of the aforementioned clarity, however. And there's always the chance someone will come up with a striking idea of how it would be great to visualise the wind in the middle of the project.
Notice how many objects are on equal level. While in a traditional system application the object hierarchy usually resembles a pyramid, descending top down (from the Application object, in our example), Unity forces us to build in reverse. The reason why the pyramids are popular is that it's natural, starting from one entry point, to delegate more complicated tasks to serving objects. The objects on top control the objects directly below them, establishing a strict chain of command. Ideally, the objects below don't even know about anything on top, so inter-dependencies are minimised and thus removing code effects only local changes. This way we divide and conquer. With Unity, every MonoBehaviour script is an entry point of itself. Additionally, any MonoBehaviour can access any other MonoBehaviour at will. Such environment cannot be controlled and originally higher-standing managing objects, such as the GameController, take on a more passive role. There's no more need to “own” instances or update them; it's already provided for. For example, if you were to model a clock, instead of a clock object moving its hand objects you would do better to make the clock hands move on their own and only ask the clock about the time. This way, if you, let's say, later decided to add a clock hand that would display seconds, you wouldn't have to touch the clock object at all. In such set-up we don't need the GameController to reference other objects and update them. It becomes an arbiter that carries a global game state through multiple scene loads and executes general functionality, such as saving or loading data, for instance.
Considering what has been said about the bottom-up structuring, the directions of associations between objects in our diagram will often reverse. Composition will turn into aggregation, as we no longer own objects. Usually, we don't even instantiate or destroy them. An association will look like a plain reference in Unity, which we can pre-fetch and keep for faster access. We can achieve that either by calling the GameObject.Find() method[4] during initialisation, or by assigning an exposed variable in the editor. Both techniques are useful depending on a situation.
Inheritance may prove a little tricky though. Let's say we want to have different types of the AirPlane – a WarPlane and a PassengerPlane. The AirPlane will contain a common logic that has nothing to do with Unity whatsoever. Only the WarPlane and the PassengerPlane will be attached to GameObjects. It's easy to start writing the AirPlane as a simple class, yet the WarPlane and the PassengerPlane need a MonoBehaviour to draw them. So you might go and write a MonoWarPlane that would inherit from the MonoBehaviour and hold the WarPlane. That would in turn require a special kind of wings, which would have their own separate MonoBehaviour to draw them. And just like that you could end up doubling all objects, with all the ills of our second scenario about an isolated hierarchy. The solution is luckily simple, if not always obvious – derive base classes from the MonoBehaviour.
Finally, we can sketch our example application's logic adapted to Unity:
Monday, 27 May 2013
UnityScript vs. C#
The first choice you're probably going to face
developing in Unity is which scripting language to use. I must admit
I didn't think about it much at first. I just picked UnityScript and
went with it. Later, when I wrote a small application as a technology
assessment, I've become to understand the pros and cons of my choice
better. Enough to make me reconsider my options.
According to Unity documentation, there are three scripting languages available –
JavaScript, C# and Boo.
First of all, let me clear up one thing. The Unity's
JavaScript is not the JavaScript
(ECMAScript) at all. It has nothing to do with it. If you by chance
have some experience with JavaScript programming, for instance from
web scripting, you will not benefit from it. I'm not entirely sure
why the Unity Technologies chose to masquerade behind an already
established name, probably some marketing reasons, but it's only
confusing. From this moment on, to steer away from the confusion, I'm
going to refer to it solely as the UnityScript, as many developers
already do. It seems a more appropriate name. If you're curious about
the differences, you can read this very interesting article:
http://wiki.unity3d.com/index.php/UnityScript_versus_JavaScript.
Now, Boo has a flavour of Python. I've never worked
with Python. My background comes from C++ and Java, plus a few other,
scripting languages. Hence I haven't really looked into it apart from
reading a Wikipedia article and its manifesto.
I haven't stumbled upon much code written in Boo neither, so I'm not
going to discuss it any further. All I can say is, if you like
Python, give Boo a try.
For me, the main question stands: Should I stick to the
UnityScript or the C#? This question continuously raises many heated
debates. The UnityScript is the officially recommended language of
choice created specifically for Unity. The C# is a more mature
language widely used with Microsoft products. What's important is to
realize that Unity is built on the .NET platform, which means core
data types and libraries are available in all languages. Do you want
to use the Dictionary structure in UnityScript? Go ahead and import
“System.Collections.Generic”. Everybody can benefit from the .NET framework documentation on MSDN as an additional scripting
reference. Developing for mobile platforms also imposes static
typing. The final decision boils down to a different syntax and
marginal language features.
There's no point to debate the syntax. It's a thing of
preference. Its only aspect that can be objectively gauged is
verbosity. The UnityScript seems slightly less verbose than C#,
though not by much. However, the balance gets tipped the other way if
you start comparing the language features.
The UnityScript was designed to be as simple as
possible, so it could be learned quickly. That roughly translates to
as few features as possible while still convenient to use. I've
wondered what features I've employed that I couldn't have used in C#.
I've only come up with not having to write the UnityEngine import
statement and class declarations for MonoBehaviour descendants. So
I've been saved from typing some boilerplate code. (Which is great!)
On the other hand, I've also considered what I miss
from Java or C++ (and by extension from C#). Symbolic constants. Yes,
a simple feature, but I miss it greatly. They significantly add to
code clarity. Generic programming. Really, who'd want to implement
the same patterns again and again just because of working with
different data types? Or constantly cast the return values? Sadly,
support for generics on iOS and Android is limited, yet still there.
Speaking of casting, auto unboxing of primitive types would be nice.
Have you ever tried to get an int from an Array? parseInt(),
seriously? There seems to be no way of re-casting an Object to a
primitive type, although the opposite works. And finally, namespaces.
Everybody talks about them. Everybody wants them. And in Unity 4 it
is still unclear if and how they can be used in UnityScript. These
are all minor things, but handy enough to make me think if I should
go for the C# instead. Here's another reasonable attempt to compare
the language features: http://www.holoville.com/blog/?p=820.
Well, smart people make their own choices. Myself, I think I'll fiddle with the UnityScript for a bit longer, so I can actually produce something useful, and in the mean time I'll brush up my C# skills. I'm not saying anything new here; it's a generally recommended approach, see http://answers.unity3d.com/questions/7528/how-should-i-decide-if-i-should-use-c-javascript-u.html, for example. It's always good to hear opinions of other, more experienced, people: http://forum.unity3d.com/threads/18507-Boo-C-and-JavaScript-in-Unity-Experiences-and-Opinions. I guess I just had to arrive at my own conclusion. I hope you will do as well.
Hello, Unity!
Hi. This blog is about me getting familiar with the
Unity engine.
I had developed and ported mobile Java games for
several years for many prominent publishers back then. And now I have
been working for over five years for a small, but successful firm
that makes widely acknowledged PC games. So, I guess I can call
myself a seasoned game developer. Nevertheless, I have decided to
make a small mobile game in a very small team, using the Unity
engine. Just for the heck of it. And since this technology is fairly
new to me, I came up with the idea to write articles to help me think
about the fundamental topics in an organized manner. Then I told
myself, “If I'm going to have my ideas penned down anyway, why keep
them to myself? Someone somewhere might ponder of the very same
things.” Thus I'm going to publish my articles of things I've
encountered on this blog, in hopes someone would find my insights
useful.
I will not post any tutorials. There are plenty of
other resources for that. Mostly, I'm going to cover topics of
application design because that's what puzzles me in the first place:
How to structure my application so I don't have to rewrite it every
time I add something? Funny thing – I have found an abundance of
examples which deal with small specific problems, e.g. how to make a
camera follow a box, how to save an integer... Yet I had to look
really hard to find more general information about common problems,
for example, should I make the camera a child of the box game object
– why, why not? How and where do I save the whole state of my
application, which may be more complex than just a few ints and
floats? What are my options? I guess I just have to figure it out on
my own, as many others do. But that's how we learn, right? Well, we
could have saved a lot of time if people were more willing to share
their experience rather than churning out final solutions. And that
is exactly what I'm determined to do – to look at the problem, not
at the solution. I'm going to write about topics that took me
considerable time to research and discover some answers to. For
anything else, please, visit Unity
documentation, Unity
Answers, Unity
forum, or Unity wiki.
Now, without much further ado, let's get head deep into
Unity.
Subscribe to:
Posts (Atom)