Moving mobile joystick

I imported the Standard Assets (Mobile), and I found to my surprise that the joystick prefab did not seem to work at all. So I tried writing my own script, but I didn’t really get anywhere with that either.

I want to be able to move the joysticks around to control a tank, but I’m not having much luck.

Also, I only want the joysticks to be able to move within a confined area, (the red squares in the image) like you see in most mobile games.

Anybody have any ideas on how I can either use the standard Joystick script correctly, or write my own?

I was thinking perhaps the Joystick script I imported wasn’t working because maybe it relies on actual touch, and mouse clicks don’t work? I noticed certain things such as Input.touchCount and Input.GetTouch() and I wonder if maybe that is the problem.

I’m not a noob, but I’ve never made a mobile game before, so if anybody can help me out here, thanks.

So this code is in C, and I got a converted version of Joystick.js to C# so maybe someone can help convert this code into js, but this is what I do.

So I have a game manager, and it has a public GameObject and I set to a prefab that has Joystick.js as a component (actually it’s called MPJoystick.cs for me because it’s converted). My game manager checks if a instance of joystick exists, if not it creates one.

Example:

    public GameObject joyStickPrefab;
    public static GameObject joyStickInstance;

        if (GameObject.Find(joyStickPrefab.name.ToString()) != null || GameObject.Find(joyStickPrefab.name.ToString()+"(Clone)") != null){
   			joyStickInstance = GameObject.Find(joyStickPrefab.name.ToString()+"(Clone)");
		}else{
			Instantiate(joyStickPrefab);
			joyStickInstance = GameObject.Find(joyStickPrefab.name.ToString()+"(Clone)");
		}

So now that I have my joystick visible, I can have my other scripts find them.
So in my case it’s a tower that needs to find it, so I do it doing this:

    private MPJoystick rotateJoyStick; //so declare my joystick var
    rotateJoyStick = GameObject.Find("JoyStick(Clone)").GetComponent<MPJoystick>(); //find my joystick

Now that I have my joystick, I can actually get values from it.

    float speed = 55.5f;
    Vector2 camRotation = Vector2.zero;
				
    camRotation = rotateJoyStick.position;
				
    camRotation.x *= speed * Time.deltaTime;
				
    // Rotate the character around world-y using x-axis of joystick
    turretObject.Rotate(0, camRotation.x, 0, Space.World );

So obviously I have this for rotating my tower in just the y axis.
Basically the script returns a value depending on where the joystick currently is. You can apply this simple example to get full movement and rotation.

Like stated before this is in C#, I don’t know how to convert this into js. If you want the c# version of the joystick script it can be found here using UnityEngine; /** * File: MPJoystick.cs * Author: Chris Danielson o - Pastebin.com

Only works when your on the device, doesnt work in scene/game window on the pc, only when exported

//you need two round texture one for boundary are which is bigger then 2nd texture which will //be touch and drag for controlling

