Wednesday, December 09, 2015

Implicit typing in C# using "var"

I use the var keyword everywhere. Someone told me today that this is a bad practice, because "sometimes you can't tell what type it is".

Well, I disagree. I believe we generally don't care what type a variable is, we care about how we use it, the interface it provides to the programmer. For example:
foreach(var i in myListOfThings) {
    Debug.Log(i.name);
}
I don't care what typeof(i) is, I just want to know it has a .name attribute. If I change the type later, I probably still want it to have a .name attribute, and the var keyword lets this code keep working. Also:
var v = new Vector3(0,0,0);
//vs
Vector3 v = new Vector3(0,0,0);
In this case, the Vector3 type declaration is redundant, it is simply repeating information already on the same line. Remember, repeating yourself in code is a Bad Thing. Later on if I realise my Vector3 variables need to be Vector2 variables, I need to change the type information in 2 places for each variable. Yuck.

Finally, var lets me write less characters, which often means less backspacing and retyping!
var now = System.DateTime.Now;
//or
System.DateTime now = System.DateTime.Now;

This well written post describing more advantages of implicit typing. To Summarise:
  • It induces better naming for local variables.
  • It induces better API.
  • It induces variable initialisation.
  • It removes code noise.
  • It doesn't require the using directive.

Monday, November 23, 2015

MOG Server & Client for Unity.

Sometime ago I put my generic multiuser game server (NetWrok) on GitHub. It's written in Python3, uses websockets, postgresql and runs on most platforms.

I have now released the Unity NetWrok Client code.

Wednesday, November 11, 2015

I made a Mosasaur.

Wings3D for modelling. Cheetah3D for UV unwrap and rigging. Substance Painter for Texturing.



Mososaurus
by simonwittber
on Sketchfab

Tuesday, October 27, 2015

Python on Hardware

Just bought a MicroPython pyboard. Plugged it in, and I have a python prompt. Never thought this day would come. Amazing.

Thursday, October 15, 2015

Face / Avatar Generator in Unity3D

I had a need to generate infinite random character faces. I created a head mesh with a lot of bones which I used to morph and deform the face. I think the results are moderately successful. I was able to generate 10000 of these tiny portraits in about 3 minutes.

Friday, August 07, 2015

I killed my router with an apostrophe.

My router appeared to die last night, after I tried to setup a new WiFi network. The admin interface for the router was completely borked, and the browser console kept showing javascript errors.

Turns out, because my network name contained an apostrophe, the javascript code behind the admin interface became completely unusable.

Saturday, July 18, 2015

AsyncCoroutines - Rather Easy Multithreading for Unity

This is a tiny little library to help you use your multicore CPU in Unity3D.
I've made a brief video overview and the package will be available on the asset store very soon.
It includes a task viewer, which is similar to the process viewer on your operating system. It shows which coroutines are running in the background and foreground, which coroutines are waiting for execution, and how many CPU ticks each coroutine consumes per frame.


To use, make sure you have:
using AsyncCoroutines;
at the top of your script file. Below is an example of a coroutine method which can be started using:
gameObject.StartTask(MyCoroutine());
IEnumerator MyCoroutine() {
    //this statement will move the execution to the background thread
    //pool.
    yield return Schedule.GotoBackground;
    //Do some work here
        
    //This statement will move the execution back into the main unity
    //foreground thread.
    yield return Schedule.GotoForeground;

    //When the coroutine is running in the main thread, yield statements
    //will work as normal.
    yield return null;
    yield return WaitForSeconds(1);
}

Tuesday, July 14, 2015

3D Conference in Perth on 22/07/15

An interesting conference for 3D tech next week is happening in Perth. It's only short, 7:30AM - 2PM, however there is some interesting stuff happening. A realtime 3D scan of a Ducati, 3D printing and Oculus VR... I'm 90% sure I'll be there.

More info and registration here.

Tuesday, July 07, 2015

Behaviour and Decision Library for Unity

uBAD is a library for programmers to create AI based on behaviour tree systems. Instead of using a graphical editor to define the tree, it uses a text file with a simple syntax. It includes a visual debugger.

Thursday, June 11, 2015

Unity3D Micro Optimisation: Loops

This benchmark answers two questions.

1. What is the performance difference between different loop statements? The two options considered are "for" and "foreach". Why bother? These things matter when dealing with modifying 4000 particles per frame in your latest Unity game on a mobile device.

2. What is the performance difference between different collections? Arrays and Generic lists are commonly used in Unity, and I've always wondered about the performance difference of accessing arrays by index, vs lists by index.

The results are quite surprising. Benchmark code below, but here are my results:

  • For Each Loop over Array: 262 ticks
  • For Loop over Array: 120 ticks
  • For Each Loop over List: 1640 ticks
  • For Loop over List: 598 ticks

The (expected) winner is clearly a plain for loop over an array, but I didn't realise the difference between the loop structures and collections would be so large!


using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;

public class LoopBenchmarks : MonoBehaviour
{
    public int iterations = 15;
    public int arraySize = 40;

    void Start ()
    {
        BenchArray ();
        BenchList ();
    }

    void BenchArray ()
    {
        var array = new int[arraySize];
        var clock = new Stopwatch ();
        var foreachTime = 0f;
        var forTime = 0f;
        var mapTime = 0f;
        for (var iteration=0iteration<iterationsiteration++) {
            clock.Start ();
            foreach (var i in array) {
            }
            clock.Stop ();
            foreachTime += clock.ElapsedTicks;
            clock.Reset ();
            clock.Start ();
            for (var idx=0idx<array.Lengthidx++) {
                var i = array [idx];
            }
            clock.Stop ();
            forTime += clock.ElapsedTicks;
            clock.Reset ();
        }
        UnityEngine.Debug.Log (string.Format ("For Each Loop over Array: {0} ticks"foreachTime / iterations));
        UnityEngine.Debug.Log (string.Format ("For Loop over Array: {0} ticks"forTime / iterations));
    }

