As a final project in a course in computer technology, we combined Unity with the Arduino platform (arduino.cc/) to control a classic game with a labyrinth and a ball using an accelerometer. Based on the movement of our control, the labyrinth moves in the game. The goal is simply to get the ball to the end of the labyrinth by tilting the platform. If the ball falls into one of the holes – the game restarts. Here is a video demonstration: http://vimeo.com/12288710 We got a lot of help from this forum (especially from here: http://forum.unity3d.com/viewtopic.php?p=294657#294657 ) so we wanted to give something back to you. Credits: Andreas Huck, Jens Börjesson ( http://www.jensborjesson.se ) Alexander Gryth ( http://agryth.com/ ) Arduino code: About: This code picks up the values the Arduino card gets from the accelerometer and transforms them into readable data. Gets the values from the x- and y-axis up to 90° and -90°. It is also able to read the z-axis to set jump to true or false. Code (csharp): /************************************************************************* CREDITS: Andreas Huck, Jens Börjesson Alexander Gryth *************************************************************************/ /* Hardware needed: Arduino card and an accelerometer. This code picks up the values the Arduino card gets from the accelerometer and transforms them into readable data */ // variables to the analog ports that are used on the arduino card int X = 0; int Y = 1; int Z = 2; int calX = 18; int calY = 14; int zaxis; // variable that checks the Z-axis value. This is to determine if there is a jump or not void setup() { Serial.begin(9600); // start serial communication } void loop(){ Serial.flush(); // Empty the memory each time in the loop // The following adjusts the x- and y-values and prints them. These are selected by tweaking and comparing the values with the movement of the arduino card. You may need to change these to suit your accelerometer. Serial.print(map(analogRead(X),278,417,-90,90)+calX); Serial.print(","); Serial.print(map(analogRead(Y),278,417,-90,90)+calY); Serial.print(","); zaxis = map(analogRead(Z),270,402,0,1000); // adjusts the z-value // if the z-axis indicates a high value – there is a "jump". This results in a boolean (1 or 0) if(zaxis < 800 || zaxis > 1200){Serial.print(1);} else {Serial.print(0);} Serial.println(); delay(10); // delay for each turn in the loop. } C# code: About: C# code that connects Unity with the Arduino card and moves the in-game platform based on the movement of the card. The Arduino card is also programmed to understand when the user jumps with the control. This is though not implemented fully in this version. Instead, the text "Jump" is written on the screen to demonstrate that it works. Code (csharp): /************************************************************************* CREDITS: Andreas Huck, Jens Börjesson Alexander Gryth *************************************************************************/ /* C# code that connects Unity with the Arduino card and moves the in-game platform based on the movement of the card. The Arduino card is also programmed to understand when the user jumps with the control. This is though not implemented fully in this version. Instead, the text "Jump" is written on the screen to demonstrate that it works. */ using UnityEngine; using System.Collections; using System.IO.Ports; public class styrScript : MonoBehaviour { public static string jump; // String variable that displays on the screen SerialPort stream = new SerialPort("COM4", 9600); // Defines the serial port and the speed void Start () { stream.Open(); // Opens the serial port } void Update () { string value = stream.ReadLine(); // Reads the data from the arduino card string[] vec3 = value.Split(','); // Splits the data from the arduino card so that we have values to work with // Rotation. Makes the platform moves smoothly towards a target (the value from the arduino card) target = Quaternion.Euler(float.Parse(vec3[1]),0,float.Parse(vec3[0])); transform.rotation = Quaternion.Slerp(transform.rotation, target, Time.deltaTime * 2.0f); if(float.Parse(vec3[2]) == 1){// Checks if the z-value is 1 (true) and then writes "Jump" on the screen print("Jump"); jump = "Jump"; } else if(float.Parse(vec3[2]) == 0) { // If the z-value is 0 (false), nothing happens on the screen jump = ""; } } void OnGUI() { GUI.Label(new Rect(170, 570, 60, 20), jump); // Creates the placeholder on the screen for the text when "jumping" } }
^_^ Glad my post was useful. You didn't get rid of the lag though. I don't remember what I did, but I had my lag down really low. Maybe it was the lerp duration?... I think I also increased the delay in the arduino.... (I would check, but I'm in the UK for a month right now and don't have any of my files on hand.)
Thanks for sharing your code. I tried using some of it but I get this error message when trying to open the serial port in Unity: Did something similar happen to you at first?
You are probably using another serial port. Which one is hard to tell but try to change the number after "COM" Code (csharp): SerialPort stream = new SerialPort("COM4", 9600);
Thanks for your quick reply! I did change it to my proper COM port (COM3 in my case) and it still was not working. I have to say, I'm not very good with C# and that is mostly why I'm stuck. It seems that the System.IO.Ports is not implemented in JavaScript. What I don't understand is how come the basic serial open command is not working. Maybe more/less arguments?
Well, it is hard to tell without see the whole solution but there are a couple of things that might cause your problem. Are you using a C#-file for the code in Unity? Are you using a PC? You need different code if you have a Mac. If you still get error messages – cut the file down to only the communication with the serial port. You could get some compile errors from the rest of the code that unity think is from the port.
Yes, it's a C# file on a PC. I cut it down to just opening the serial port and I still get the error. I am also running the latest version of Unity so it should come with a recen version of Mono. I will try some other things when I get to work. Thanks for your help so far! I'll paste my code when I get there.
Solved! This is kind of embarrassing, but the problem was that I had the Arduino Serial Monitor open when I tried to run the program. Once I closed it everything started working. Again, thank you so much for your help!
What code would I need to get this working on a mac? I'm new to Unity, but would like to connect Arduino to it to make a custom game controller.
I do not know, we did not have the time to look into that during the project. Please share it with you if you find out how!
I'm not sure on Mac either. I don't use macs at all, so I haven't the foggiest. My goal with the first script was just for c# (as I knew it had the libraries capable of doing serial connections from the .net framework) It may work right if you have mono installed though. I'm not sure how C# works with mono and if you have to include different libraries or not. Sorry I can't be of much use on the subject.
Here is an example for Mac using Unity and Arduino: http://www.sundh.com/blog/2012/05/unity-processing-arduino/
Anybody still working on this? I've just been hacking the new Arduino Esplora, a board shaped like a game controller, which includes a joystick, buttons, and accelerometer. At the moment only available at Radio Shack. What a world. And I've been hitting my head against that serial problem on the Mac. So I wrote a Processing sketch that sends all the board data as OSC. That sketch is here: https://s3.amazonaws.com/domebase/Esplora/ProcessingEsploraOSC2.zip (You'll have to load a sketch from the Arduino site called Esplora Remote into the board itself). I tested it with a Unity project and it works well. But I'll work some more on that project before posting it here. Anybody interested? Have any news on the Mac serial bug? Any new Arduino/Unity chatter?
I can't try anything out right now, but I do know you can send OSC directly into Unity on Mac. This library has a Unity project that does this: http://opentsps.com/ I remember I had to check the ' legacy' option in opentsps and set up the correct port number, but it worked great and I was able to use one computer for sensing and the other to run the game.
I am trying to connect the arduino with unity but unity doesnt seem to be picking up any input from the arduino board. I am basically getting speed as an input from a potentiometer(arduino) to move a ball(unity). But the ball doesnt move at all. I have uploaded the script. Could you maybe point out what can be wrong? Thanks..
Really cool, I made a Leap motion version: https://www.udemy.com/labyrinth-game-in-unity-3d-with-leap-support/learn/#/
I am trying to upload the C# code on unity, but it is coming up with error that "target" does not exist in the current context. How do i define it that it can exist?