UI / UX Design and Games

UI / UX Design

What is it?

UI – The User Interface of a game is the input methods and interfaces/screens through which a user interacts with the game.

UX – The User Experience of a game refers to how intuitive and enjoyable the experience of interacting with the game is.

The UI is tangible, for example using the mouse or touching an on screen button. The UX is untangible, for example an animation effect on a button that is subtle ,pleasing, and communicative.

UI Design is primarily a logical process rather than a creative one. This is because the design itself should be largely invisible as its goal is to enhance the game and not to be noticeable. It really does depend upon the game, building on design principles such as composition, color theory, lighting, typography, architecture etc will help to crteate something that stands out from the rest.

Why use it?

To achieve immersion through a quality and seamless user experience. To achieve a seamless user experience the user must be able to convert an idea into a game action with ease. A balance must be achieved on screen so that the perfect amount of information is displayed and how to interact with what is shown is obvious and natural.

The Fundamentals

♦ The interface should communicate only relevant information?

♦ The information that is needed should be easily accessible (is it obvious and easy to navigate to the required information through the UI)

♦ Interacting with the UI should be an intuitive experience and should not require any information on how to interact with it.

♦ It should be obvious to the user what I can interact with on screen.

♦ The experience should be seamless and fluid, the user should not have to wait for an interface to load or animate.

♦ Repetitive tasks or events should be fast and subtle.

How to acheive good UI and UX Design

Traditionally in software a UX designers job is to create an experience when using something for a purpose. These are the traditional common characteristics of UX design for software.

  • Transparent, so that the user needs to think as little as possible
  • Affordant, so that the user knows what possibilities it offers
  • Scalable, so that it unfolds as the user develops skills
  • Feedback-rich, so that the user knows when they did something
  • Constraining, so that the user can’t do things that get them in trouble

How do people interact with games?

UX design principles in games are often genre specifc, for example in an RTS game the panning camera through moving the mouse to the edges of screen is the expected norm for users.

User Experience Design and Game Experience Design

UX design in games is different than in other software. A good game is an immersive experience by design. The user experience of interacting with the game must ultimately support the game user experience. For example for a website traditionally with UX design you would show the minimum amount of information required to the user, however for a game, the game design may require the user to learn or solve a puzzle. Therefore more information is shown so as to satisfy the goal of the game design which is to provide an immersive and enjoyable game user experience. UX is about clarity that hides complexity while game design is about clarity that teaches complexity.

Clarity

At any place in an app, a few things should be perfectly clear to the user:

  • What just happened
  • Where you are
  • What you can do
  • What will happen when you do it

Just as in other software clarity is the first and most important job of any game interface. To be effective using an interface you’ve designed, people must be able to recognize what it is, care about why they would use it, understand what the interface is helping them interact with, predict what will happen when they use it, and then successfully interact with it. While there is room for mystery and delayed gratification in interfaces, there is no room for confusion. Clarity inspires confidence and leads to further use.

Consistency Matters

Screen elements should not appear consistent with each other unless they behave consistently with each other. Elements that behave the same should look the same. But it is just as important for unlike elements to appear unlike (be inconsistent) as it is for like elements to appear consistent. In an effort to be consistent novice designers often obscure important differences by using the same visual treatment (often to re-use code) when different visual treatment is appropriate.

Strong Visual Hierarchies Work Best

A strong visual hierarchy is achieved when there is a clear viewing order to the visual elements on a screen. That is, when users view the same items in the same order every time. Weak visual hierarchies give little clue about where to rest one’s gaze and end up feeling cluttered and confusing. In environments of great change it is hard to maintain a strong visual hierarchy because visual weight is relative: when everything is bold, nothing is bold. Should a single visually heavy element be added to a screen, the designer may need to reset the visual weight of all elements to once again achieve a strong hierarchy. Most people don’t notice visual hierarchy but it is one of the easiest ways to strengthen (or weaken) a design.

Smart Organization Reduces Cognitive Load

Group together like elements, show natural relationships by placement and orientation. By smartly organizing your content you make it less of a cognitive load on the user, they now do not have to think about how elements are related as it is obvious.

Interfaces exist to be used

As in most design disciplines, interface design is successful when people are using what you’ve designed.

Familiarity

Research shows that people enjoy seeing simple and familiar things. If something is an established norm then it should be used without any feeling of guilt.

 

Great design is Invisible

Great design usually goes unnoticed by the people who use it. One reason for this is that if the design is successful the user can focus on their own goals and not the interface.

Things To Consider

What am I on the screen?

