Wednesday, 15 June 2016

Making scriptable characters in Unity3D

While waiting for some quotes for PCBs for the light-up-LED-guitar project, we thought we'd revisit another never-ending project (thanks to some prompting from Steve at nerd night last week). Namely, our electronically enhanced board game.

Except making PCBs and hand etching great bit clumsy boards is still a bit boring - so we had a look at some Unity3D. In fact, a few of the nerds are working on some "real life" commissions, using Unity as a multi-platform app development IDE, so it was a perfect excuse to try out some Unity coding techniques, without it feeling too much like real work!

Anyway, after  couple of days, we managed to build a nice framework for a strategy-based game. It consists of a simple map (although getting the lighting right is a real nightmare) and some modular characters (with character-controller scripts). The game framework could be used for a few different game types (turn-by-turn you-go-I-go type games, or real-time simultaneous "command and conquer" type games to name just two).

The character controller accepts a list of commands in a simple script format, and plays back the instructions in the game environment. Here's a video to demonstrate

(the screen refresh rate of our screen capture software isn't brilliant, and Unity uses a lot of cpu cycles on the laptop this example runs on, so it's a bit jittery)

What seems curious is that we don't always get consistent results.
Soldier one has been programmed with the following commands:
  • c.addAction ("M0126");
  • c.addAction ("T0133");
  • c.addAction ("T0103");
  • c.addAction ("F0115");
  • c.addAction ("F0115");
  • c.setFocusOnWalk (true);
This is "move to board 01, square 26" then "turn to face board 01, square 33", then "turn to face board 01, square 3" finally "fire at board 01, square 15" (twice)

Soldier two has been programmed with the following commands:
  • c2.addAction ("T0115");
  • c2.addAction ("M0115");
  • c2.addAction ("T0126");
  • c2.addAction ("F0126");
Which equates to "turn to face board 01, square 15" then "move to board 01, square 15" then "turn to face board 01, square 26" and finally "fire at board 01, square 26".

So the scripts are the same on both soldiers and do not time.
Animations are carried out using Unity's Animator (state-machine-based animation) setting a parameter value to blend the current animation into any other animation

(to blend from the current animation into the "shoot" pose, for example, we simply set the anim_state value to 4 from one of our scripts)

What's peculiar is that, four times out of five, when these scripts are run at the same time, the soldier towards the bottom of the screen gets his shot away first, killing the guy further away.
But - every now and again - the other soldier manages to fire first!

Watch the video again - although the laser beams don't animate well enough to see who is shooting, just watch which soldier falls over at the end of the firing sequence. We seem to have an inconsistent result. From running exactly the same script.

Einstein once said that "madness is doing exactly the same thing over and over again and expecting a different outcome".

I think Unity has gone a bit mad....