Unity 3D iOS apps with JOY(STICK)
In the last tutorial , we used a joystick to control an iOS space shooter game, I hope you had fun with it. This time around, we are going to use joystick to control a 3D iOS App made in Unity3D. Here is a demo video of the final product.
Assumptions
- You are somewhat familiar with Unity's GUI. No previously coding experiences in Unity is assumed.
- You have heard about Arduino. No coding experience in Arduino required.
- Basic Understanding of Objective-c & iOS application development
The Big Picture
The idea of this tutorial is to use an Arduino Joystick to wirelessly control a character in Unity 3D and run the app on iPhone. In order to accomplish this, there are several things we need:
- Arduino: get joystick data and button data and broadcast it with UDP protocol.
- Xcode data receiving interface: Our Open Source RedButton API provides a delegate method to easily retrieve Joystick data broadcasted from the Arduino joystick.
- Unity Plugins for iOS: Once our iPhone receives the Joystick data, it need to send data from our Objective-c code to Unity code, so the joystick position can control the character in Unity.
- Unity 3D application: A character in Unity that can move forward, backward, left and right in response to our Joystick data.
Arduino
This part is exactly the same as the Hardware, Arduino program section in the previous blog You can upload the same code (Under Arduino folder) to your arduino board.
Xcode data receiving interface
The RedButton API is used to receiving Joystick data from Joystick. This is an API we developed and used in our [iOS Games with Joy(stick)] tutorial. Follow the RedButton API Introduction section in the blog if you haven't used it before.
Unity Plugins for iOS
One of the main issues you may ask is how do you send Joystick data to Unity. Luckily for you, Unity describes a way to do just that in their official documentation. You can take a close look at Unity's build native code plugins for the iOS platform [here]. or you can follow the instruction below.
Three steps from the official documentations:
Define your extern method in the C# file like follows:
[DllImport ("__Internal")] private static extern float FooPluginFunction ();Set the editor to the iOS build target
- Add your native code source files to the "Classes" folder
In the RedButton API, we have defined several delegate methods to receive data from Arduino. Now we just need to add a layer on top of RedButtonAPI layer so it can send messages to Unity. Let's call this transition layer SendToUnity. The SendToUnity.h and SendToUnity.mm was defined for this purpose. SendToUnity Class is the transition layer: it sends data received from RedButtonAPI class to Unity.
Let us apply those steps in this project:
Here we use Joystick X axis data as an example to go through each line of code in both the Objective-C and Unity code. The Joystick Y axis data and the A,B,C buttons is similar to Joystick X axis data. The whole file of SendToUnity.h & SendToUnity.mm file can be downloaded from [here](Under Xcode file folder)
In Xcode, SendToUnity.h file add a float property x to save joystick x axis data.
#import <UIKit/UIKit.h> #import "RedButtonAPI.h" @interface SendToUnity : NSObject<RedButtonAPIDelegate> @property(nonatomic) float x; @endIn SendToUnity.mm file
#import "SendToUnity.h" #define kJoystickCenterX 50 @implementation SendToUnity @synthesize x; -(id)init{ if (self = [super init]) { RedButtonAPI *redButton = [[RedButtonAPI alloc] init]; redButton.delegate = self; } return self; } - (void)joystickDataofX:(NSString *)xData Y:(NSString *)yData{ self.x = [xData intValue]; } @end static SendToUnity *tmp = nil; extern "C" { float RedButtonJoystickX(){ if (tmp == nil) { tmp = [[SendToUnity alloc] init]; } return (tmp.x-kJoystickCenterX)/kJoystickCenterX; } }
The SendToUnity.mm file defined a constant to store Joystick's center value. In its init method, we instantiate a RedButtonAPI object and set its delegate to SendToUnity.
Then, joystickDataofX:Y: delegate is used to receive the axis data. The last extern "c" part is necessary in order for Unity to call and get the return value.
Note that we use (tmp.x-kJoystickCenterX)/kJoystickCenterX equation to normalize the return value to a range between -1 to 1.
3.In Unity, if you want to call RedButtonJoystickX methods, you need to defined it in the c# file like so:
[DllImport ("__Internal")]
private static extern float RedButtonJoystickX();
The method can then be called as if it is an internal Unity method:
float fA = RedButtonJoystickX();
Unity 3D application
OK. Now the issue about send data from Joystick to Unity is solved, the next step is to build the Unity app.
In this app, we reused some source files from Unity's official tutorial called Penelope. Speaking of which, If you are going to create a third person game in Unity, Penelope tutorial is really a MUST read.
Download and import Resources file from [Penelope tutorial].
Create a new project named NewPenelope
Create a Plane via Unity->GameObject->Create Other->Plane. Drag & Drop the grass1TGA file onto Plane to set the grass ground. Set Position to 0,0,0 & Scale to 10,10,10 as the image below.
Create a Directional light via Unity->GameObject->Create Other->Directional light. Make its position 0,0,0 and set its Rotation to 45,0,0
Create Player Object via Unity->GameObject->Create Empty. Rename it to Player. In the Project Objects folder, choose penelopeFBX. Drag & Drop it onto Player to make it as Player's child object.
Now comes the fun part. Let's add some scripts to our Player object.
(1) Character Controller script
Select Player in the Hierarchy, then using Component->Physics->Character Controller set the parameters as indicated in the screenshot below.
(2) Animation Controller script
For this one, use the same script in Penelope tutorial named AnimationController.js. This script will be attached to the Player object. This script plays the appropriate animations for Penelope and blends the animations. It also uses the character’s movement direction to determine which animation should be played.
(3) Move script
This is the main script we are using to control the Character.
using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;
public class Move : MonoBehaviour {
//character variable stores the player
public CharacterController character;
//defined all objective-c side method as extern data
[DllImport ("__Internal")]
private static extern float RedButtonJoystickX();
[DllImport ("__Internal")]
private static extern float RedButtonJoystickY();
[DllImport ("__Internal")]
private static extern bool RedButtonIsButtonAPressed();
[DllImport ("__Internal")]
private static extern bool RedButtonIsButtonBPressed();
void Start () {
Screen.orientation = ScreenOrientation.LandscapeLeft;
}
void Update () {
float fA = RedButtonJoystickX();
float fB = RedButtonJoystickY();
bool bC = RedButtonIsButtonAPressed();
//use the Joystick X value to control Unity's X axis
//use the Joystick Y value to control Unity's Z axis
character.Move(new Vector3(fA,0,fB));
//send a log output if button A is pressed.
if(bC)
{
Debug.Log(bC.ToString());
}
}
}
7.Add script to Camera
Add FollowTransform.js to Camera. This script makes camera follow the player when the player is moving to a different position. Here is the FollowTransform.js code:
var targetTransform : Transform; // Transform to follow
var faceForward : boolean = false; // Match forward vector?
private var thisTransform : Transform;
function Start()
{
thisTransform = transform;
}
function Update ()
{
thisTransform.position.x = targetTransform.position.x;
thisTransform.position.y = targetTransform.position.y+2;
thisTransform.position.z = targetTransform.position.z-3.5;
if ( faceForward )
thisTransform.forward = targetTransform.forward;
}
This script sets the camera x as player x, camera y as player y + 2, camera z as player z - 3.5 so that the relative position of camera and player are always the same.
8.Make all connections IMPORTANT
In Camera's Follow Transform (Script), set Player as target like this:
In Player's Animation Controller, Character Controller, Move (Script)
Set all the connection and values as shown below:
Summary: Steps to run the whole project
- Upload theArduino program to the Arduino board, make sure your connect Joystick Shield (top), WiFi Shield (middle), Arduino (bottom) in the right order and make sure the Red LED light is on (WiFi network is created)
- In your iPhone WiFi Settings select RedButtonAPI
- In Unity, click Build Settings, switch platform to iOS
- Click Build & run. It will open Xcode for you.
- In Xcode, select Run on device.
- That's it. It's time to use joystick to control your penelope.
All files for this project can be found from [GitHub]
I hope you found this tutorial useful.
Zeng Le |
2 Comments |
Unity3D,
arduino,
iOS in
idevblogaday 
