Character Identification: The interface in games is more than how the user completes a task, it is also about to communicate with the user what they are on the screen and how that ‘character’ can be controlled through the UI. Immersion is critical in games and so making the user connect with the player ‘character’ is key.

Screen Space

Screen space should be used and not wasted, everything on screen should serve a purpose. Bigger is better but always try to show an appropriate amount of elements, scrolling should be avoided if possible.

Some Tips

  • Reptitive scrolling due to linear lists is never a good idea.
  • Not responding to clicks sometimes is not good, it should be obvious when input is working and when it is not.
  • Having the HUD  fading in and out is a good idea if that information is not constantly required, for example, the information does not change and is not required by the player all the time. When the player has low health the hud may instead not fade. If the HUD started pulsating it may distract from the game experience however due to the game design you may want the player to be distracted and aware that their health is low.
  • Don’t remind the user that they are using software, sudden pop ups are not good.
  • Everything should be a few clicks or touches away.
  • Aural feedback is important and enhances the user experience.
  • Reduce delays where possible especially around repetitive tasks.
  • Complex multi layered games sometimes require a more elaborate UI that must communicate a lot of information. Here pop ups or tool tips can be used to display that information when the user needs it.
  • Make something flexible, meaning something that looks in good in any possible situation.
  •  Connect emotionally with the user through color theory.
  • Sometimes elements that can help save you space, put more of a burden on the user mentally by forcing them to guess what is within the dropdown or what the element might be.

AB Testing

Why AB Test?

  • What should we build?
  • How do we build it?
  • How much of a feature do we need to build?
  • How do we learn fast?

How do we AB Test?

Before we start designing a feature, we come up with a hypothesis. A statement about our product and our users and their relationship. We also specify acceptance criteria.

Next we define different alternatives. What are the possible solutions that address our hypothesis.

We A/B test. We compare all the solutions side by side to figure out which ones perform best according to our acceptance criteria.

Finally we can make a decision. Either we’ve found a solution, or we’ve disproved our hypothesis, or we’ve had to modify our hypothesis.

Depending on the kind of hypothesis and the different testable alternatives we interpret A/B testing in a very broad sense. We have 4 different ways of A/B testing:

AB Testing Process

  1. Existing data: If we have alternatives that have already been tested out in another game, and if those results are applicable to our case, then we use the existing data to decide which direction to take.
  2. Mock: Can we test the feature or idea separately from the rest of the game experience? In that case we might mock out the feature on paper, or as a video. Then test it on a number of test volunteers.
  3. Prototype: It could be that we need to have the rest of the game experience to verify a feature. In that case a prototype is required for each of the different alternatives as separate code branches, then deploy them on different devices and find a number of test volunteers to try each prototype.
  4. In-product: This is the real deal, an actual A/B test. We implement the feature as a set of alternatives in the product, then split the traffic assigning each user to a specific alternative, then analyze the results. Sometimes we need to test a feature in a real life situation to determine if it’s good, and our own users are the most representative test group that we have.

Memory Management

Detecting Memory Issues Using Unity’s Profiler

Unity’s profiler is primarily geared at analyzing the performance and the resource demands of the various types of assets in your game. Yet the profiler is equally useful for digging into the memory-related behavior of your C# code – even of external .NET/Mono assemblies that don’t reference UnityEngine.dll.

Unity memory profiler window

This is to allow you to see if you have any memory leaks stemming from your C# code. Even if you don’t use any scripts, the ‘Used’ size of the heap grows and contracts continuously. As soon as you do use scripts, you need a way to see where allocations occur, and the CPU profiler provides that info.

Unity CPU profiler window

 

 C# Memory Management

Automatic Memory Management. This feature had been built deeply into the C# language and was an integral part of its philosophy. Memory management is a problematic issue that cannot be simply entrusted to the common language runtime (CLR).

Your ability to manage memory, or more precisely how memory is allocated, in Unity / .NET is limited.  You get to choose whether your custom data structures are class (always allocated on the heap) or struct (allocated on the stack unless they are contained within a class), and that’s it. If you want more magical powers, you must use C#’s unsafekeyword. But unsafe code is just unverifiable code, meaning that it won’t run in the Unity Web Player and probably some other target platforms. For this and other reasons, don’t use unsafe. Because of the above-mentioned limits of the stack, and because C# arrays are just syntactic sugar for System.Array(which is a class), you cannot and should not avoid automatic heap allocation. What you should avoid are unnecessary heap allocations.