public class JoyStick : MonoBehaviour {

public Texture areaTexture;
public Texture touchTexture;
public Vector2 joystickPosition = new Vector2( 135f,135f);
public Vector2 speed = new Vector2(2,100);
public float zoneRadius=100f;
public float touchSize = 30;
public float deadZone=20;
public float touchSizeCoef=0;
protected Vector2 joystickAxis;
protected Vector2 joystickValue;
public Vector2 joyTouch;
private Vector2 _joystickCenter;
[SerializeField]
private Vector2 _smoothing = new Vector2(20f,20f);
public Vector2 Smoothing 
{
    get {
       return this._smoothing;
    }
    set {
       _smoothing = value;
       if (_smoothing.x<0.1f){
         _smoothing.x=0.1f;
       }
       if (_smoothing.y<0.1){
         _smoothing.y=0.1f;   
       }
    }
}
private int _joystickIndex=-1;
private bool _enaReset;
private bool _enaZoom;
 
void Start () 
{
    _joystickCenter = joystickPosition;
    _enaReset=false;
}

void Update () 
{
       if (Application.platform == RuntimePlatform.IPhonePlayer || Application.platform == RuntimePlatform.Android) 
		{
	       foreach (Touch touch in Input.touches)
	       {
	         if (touch.phase == TouchPhase.Ended || touch.phase == TouchPhase.Canceled) 
			 {
	          	if (_joystickIndex==touch.fingerId){
	              _joystickIndex=-1;
	              _enaReset=true;
	          	}
	         }
	 
	         if(_joystickIndex==touch.fingerId)
			 {
	          	OnTouchDown(touch.position);
	         }
	         if (touch.phase == TouchPhase.Began)
			 {
	         	 if (((Vector2)touch.position - _joystickCenter).sqrMagnitude < Mathf.Pow((zoneRadius+touchSizeCoef/2),2))
			  	  {
	              	_joystickIndex = touch.fingerId;
	         	 }
	         }
       }
 
       UpdateJoystick();
       if(_enaReset)
		{
        	 ResetJoystick();
       	}
    }
	else
	{ 
       if (Input.GetButtonUp ("Fire1")) 	
		{
         	_joystickIndex=-1;
         	_enaReset=true;
       }
       if(_joystickIndex==1)
		{
         	OnTouchDown(Input.mousePosition);
        }
        if (Input.GetButtonDown ("Fire1") ) 
		{
	         if (((Vector2)Input.mousePosition - _joystickCenter).sqrMagnitude <Mathf.Pow( (zoneRadius+touchSizeCoef/2),2))
			 {
	         	 _joystickIndex = 1;
	 
	         }
	 
       }
       if(_enaReset)
		{
         	ResetJoystick();
       	}
 
       UpdateJoystick();
 
    }
 
}
 



private void UpdateJoystick()
	{ 
       if (joyTouch.sqrMagnitude>deadZone*deadZone)
		{
 
         joystickAxis = Vector2.zero;
      	 if (Mathf.Abs(joyTouch.x)> deadZone)
		  {
         	 joystickAxis = new Vector2( (joyTouch.x -(deadZone*Mathf.Sign(joyTouch.x)))/(zoneRadius-touchSizeCoef-deadZone),joystickAxis.y);
 
          }
		 else
		 {
          	joystickAxis = new Vector2( joyTouch.x /(zoneRadius-touchSizeCoef),joystickAxis.y);
 
         }
       if (Mathf.Abs(joyTouch.y)> deadZone)
		{
 			joystickAxis = new Vector2( joystickAxis.x,(joyTouch.y-(deadZone*Mathf.Sign(joyTouch.y)))/(zoneRadius-touchSizeCoef-deadZone));
        }
		else{
          joystickAxis = new Vector2( joystickAxis.x,joyTouch.y/(zoneRadius-touchSizeCoef));  
         }
 
       }
       else{
         joystickAxis = new Vector2(0,0);
       }
    Vector2 realvalue = new Vector2(  speed.x*joystickAxis.x,speed.y*joystickAxis.y);
    joystickValue=realvalue;
    print(realvalue);
 
}

void OnTouchDown(Vector2 position)
	{
       joyTouch  = new Vector2( position.x, position.y) - _joystickCenter;
       if ((joyTouch/(zoneRadius-touchSizeCoef)).sqrMagnitude > 1)
		{
         joyTouch.Normalize();
         joyTouch *= zoneRadius-touchSizeCoef;
       }
    //print(joyTouch);
 }


private void ResetJoystick()
{
    if (joyTouch.sqrMagnitude>0.1)
	{
       joyTouch = new Vector2( joyTouch.x - joyTouch.x*_smoothing.x*Time.deltaTime, joyTouch.y - joyTouch.y*_smoothing.y*Time.deltaTime);    
    }
    else{
       joyTouch = Vector2.zero;
       _enaReset=false;
    }
}
void OnGUI()
{
       GUI.DrawTexture( new Rect(_joystickCenter.x -zoneRadius ,Screen.height- _joystickCenter.y-zoneRadius,zoneRadius*2,zoneRadius*2), areaTexture,ScaleMode.ScaleToFit,true);
       GUI.DrawTexture( new Rect(_joystickCenter.x+(joyTouch.x -touchSize) ,Screen.height-_joystickCenter.y-(joyTouch.y+touchSize),touchSize*2,touchSize*2), touchTexture,ScaleMode.ScaleToFit,true);
}

}

This is the way I make it: drag the FPSController prefab (Mobile) to the scene and VERY IMPORTANT: don’t move it, just let it wherever it is. Then create an empty object and rename it to PlayerSpawn(1), place this object where you want the player to be spawned and that’s all, when you hit play you can move the player properly with unity remote. Hope it helps

(1) this is because, if you open the FirstPersonControl.js, you can see that in the Start() function it looks for an object called PlayerSpawn and moves the player to it

You could use joystick.js. It is a pre-written script by unity. You can import it in Assets|Standard Assets(Mobile) and then select Joystick.js from the window.