A bucket list item for me was getting a 3D video game published.  Although I have a ton of web apps in use where I have worked to eliminate paper forms and processes, its been since the 1990's that I published software globally.  But that was freely distributable on aminet.net for the amiga and after 22 years has only received 1500 downloads.  The 2nd version - much improved - only got 89!  Ouch.

 

Amazingly, Aminet.net still exists and looks the same!  Here's a trip down memory lane for those of you who may remember ACE BASIC by David Benn for the Amiga in the 90's.  ACE was a pretty big deal because you could write applications that looked like they were written in C, but write them in BASIC - for free!  I recently reconnected with David Benn again - he's down under with Dave Jones. 

 

 

Since then, I evolved through C, Java, Java3D, C#, javascript, a Game Editor called DXStudio, and then discovered Unity at Unity3D.com.  They give away their game engine!  Digging around, I found that you could tweak it to send serial to the COM ports.  That's when it hit me - I can talk to an Arduino!  (or any other microcontroller).

 

So, that gave me the idea to make my game have a hidden feature to allow for "4D Gaming".  When you hit the "m" key during the pause menu, it will loop through each COM port so you can select your microcontroller.  From there, you can have your Arduino do all kinds of crazy things in the physical world like:

 

  • Smart Lights turn on, off, or cycle.
  • A knocking sound suddenly comes from another room.
  • Small vibrators clipped at strategic locations on your clothes to your shirt suddenly give you jump.
  • Water is misted out to your face.
  • A radio turns on to static or playing spooky sounds in another room.
  • A fan turns on and blows air at you.
  • Turn on one of the electric pulse zapper things they give people with chronic back pain.

 

So, you need code on both sides - the Unity Gaming Engine and the Arduino.

 

Here is a very basic script for Unity that you can attach to the default light source when opening a new Unity Project:

using UnityEngine;
using System.IO.Ports;
public class SeanSerialTesterScript : MonoBehaviour {
    SerialPort sp;
    float next_time; int ii = 0;
    // Use this for initialization
    void Start () {
        string the_com="";
        next_time = Time.time;
        
        foreach (string mysps in SerialPort.GetPortNames())
        {
            print(mysps);
            if (mysps != "COM1") { the_com = mysps; break; }
        }
        sp = new SerialPort("\\\\.\\" + the_com, 9600);
        if (!sp.IsOpen)
        {
            print("Opening " + the_com + ", baud 9600");
            sp.Open();
            sp.ReadTimeout = 100;
            sp.Handshake = Handshake.None;
            if (sp.IsOpen) { print("Open"); }
        }
    }
    // Update is called once per frame
    void Update() {
        if (Time.time > next_time) { 
            if (!sp.IsOpen)
            {
                sp.Open();
                print("opened sp");
            }
            if (sp.IsOpen)
            {
                print("Writing " + ii);
                sp.Write((ii.ToString()));
            }
            next_time = Time.time + 5;
            if (++ii > 9) ii = 0;
        }
    }
}

This outputs a number from 0 to 9 to a COM Port.

 

To catch the serial on the Arduino, you would do this code:

int inByte;
void setup() {
  // start serial port at 9600 bps:
  Serial.begin(9600);
  pinMode(LED_BUILTIN, OUTPUT); 
  digitalWrite(LED_BUILTIN, LOW);
}
void loop() {
  // if we get a valid byte, read analog ins:
  if (Serial.available() > 0) {
    // get incoming byte:
    inByte = Serial.read();
    if ((57-inByte)==0)
    { //after pressing m in pause screen and connected
      blink_it (10);
    }

    if ((57-inByte)==1) 
    {
      //Saw kid    
      blink_it(1);
    }
    if ((57-inByte)==2) 
    {
      //Lightening/Thunder
      blink_it(2);
    }
    if ((57-inByte)==3) 
    {
      //Spooky Noises
      blink_it(3);
    }
    if ((57-inByte)==4) 
    {
      //Sudden sound like the door being beat on
      blink_it(4);
    }
    if ((57-inByte)==5) 
    {
      //Chilling Ambient Sound
      blink_it(5);
    }
    if ((57-inByte)==6) 
    {
      //door creak
       blink_it(6);
    }
    if ((57-inByte)==7) 
    {
      //voices talking
       blink_it(7);
    }
    if ((57-inByte)==8) 
    {
      //drone woke kid
       blink_it(8);
    }
    if ((57-inByte)==9) 
    {
      //next chapter
       blink_it(9);
    }
  }
  delay(500);
}

void blink_it(int the_count){
  for (int ii=0;ii<the_count;ii++){
     digitalWrite(LED_BUILTIN, HIGH);
     delay(150);
     digitalWrite(LED_BUILTIN, LOW);
     delay(150);
  }        
}

 

 

Instead of doing the function "blink_it", you can replace it with code that drives pins to then hit transistors, relays, and even do web client requests if you have a WiFI shield or MKR1000.  This allows you to couple your Unity Game Engine Code to the Internet of Things - the sky is the limit!

 

In my game, its a jump scare game similar to Five Nights and Freddy's, but with a very original story.  It's still in Early Access, but is playable all the way through and the Maker Mode is enabled.  The comments in the code link the game events to when that serial command will trigger.  So, for example, you can have super bright LEDs flash behind you when Lightening/Thunder hits when receiving the serial command 2.

 

Here's the link to the early release game:

https://store.steampowered.com/app/905120/SonLightSleepwalker/

 

If you check it out, don't let him get into the light!

 

If you want to make your own game starting with the code above, go to Unity3d.com and download the Personal Edition. Feel free to comment here for tips to get started.

 

-Sean