Your powers are equally limited when it comes to deallocation. Actually, the only process that can deallocate heap objects is the GC, and its workings are shielded from you. What you can influence is when the last reference to any of your objects on the heap goes out of scope, because the GC cannot touch them before that. This limited power turns out to have huge practical relevance, because periodic garbage collection (which you cannot suppress) tends to be very fast when there is nothing to deallocate.

Each use of foreach creates an enumerator object – an instance of the System.Collections.IEnumerator interface – behind the scenes. But does it create this object on the stack or on the heap? That turns out to be an excellent question, because both are actually possible. Most importantly, almost all of the collection types in the System.Collections.Generic namespace (List<T>, Dictionary<K, V>, LinkedList<T>, etc.) are smart enough to return a struct from from their implementation of GetEnumerator()). This includes the version of the collections that ships with Mono 2.6.5 (as used by Unity).

So should you avoid foreach loops?

  • Don’t use them in C# code that you allow Unity to compile for you.
  • Do use them to iterate over the standard generic collections (List<T> etc.) in C# code that you compile yourself with a recent compiler. Visual Studio as well as the free .NET Framework SDK are fine, and I assume (but haven’t verified) that the one that comes with the latest versions of Mono and MonoDevelop is fine as well.

Should you avoid closures and LINQ?

You probably know that C# offers anonymous methods and lambda expressions (which are almost but not quite identical to each other). You can create them with the delegate keyword and the => operator, respectively. They are often a handy tool, and they are hard to avoid if you want to use certain library functions (such as List<T>.Sort()) or LINQ.

Do anonymous methods and lambdas cause memory leaks? The answer is: it depends. The C# compiler actually has two very different ways of handling them. To understand the difference, consider the following small chunk of code:

int result = 0;
    
void Update()
{
    for (int i = 0; i &lt; 100; i++)
    {
        System.Func&lt;int, int&gt; myFunc = (p) =&gt; p * p;
        result += myFunc(i);
    }
}

Coroutines

If you launch a coroutine via StartCoroutine(),  you implicitly allocate both an instance of Unity’sCoroutine class (21 Bytes on my system) and an Enumerator (16 Bytes). Importantly, no allocation occurs when the coroutine yield's or resumes, so all you have to do to avoid a memory leak is to limit calls to StartCoroutine() while the game is running.

Strings

No overview of memory issues in C# and Unity would be complete without mentioning strings. From a memory standpoint, strings are strange because they are both heap-allocated and immutable. When you concatenate two strings (be they variables or string-constants) as in:

void Update()
{
    string string1 = "Two";
    string string2 = "One" + string1 + "Three";
}

the runtime has to allocate at least one new string object that contains the result. In String.Concat() this is done efficiently via an external method called FastAllocateString(), but there is no way of getting around the heap allocation (40 Bytes on my system in the example above). If you need to modify or concatenate strings at runtime, use System.Text.StringBuilder.

Boxing

Sometimes, data has to be moved between the stack and the heap. For example, when you format a string as in:

string result = string.Format("{0} = {1}", 5, 5.0f);

… you are calling a method with the following signature:

public static string Format(
  string format,
  params Object[] args
)

In other words, the integer “5” and the floating-point number “5.0f” have to be cast to System.Objectwhen Format() is called. But Object is a reference type whereas the other two are value types. C# therefore has to allocate memory on the heap, copy the values to the heap, and hand Format() a reference to the newly created int and float objects. This process is called boxing, and its counterpartunboxing.

This behavior may not be a problem with String.Format() because you expect it to allocate heap memory anway (for the new string). But boxing can also show up at less expected locations. A notorious example occurs when you want to implement the equality operator==” for your home-made value types (for example, a struct that represents a complex number). Read all about how to avoid hidden boxing in such cases here.

Now we also want to avoid unnecessary deallocations, so that while our game is running, the garbage collector (GC) doesn’t create those ugly drops in frames-per-second. Object pooling is ideal for this purpose. 

Object Pooling

The idea behind object pooling is extremely simple. Instead of creating new objects with the new operator and allowing them to become garbage later, we store used objects in a pool and reuse them as soon as they’re needed again. The single most important feature of the pool – really the essence of the object-pooling design pattern – is to allow us to acquire a ‘new’ object while concealing whether it’s really new or recycled. This pattern can be realized in a few lines of code:

public class ObjectPool&lt;<strong>T</strong>&gt; where <strong>T</strong> : <strong>class</strong>, new()
{
    private Stack&lt;<strong>T</strong>&gt; m_objectStack = new Stack&lt;<strong>T</strong>&gt;();

    public <strong>T</strong> New()
    {
        return (m_objectStack.Count == 0) ? new <strong>T</strong>() : m_objectStack.Pop();
    }

