Hi there,
I’m using a version of unity’s on screen joystick and have got it working how I would like, however the boundary for the joystick is a rectangle and I would prefer a Circle.
I’ve looked a bit on the internet and I have tried to implement it myself by trying to set up the boundary as a radius but have failed
I was wondering if anyone could point me in the right direction.
here is my code
using UnityEngine;
using System.Collections;
class AxisBoundary
{
public Vector2 min = Vector2.zero;
public Vector2 max = Vector2.zero;
}
public class JoystickScript : MonoBehaviour
{
static private Joystick[] joysticks;
static private bool enumeratedJoysticks = false;
static private float tapTimeDelta = 0.3f;
public bool touchPad;
public Rect touchZone;
public Vector2 deadZone = Vector2.zero;
public bool normalize = false;
public Vector2 position;
public int tapCount;
private int lastFingerId = -1;
private float tapTimeWindow;
private Vector2 fingerDownPos;
private float fingerDownTime;
private float firstDeltaTime = 0.5f;
private GUITexture gui;
private Rect defaultRect;
private AxisBoundary guiBoundary = new AxisBoundary();
private Vector2 guiTouchOffset;
private Vector2 guiCenter;
private float resRatio;
public GameObject globalScripts;
// Use this for initialization
void Start()
{
//Cache this texture
gui = gameObject.guiTexture;
globalScripts = GameObject.FindGameObjectWithTag("Global");
ScreenResolutionScript resScript = globalScripts.GetComponent<ScreenResolutionScript>();
resRatio = resScript.GetResRatio();
gui.pixelInset = new Rect((Screen.width / 6) - (200 * resRatio), (Screen.height / 2 ), (200 * resRatio), (200 * resRatio));
//Store the default rect for the gui
defaultRect = gui.pixelInset;
defaultRect.x += gameObject.transform.position.x * Screen.width;
defaultRect.y += gameObject.transform.position.y * Screen.height;
gameObject.transform.position = new Vector3(0.0f, 0.0f, gameObject.transform.position.z);
if (touchPad)
{
//If a texture has been assigned, then use the rect from the gui
if (gui.texture)
touchZone = defaultRect;
}
else
{
//corner of GUI
guiTouchOffset.x = defaultRect.width * 0.5f;
guiTouchOffset.y = defaultRect.height * 0.5f;
//cache center of GUI
guiCenter.x = defaultRect.x + guiTouchOffset.x;
guiCenter.y = defaultRect.y + guiTouchOffset.y;
//Build GUI boundary
guiBoundary.min.x = defaultRect.x - guiTouchOffset.x;
guiBoundary.max.x = defaultRect.x + guiTouchOffset.x;
guiBoundary.min.y = defaultRect.y - guiTouchOffset.y;
guiBoundary.max.y = defaultRect.y + guiTouchOffset.y;
}
}
void Disable()
{
gameObject.SetActive(false);
enumeratedJoysticks = false;
}
void ResetJoystick()
{
//Release the finger and reset joystick to default position
gui.pixelInset = defaultRect;
lastFingerId = -1;
position = Vector2.zero;
fingerDownPos = Vector2.zero;
if (touchPad)
{
gui.color = new Color (gui.color.r, gui.color.g, gui.color.b, 0.025f);
}
else
{
gui.color = new Color (gui.color.r, gui.color.g, gui.color.b, 0.2f);
}
}
bool IsFingerDown()
{
return (lastFingerId != -1);
}
void LatchedFinger(int fingerId)
{
//If another Joystick latched this finger, release it
if (lastFingerId == fingerId)
{
ResetJoystick();
}
}
// Update is called once per frame
void Update()
{
if (!enumeratedJoysticks)
{
//Collect all joysticks
joysticks = (Joystick[])FindObjectsOfType(typeof(Joystick));
enumeratedJoysticks = true;
}
int count = Input.touchCount;
//Adjust tap time window
if (tapTimeWindow > 0)
{
tapTimeWindow -= Time.deltaTime;
}
else
{
tapCount = 0;
}
if (count == 0)
ResetJoystick();
else
{
for (int i = 0; i < count; i++)
{
Touch touch = Input.GetTouch(i);
Vector2 guiTouchPos = touch.position - guiTouchOffset;
bool shouldLatchFinger = false;
if (touchPad)
{
if (touchZone.Contains(touch.position))
{
shouldLatchFinger = true;
}
}
else if (gui.HitTest(touch.position))
{
shouldLatchFinger = true;
}
//Latch finger if its a new touch
if (shouldLatchFinger && (lastFingerId == -1 || lastFingerId != touch.fingerId))
{
if (touchPad)
{
gui.color = new Color(gui.color.r, gui.color.g, gui.color.b, 0.15f);
lastFingerId = touch.fingerId;
fingerDownPos = touch.position;
fingerDownTime = Time.time;
}
lastFingerId = touch.fingerId;
//Count taps if they are within the time window
if (tapTimeWindow > 0)
{
tapCount++;
}
else
{
tapCount = 1;
tapTimeWindow = tapTimeDelta;
}
//Tell other joysticks finger is latched
foreach (Joystick j in joysticks)
{
if (j != this)
{
j.LatchedFinger(touch.fingerId);
}
}
}
if (lastFingerId == touch.fingerId)
{
if (touch.tapCount > tapCount)
{
tapCount = touch.tapCount;
}
if (touchPad)
{
//For touchpads set the position directly
position.x = Mathf.Clamp((touch.position.x - fingerDownPos.x) / (touchZone.width / 2), -1, 1);
position.y = Mathf.Clamp((touch.position.y - fingerDownPos.y) / (touchZone.height / 2), -1, 1);
}
else
{
//Change the position of the joystick GUI to match touch position
gui.pixelInset = new Rect(Mathf.Clamp(guiTouchPos.x, guiBoundary.min.x, guiBoundary.max.x), Mathf.Clamp(guiTouchPos.y, guiBoundary.min.y, guiBoundary.max.y), 200 * resRatio, 200 * resRatio);
}
if (touch.phase == TouchPhase.Ended || touch.phase == TouchPhase.Canceled)
{
ResetJoystick();
}
}
}
}
if (!touchPad)
{
//get a value between -1 and 1 based on joystick gui position
position.x = (gui.pixelInset.x + guiTouchOffset.x - guiCenter.x) / guiTouchOffset.x;
position.y = (gui.pixelInset.y + guiTouchOffset.y - guiCenter.y) / guiTouchOffset.y;
}
//Adjust for deadzone
float absoluteX = Mathf.Abs(position.x);
float absoluteY = Mathf.Abs(position.y);
if (absoluteX < deadZone.x)
{
//Report the joystick as being at the center
position.x = 0;
}
else if (normalize)
{
// Rescale the output after taking the dead zone into account
position.x = Mathf.Sign(position.x) * (absoluteX - deadZone.x) / (1 - deadZone.x);
}
if (absoluteY < deadZone.y)
{
// Report the joystick as being at the center if it is within the dead zone
position.y = 0;
}
else if (normalize)
{
// Rescale the output after taking the dead zone into account
position.y = Mathf.Sign(position.y) * (absoluteY - deadZone.y) / (1 - deadZone.y);
}
}
}