    void BenchList ()
    {
        var list = new List<int> (new int[arraySize]);
        var clock = new Stopwatch ();
        var foreachTime = 0f;
        var forTime = 0f;
        for (var iteration=0iteration<iterationsiteration++) {
            clock.Start ();
            foreach (var i in list) {
            }
            clock.Stop ();
            foreachTime += clock.ElapsedTicks;
            clock.Reset ();
            clock.Start ();
            for (var idx=0idx<list.Countidx++) {
                var i = list [idx];
            }
            clock.Stop ();
            forTime += clock.ElapsedTicks;
            clock.Reset ();
        }
        UnityEngine.Debug.Log (string.Format ("For Each Loop over List: {0} ticks"foreachTime / iterations));
        UnityEngine.Debug.Log (string.Format ("For Loop over List: {0} ticks"forTime / iterations));
    }
    
}


Update: Thanks to a comment below, I've added in a new benchmark, and run the test in the latest Unity5.1; The results are surprising. Surprising enough that I added some work to each benchmark just to be sure the compiler wasn't optimising away the useless loops.

  • For Each Loop over Array: 184 ticks
  • For Loop over Array: 206 ticks
  • For Loop over Array with cached Length: 201 ticks
  • For Each Loop over List: 1153 ticks
  • For Loop over List: 686 ticks

It seems that the foreach loop over an array is now FASTER than a for loop. The other surprise is that caching the Length attribute has a very small impact on performance. These results were unexpected... if I get time I'll do some more tests to confirm.

This is the new Benchmark code.

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;

public class LoopBenchmarks : MonoBehaviour
{
  public int iterations = 1500;
  public int arraySize = 4000;
  
  void Start ()
  {
    BenchArray ();
    BenchArrayWithLengthCached ();
    BenchList ();
  }
  
  void BenchArray ()
  {
    var array = new int[arraySize];
    var clock = new Stopwatch ();
    var foreachTime = 0f;
    var forTime = 0f;
    for (var iteration=0; iteration<iterations; iteration++) {
      clock.Start ();
      foreach (var i in array) {
        if (i < 0)
          throw new System.Exception ();
      }
      clock.Stop ();
      foreachTime += clock.ElapsedTicks;
      clock.Reset ();
      clock.Start ();
      for (var idx=0; idx<array.Length; idx++) {
        var i = array [idx];
        if (i < 0)
          throw new System.Exception ();
      }
      clock.Stop ();
      forTime += clock.ElapsedTicks;
      clock.Reset ();
    }
    UnityEngine.Debug.Log (string.Format ("For Each Loop over Array: {0} ticks", foreachTime / iterations));
    UnityEngine.Debug.Log (string.Format ("For Loop over Array: {0} ticks", forTime / iterations));
  }

  void BenchArrayWithLengthCached ()
  {
    var array = new int[arraySize];
    var clock = new Stopwatch ();

    var forTime = 0f;

    for (var iteration=0; iteration<iterations; iteration++) {
      int length = array.Length;
      clock.Start ();
      for (var idx=0; idx<length; idx++) {
        var i = array [idx];
        if (i < 0)
          throw new System.Exception ();
      }
      clock.Stop ();
      forTime += clock.ElapsedTicks;
      clock.Reset ();
    }
    UnityEngine.Debug.Log (string.Format ("For Loop over Array with Cached Length: {0} ticks", forTime / iterations));
  }
  
  void BenchList ()
  {
    var list = new List<int> (new int[arraySize]);
    var clock = new Stopwatch ();
    var foreachTime = 0f;
    var forTime = 0f;
    for (var iteration=0; iteration<iterations; iteration++) {
      clock.Start ();
      foreach (var i in list) {
        if (i < 0)
          throw new System.Exception ();
      }
      clock.Stop ();
      foreachTime += clock.ElapsedTicks;
      clock.Reset ();
      clock.Start ();
      for (var idx=0; idx<list.Count; idx++) {
        var i = list [idx];
        if (i < 0)
          throw new System.Exception ();
      }
      clock.Stop ();
      forTime += clock.ElapsedTicks;
      clock.Reset ();
    }
    UnityEngine.Debug.Log (string.Format ("For Each Loop over List: {0} ticks", foreachTime / iterations));
    UnityEngine.Debug.Log (string.Format ("For Loop over List: {0} ticks", forTime / iterations));
  }
  
}

Thursday, April 09, 2015

Malloc in BinaryReader and BinaryWriter

In my efforts to write a malloc-free network library for Unity3D, I discovered that BinaryReader and BinaryWriter perform malloc operations when reading/writing floats and doubles.

It seems this is the case, because C# does not allow bit shifting operations on these types, which is used to turn these types into 4 or 8 bytes.

I ended up using this code to convert these types without using the builtin BitConverter (which performs a malloc!)


float[] FLOAT = new float[1];

public float ReadFloat ()
{
   Buffer.BlockCopy(buffer, (int)readStream.Position, FLOAT, 0, 4);
   readStream.Position += 4;
   return FLOAT[0];
}

public void Write (float value)
{
   FLOAT[0] = value;
   Buffer.BlockCopy(FLOAT, 0, buffer, (int)writeStream.Position, 4);
   writeStream.Position += 4;
}


Popular Posts