    public void Store(<strong>T</strong> t)
    {
        m_objectStack.Push(t);
    }
}

Simple, yes, but a perfectly good realization of the core pattern. (If you’re confused by the “where T...” part, it is explained below.) To use this class, you have to replace allocations that make use of the new operator, such as here…

void Update()
{
    MyClass m = new MyClass();
}

… with paired calls to New() and Store():

ObjectPool&lt;<strong>MyClass</strong>&gt; poolOfMyClass = new ObjectPool&lt;<strong>MyClass</strong>&gt;();

void Update()
{
    MyClass m = poolOfMyClass.New();

    // do stuff...

    poolOfMyClass.Store(m);
}

This is annoying because you’ll need to remember to call Store(), and do so at the right place. Unfortunately, there is no general way to simplify this usage pattern further because neither theObjectPool class nor the C# compiler can know when your object has gone out of scope. Well, actually, there is one way – it is called automatic memory managment via garbage collection, and it’s shortcomings are the reason you’re reading these lines in the first place! That said, in some fortunate situations, you can use a pattern explaind under “A pool with collective reset” at the end of this article. There, all your calls to Store() are replaced by a single call to a ResetAll() method.

Functionality Requirements

  • Many types of objects need to be ‘reset’ in some way before they can be reused. At a minimum, all member variables may be set to their default state. This can be handled transparently by the pool, rather than by the user. When and how to reset is a matter of design that relates to the following two distinctions.
    • Resetting can be eager (i.e., executed at the time of storage) or lazy (executed right before the object is reused).
    • Resetting can be managed by the pool (i.e., transparently to the class that is being pooled) or by the class (transparently to the person who is declaring the pool object).
  • In the example above, the object pool ‘poolOfMyClass‘ had to be declared explicitly with class-level scope. Obviously, a new such pool would have to be declared for each new type of resource (My2ndClass etc.). Alternatively, it is possible to have the ObjectPool class create and manage all these pools transparently to the user.
  • Several object-pooling libraries you find out there aspire to manage very heterogeneous kinds of scarce resources (memory, database connections, game objects, external assets etc.). This tends to boost the complexity of the object pooling code, as the logic behind handling such diverse resources varies a great deal.
  • Some types of resources (e.g., database connections) are so scarce that the pool needs to enforce an upper limit and offer a safe way of failing to allocate a new/recycled object.
  • If objects in the pool are used in large numbers at relatively ‘rare’ moments, we may want the pool to have the ability to shrink (either automatically or on-demand).
  • Finally, the pool can be shared by several threads, in which case it would have to be thread-safe.

Which of these are worth implementing? Your answer may differ from mine, but allow me to explain my own preferences.

  • Yes, the ability to ‘reset’ is a must-have. But, as you will see below, there is no point in choosing between having the reset logic handled by the pool or by the managed class. You are likely to need both, and the code below will show you one version for each case.
  • Unity imposes limitations on your multi-threading – basically, you can have worker threads in addition to the main game thread, but only the latter is allowed to make calls into the Unity API. In my experience, this means that we can get away with separate object pools for all our threads, and can thus delete ‘support for multi-threading’ from our list of requirements.
  • Personally, I don’t mind too much having to declare a new pool for each type of object I want to pool. The alternative means using the singleton pattern: you let your ObjectPool class create new pools as needed and store them in a dictionary of pools, which is itself stored in a static variable. To get this to work safely, you’d have to make your ObjectPool class multi-threaded. ( I would avoid multi threaded pooling solutions due to being likely unsafe).
  • In line with the scope of this three-part blog, I’m only interested in pools that deal with one type of scarce resource: memory. Pools for other kinds of resources are important, too, but they’re just not within the scope of this post. This really narrows down the remaining requirements.
    • The pools presented here do not impose a maximum size. If your game uses too much memory, you are in trouble anyway, and it’s not the object pool’s business to fix this problem.
    • By the same token, we can assume that no other process is currently waiting for you to release your memory as soon as possible. This means that resetting can be lazy, and that the pool doesn’t have to offer the ability to shrink.

A basic pool with initialization and reset

Our revised ObjectPool<T> class looks as follows:

public class ObjectPool&lt;<strong>T</strong>&gt; where <strong>T</strong> : <strong>class</strong>, new()
{
    private Stack&lt;<strong>T</strong>&gt; m_objectStack;

    private Action&lt;<strong>T</strong>&gt; m_resetAction;
    private Action&lt;<strong>T</strong>&gt; m_onetimeInitAction;

