I am really curious if it is possible to change the joystick texture (default character controller in mobile assets) from the current D-pad behavior - where the joystick is moving in all directions and returns to its initial point on release - to a rotation mode where the texture would rotate CW or CCW. An alternative might be to have 2 separate joysticks one for horizontal input and one for vertical input.
I fiddled about this for a while and then went on to ask for help from a good programmer and friend and we ended up with something rather nice. No need to actually modify the joystick code; a workaround to this was to draw a texture on top of the area where the joystick is and provide the visual feedback I wanted for the game (in this case, a ship helm) by rotating it with a few finish touches - when released the helm texture will auto-rotate back to initial angle, throttle indicator and so on.
using UnityEngine;
using System.Collections;
public class Steering_Wheel : MonoBehaviour
{
public GUITexture guiItem;
public Rect steerBounds = new Rect(0,0,100,100);
public Texture steerTex;
public float steerAngle = 0.0f;
public float steerDeadZone = 10.0f;
public float steerSen = 1.0f;
public float steerPower = 0.1f;
public float steerMin = -200.0f;
public float steerMax = 200.0f;
public Rect throttleBounds = new Rect(0,0,10,100);
public float throttleSize = 15.0f;
public Texture throttleTex;
public float throttlePos = 0.0f;
public float throttleDeadZone = 10.0f;
public float throttleSen = 1.0f;
public float throttlePower = 0.1f;
public float throttleMin = -1.0f;
public float throttleMax = 1.0f;
private bool isTouching;
private float oldTouchX, oldTouchY;
private float origTouchX, origTouchY;
private Rect dispThrottle;
// Use this for initialization
void Start ()
{
isTouching = false;
dispThrottle = new Rect(throttleBounds);
dispThrottle.height = throttleSize;
}
// Update is called once per frame
void Update ()
{
if (Input.GetMouseButton(0))
{
float mx = Input.mousePosition.x;
float my = Screen.height - Input.mousePosition.y;
if (!isTouching)
{
if (steerBounds.Contains(new Vector2(mx, my)))
{
isTouching = true;
oldTouchX = mx;
oldTouchY = my;
origTouchX = mx;
origTouchY = my;
}
}
else
{
float dx = mx - oldTouchX;
float dy = my - oldTouchY;
if (Mathf.Abs(mx - origTouchX) > steerDeadZone)
{
steerAngle += dx * steerSen;
}
if (Mathf.Abs(my - origTouchY) > throttleDeadZone)
{
throttlePos += dy * throttleSen;
}
oldTouchX = mx;
oldTouchY = my;
}
}
else
{
isTouching = false;
steerAngle = steerAngle * (1.0f - steerPower);
if (Mathf.Abs(steerAngle) < 0.1f)
steerAngle = 0.0f;
throttlePos = throttlePos * (1.0f - throttlePower);
if (Mathf.Abs(throttlePos) < 0.05f)
throttlePos = 0.0f;
}
if (steerAngle < steerMin)
steerAngle = steerMin;
if (steerAngle > steerMax)
steerAngle = steerMax;
if (throttlePos < throttleMin)
throttlePos = throttleMin;
if (throttlePos > throttleMax)
throttlePos = throttleMax;
}
void OnGUI()
{
Matrix4x4 oldMat= GUI.matrix;
Rect r = steerBounds;
GUIUtility.RotateAroundPivot(steerAngle, new Vector2(r.x + r.width/2.0f, r.y + r.height/2.0f));
GUI.DrawTexture(r, steerTex);
GUI.matrix = oldMat;
float h = (throttleBounds.height - throttleSize) / 2.0f;
float py = h * throttlePos;
r = dispThrottle;
r.y = throttleBounds.y + throttleBounds.height/2.0f + py - throttleSize;
GUI.DrawTexture(r, throttleTex);
}
}