    public ObjectPool(int initialBufferSize, Action&lt;<strong>T</strong>&gt;
        ResetAction = null, Action&lt;<strong>T</strong>&gt; OnetimeInitAction = null)
    {
        m_objectStack = new Stack&lt;<strong>T</strong>&gt;(initialBufferSize);
        m_resetAction = ResetAction;
        m_onetimeInitAction = OnetimeInitAction;
    }

    public <strong>T</strong> New()
    {
        if (m_objectStack.Count &gt; 0)
        {
            <strong>T</strong> t = m_objectStack.Pop();

            if (m_resetAction != null)
                m_resetAction(t);

            return t;
        }
        else
        {
            <strong>T</strong> t = new <strong>T</strong>();

            if (m_onetimeInitAction != null)
                m_onetimeInitAction(t);

            return t;
        }
    }

    public void Store(<strong>T</strong> obj)
    {
        m_objectStack.Push(obj);
    }
}

This implementation is very simple and straightforward. The parameter ‘T‘ has two constraints that are specified by way of “where T : class, new()“. Firstly, ‘T‘ has to be a class (after all, only reference types need to be object-pooled), and secondly, it must have a parameterless constructor.

The constructor takes your best guess of the maximum number of objects in the pool as a first parameter. The other two parameters are (optional) closures – if given, the first closure will be used to reset a pooled object, while the second initializes a new one. ObjectPool<T> has only two methods besides its constructor, New() and Store(). Because the pool uses a lazy approach, all work happens in New(), where new and recycled objects are either initialized or reset. This is done via two closures that can optionally be passed to the constructor. Here is how the pool could be used in a class that derives from MonoBehavior.

class SomeClass : MonoBehaviour
{
    private ObjectPool&lt;<em>List&lt;</em>Vector3<em>&gt;</em>&gt; m_poolOfListOfVector3 =
        new ObjectPool&lt;<em>List&lt;</em>Vector3<em>&gt;</em>&gt;(32,
        (list) =&gt; {
            list.Clear();
        },
        (list) =&gt; {
            list.Capacity = 1024;
        });

    void Update()
    {
        List&lt;<em>Vector3</em>&gt; listVector3 = m_poolOfListOfVector3.New();

        // do stuff

        m_poolOfListOfVector3.Store(listVector3);
    }
}

A pool that lets the managed type reset itself

The basic version of the object pool does what it is supposed to do, but it has one conceptual blemish. It violates the principle of encapsulation insofar as it separates the code for initializing / resetting an object from the definition of the object’s type. This leads to tight coupling, and should be avoided if possible. In the SomeClass example above, there is no real alternative because we cannot go and change the definition of List<T>. However, when you use object pooling for your own types, you may want to have them implement the following simple interface IResetable instead. The corresponding classObjectPoolWithReset<T> can hence be used without specifying any of the two closures as parameters.

public interface IResetable
{
    void Reset();
}

public class ObjectPoolWithReset&lt;<strong>T</strong>&gt; where <strong>T</strong> : <strong>class</strong>, IResetable, new()
{
    private Stack&lt;<strong>T</strong>&gt; m_objectStack;

    private Action&lt;<strong>T</strong>&gt; m_resetAction;
    private Action&lt;<strong>T</strong>&gt; m_onetimeInitAction;

    public ObjectPoolWithReset(int initialBufferSize, Action&lt;<strong>T</strong>&gt;
        ResetAction = null, Action&lt;<strong>T</strong>&gt; OnetimeInitAction = null)
    {
        m_objectStack = new Stack&lt;<strong>T</strong>&gt;(initialBufferSize);
        m_resetAction = ResetAction;
        m_onetimeInitAction = OnetimeInitAction;
    }

    public <strong>T</strong> New()
    {
        if (m_objectStack.Count &gt; 0)
        {
            <strong>T</strong> t = m_objectStack.Pop();

            t.Reset();

            if (m_resetAction != null)
                m_resetAction(t);

            return t;
        }
        else
        {
            <strong>T</strong> t = new <strong>T</strong>();

            if (m_onetimeInitAction != null)
                m_onetimeInitAction(t);

            return t;
        }
    }

    public void Store(<strong>T</strong> obj)
    {
        m_objectStack.Push(obj);
    }
}

A Pool with Collective Reset

Some types of data structures in your game may never persist over a sequence of frames, but get retired at or before the end of each frame. In this case, when we have a well-defined point in time by the end of which all pooled objects can be stored back in the pool, we can rewrite the pool to be both easier to use and significantly more efficient. Let’s look at the code first.

public class ObjectPoolWithCollectiveReset&lt;<strong>T</strong>&gt; where <strong>T</strong> : <strong>class</strong>, new()
{
    private List&lt;<strong>T</strong>&gt; m_objectList;
    private int m_nextAvailableIndex = 0;

    private Action&lt;<strong>T</strong>&gt; m_resetAction;
    private Action&lt;<strong>T</strong>&gt; m_onetimeInitAction;

    public ObjectPoolWithCollectiveReset(int initialBufferSize, Action&lt;<strong>T</strong>&gt;
        ResetAction = null, Action&lt;<strong>T</strong>&gt; OnetimeInitAction = null)
    {
        m_objectList = new List&lt;<strong>T</strong>&gt;(initialBufferSize);
        m_resetAction = ResetAction;
        m_onetimeInitAction = OnetimeInitAction;
    }

    public <strong>T</strong> New()
    {
        if (m_nextAvailableIndex &lt; m_objectList.Count)
        {
            // an allocated object is already available; just reset it
            <strong>T</strong> t = m_objectList[m_nextAvailableIndex];
            m_nextAvailableIndex++;

            if (m_resetAction != null)
                m_resetAction(t);

            return t;
        }
        else
        {
            // no allocated object is available
            <strong>T</strong> t = new <strong>T</strong>();
            m_objectList.Add(t);
            m_nextAvailableIndex++;

            if (m_onetimeInitAction != null)
                m_onetimeInitAction(t);

            return t;
        }
    }

    public void ResetAll()
    {
        m_nextAvailableIndex = 0;
    }
}

The changes to the original ObjectPool<T> class are substantial this time. Regarding the signature of the class, the Store() method is replaced by ResetAll(), which only needs to be called once when all allocated objects should go back into the pool. Inside the class, the Stack<T> has been replaced by aList<T> which keeps references to all allocated objects even while they’re being used. We also keep track of the index of the most recently created-or-released object in the list. In that way, New() knows whether to create a new object or reset an existing one.

Delegates, Action Delegates, Func Delegates, and Lambda Expressions

Delegates

A delegate is a type that safely encapsulates a method, similar to a function pointer in C and C++. Unlike C function pointers, delegates are object-oriented, type safe, and secure. The type of a delegate is defined by the name of the delegate. A Delegate can be thought of as a reference pointer to an object/method. When it gets called, it notifies all methods that reference the delegate.

Delegate Multicast Example (+=):

using UnityEngine;
using System.Collections;

public class MulticastScript : MonoBehaviour 
{
    delegate void MultiDelegate();
    MultiDelegate myMultiDelegate;
    

    void Start () 
    {
        myMultiDelegate += PowerUp;
        myMultiDelegate += TurnRed;
        
        if(myMultiDelegate != null)
        {
            myMultiDelegate();
        }
    }
    
    void PowerUp()
    {
        print ("Orb is powering up!");
    }
    
    void TurnRed()
    {
        renderer.material.color = Color.red;
    }
}

Action Delegates

You can use the Action(Of T) delegate to pass a method as a parameter without explicitly declaring a custom delegate. The benefit here is you don’t have to declare a delegate. The compiler is smart enough to figure out the proper types.

However there is a limitation, the corresponding method action must not return a value. (In C#, the method must return void.)

Action Delegate Example:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ModernLanguageConstructs
{
    class Program
    {
        static void Main(string[] args)
        {
            // Part 1 - First action that takes an int and converts it to hex
            Action&lt;int&gt; displayHex = delegate(int intValue)
            {
                Console.WriteLine(intValue.ToString("X"));
            };

            // Part 2 - Second action that takes a hex string and 
            // converts it to an int
            Action&lt;string&gt; displayInteger = delegate(string hexValue)
            {
                Console.WriteLine(int.Parse(hexValue,
                    System.Globalization.NumberStyles.HexNumber));
            };
            
            // Part 3 - exercise Action methods
            displayHex(16);
            displayInteger("10");
        }
    }
}

Func Delegates
This differs from Action<> in the sense that it supports parameters AND return values.
You can use this delegate to represent a method that can be passed as a parameter without explicitly declaring a custom delegate. The encapsulated method must correspond to the method signature that is defined by this delegate.
This means that the encapsulated method must have one parameter that is passed to it by value, and that it must return a value.
Func Delegate Example:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ModernLanguageConstructs
{
    class Program
    {
        static void Main(string[] args)
        {
            // Part 1 - First Func&lt;&gt; that takes an int and returns a string
            Func&lt;int, string&gt; displayHex = delegate(int intValue)
            {
                return (intValue.ToString("X"));
            };

            // Part 2 - Second Func&lt;&gt; that takes a hex string and 
            // returns an int
            Func&lt;string, int&gt; displayInteger = delegate(string hexValue)
            {
                return (int.Parse(hexValue,
                    System.Globalization.NumberStyles.HexNumber));
            };

            // Part 3 - exercise Func&lt;&gt; delegates
            Console.WriteLine(displayHex(16));
            Console.WriteLine(displayInteger("10"));
        }
    }
}
 Lambda Expressions
A lambda expression is an anonymous function that can contain expressions and statements, and can be used to create delegates or expression tree types.
All lambda expressions use the lambda operator =>, which is read as “goes to”. The left side of the lambda operator specifies the input parameters (if any) and the right side holds the expression or statement block.
The lambda expression x => x * x is read “x goes to x times x.”
Lambda Expression Example:
private IEnumerator waitThenCallback(float time, Action callback)
{
   yield return new WaitForSeconds(time);
   callback();
}

void Start()
{
  splashScreen.show();

  StartCoroutine(waitThenCallback(5, () =&gt; 
         { Debug.Log("Five seconds have passed!"); }));
  StartCoroutine(waitThenCallback(10, () =&gt; 
         { Debug.Log("Ten seconds have passed!"); }));
  StartCoroutine(waitThenCallback(20, () =&gt; 
  {
    Debug.Log("Twenty seconds have passed!"); 
    splashScreen.hide();
  }));
}
Another Lambda Expression Example:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ModernLanguageConstructs
{
    class Program
    {
        static void Main(string[] args)
        {
            // Part 1 - An action and a lambda
            Action&lt;int&gt; displayHex = intValue =&gt;
            {
                Console.WriteLine(intValue.ToString("X"));
            };

            Action&lt;string&gt; displayInteger = hexValue =&gt;
            {
                Console.WriteLine(int.Parse(hexValue,
                    System.Globalization.NumberStyles.HexNumber));
            };

            // Part 2 - Use the lambda expressions
            displayHex(16);
            displayInteger("10");

        }
    }
}

Communicate with Comments

/// Comments

After declaring the public method or field,  enter “///” in the line above it, that will auto fill a comment block. This will also enable hover help text.

Summary Comment Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/// &lt;summary&gt;
/// Initializes a new instance of the &lt;see cref="EnemyLoader"/&gt; class.
/// &lt;/summary&gt;
/// &lt;param name='enemyName'&gt;
/// Enemy name. e.g evilfrog bustyfox
/// &lt;/param&gt;
/// &lt;param name='successCallback'&gt;
/// Success callback.
/// &lt;/param&gt;
/// &lt;param name='failureCallback'&gt;
/// Failure callback.
/// &lt;/param&gt;
public EnemyLoader( string enemyName, LoadSuccess successCallback, LoadFailure failureCallback)

Code Comment Example:

Bad Good
// increment enemies // we know there is now another enemy
enemies++; enemies++;

Enums and Bitwise operators

Enums and Unity Editor

How to make life easier by making enum flags into mask fields in the Unity inspector.

EnumFlagAttribute.cs [Must be placed in a folder that is not Editor]

using UnityEngine;

public class EnumFlagAttribute : PropertyAttribute
{
 public string enumName;

 public EnumFlagAttribute() {}

 public EnumFlagAttribute(string name)
 {
    enumName = name;
 }
}

EnumFlagsAttributeDrawer.cs [Must be placed in the Editor folder]

using System;
using System.Reflection;
using UnityEditor;
using UnityEngine;

[CustomPropertyDrawer(typeof(EnumFlagAttribute))]
public class EnumFlagDrawer : PropertyDrawer {
 public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
 {
    EnumFlagAttribute flagSettings = (EnumFlagAttribute)attribute;
    Enum targetEnum = GetBaseProperty&lt;Enum&gt;(property);

    string propName = flagSettings.enumName;
    if (string.IsNullOrEmpty(propName))
    propName = property.name;

    EditorGUI.BeginProperty(position, label, property);
    Enum enumNew = EditorGUI.EnumMaskField(position, propName,   
    targetEnum);
    property.intValue = (int) Convert.ChangeType(enumNew,  
    targetEnum.GetType());

    EditorGUI.EndProperty();
 }

 static T GetBaseProperty&lt;T&gt;(SerializedProperty prop)
 {
    // Separate the steps it takes to get to this property
    string[] separatedPaths = prop.propertyPath.Split('.');

    // Go down to the root of this serialized property
    System.Object reflectionTarget =   
    prop.serializedObject.targetObject as object;
    // Walk down the path to get the target object
    foreach (var path in separatedPaths)
    {
       FieldInfo fieldInfo =  
       reflectionTarget.GetType().GetField(path);
       reflectionTarget = fieldInfo.GetValue(reflectionTarget);
    }
    return (T) reflectionTarget;
 }
}

It is important to note that Enum definition should also use power-of-two values. Bitwise shifts achieve this, they basically shift the bits of a number right (>>) or left (<<). If you have a decimal number, let’s say “1” and you shift it of one position to the left, you’ll have “10”. Another shift and you’ll get “100”. If shifting one position in base ten is equivalent to multiply (or divide) by ten, shifting one position in base two is equivalent to multiply (or divide) by two. This is why bitwise shifts can be used to easily create powers of two.

Test.cs [Attach this to a gameObject to see the property drawer in action]

using UnityEngine;
using System.Collections;
using System;

public enum MyEnum
{                      //BINARY DEC
  None = 0 &lt;&lt; 0,     //000000 0
  First = 1 &lt;&lt; 1,    //000001 1
  Second = 1 &lt;&lt; 2,   //000010 2
  Third = 1 &lt;&lt; 3,    //000100 4
  Fourth = 1 &lt;&lt; 4,   //001000 8
  Fifth = 1 &lt;&lt; 5,
  Sixth = 1 &lt;&lt; 6,
  Seventh = 1 &lt;&lt; 7,
  Eighth = 1 &lt;&lt; 8,
}

public class Test : MonoBehaviour 
{
  [EnumFlagAttribute]
  public MyEnum m_enum;

  public MyEnum m_lastEnum;
  public void Update()
  {
    if (m_lastEnum != m_enum) 
    {
      Debug.Log (m_enum);
      m_lastEnum = m_enum;
      if ((m_enum &amp; MyEnum.Fourth) != 0) 
                        {
        Debug.Log ("HAS FOURTH");
      }

    }
  }
}

Agile

Agile isn’t what you do, it’s how you do it. Agile is not about having a strict list of tasks and rules. It is about finding methods that work best for your team/company, and using them. At its core it is about cutting inefficient practices and adopting more efficient ones.

The Core values of any true Agile Methodology

Individuals and interactions over processes and tools
Working software over comprehensive documentation
Customer collaboration over contract negotiation
Responding to change over following a plan

It is important to realise that while Scrum and Kanban are agile frameworks, they are not what agile is.  They can lead to benefits but it depends on how you are using them. Do not fit the team to the framework, adapt the framework to the team.

The Twelve principles of the Agile Manifesto

  1. Our highest priority is to satisfy the customer
    through early and continuous delivery
    of valuable software.
  2. Welcome changing requirements, even late in
    development. Agile processes harness change for
    the customer’s competitive advantage.
  3. Deliver working software frequently, from a
    couple of weeks to a couple of months, with a
    preference to the shorter timescale.
  4. Business people and developers must work
    together daily throughout the project.
  5. Build projects around motivated individuals.
    Give them the environment and support they need,
    and trust them to get the job done.
  6. The most efficient and effective method of
    conveying information to and within a development
    team is face-to-face conversation.
  7. Working software is the primary measure of progress.
  8. Agile processes promote sustainable development.
    The sponsors, developers, and users should be able
    to maintain a constant pace indefinitely.
  9. Continuous attention to technical excellence
    and good design enhances agility.
  10. Simplicity–the art of maximizing the amount
    of work not done–is essential.
  11. The best architectures, requirements, and designs
    emerge from self-organizing teams.
  12. At regular intervals, the team reflects on how
    to become more effective, then tunes and adjusts
    its behavior accordingly.

Automated Deployment in Unity

The automated deployment process of an application is critical to achieving the Continuous Delivery approach. CD is about helping teams or individuals build, test, and release faster and more reliably. Essential to automated deployment is the Build Automation server which plays a major part in a solid Continuous Delivery Deployment Pipeline. A deployment pipeline is basically an automated implementation of your application’s build, deploy, test and release process.

AutoDeployment

Unity has finally come out with a built in solution to build automation, Unity Cloud Build. You simply:

  • Setup a repo (.git BitBucket) and commit your Unity Project files
  • Create/Activate Unity Cloud Build from the services window
  • Copy the repo url into the Unity Cloud Build window (Window – Services – Cloud Build)
  • Setup Access Rights if the repo is private by adding an SSH key created by Unity Cloud Build to your BitBucket repo
  • Configure your Unity Cloud Build – Select platform, select branch of repo to build from
  • Build

From here Unity Cloud Build will watch your repo for new changes. Once a change has been detected the project will start building. Once complete, emails are sent out with links to install on your devices.

UnityCloudBuildPipeline