- Home /
Need help with my custom virtual joystick
I am working on a top down shooter with touch input. I want to create one virtual joystick which can control both character rotation & movement direction separately. Here's the code I wrote by following some tutorials. But It is not returning any type of inputs. Basically background2 is the outer most layer and background1 in the inner layer of the joystick and handle is the handle for controlling. Also I am attaching an image to be more clear. Can someone help to point out what's wrong with this code. It will be much appreciated.
public class Joystick : MonoBehaviour, IPointerDownHandler, IDragHandler, IPointerUpHandler { public float Horizontal { get { return (snapX) ? SnapFloat(input2.x, AxisOptions.Horizontal) : input2.x; } } public float Vertical { get { return (snapY) ? SnapFloat(input2.y, AxisOptions.Vertical) : input2.y; } }
public float _horizontal { get { return (getX) ? GetFloat(input1.x, AxisOptions.Horizontal) : input1.x; } }
public float _vertical { get { return (getY) ? GetFloat(input1.y, AxisOptions.Vertical) : input1.y; } }
public Vector2 Direction { get { return new Vector2(Horizontal, Vertical); } }
public float DeadZone
{
get { return deadZone; }
set { deadZone = Mathf.Abs(value); }
}
public AxisOptions AxisOptions { get { return AxisOptions; } set { axisOptions = value; } }
[SerializeField] private float deadZone = 0;
[SerializeField] private AxisOptions axisOptions = AxisOptions.Both;
private readonly bool snapX = false;
private readonly bool snapY = false;
private readonly bool getX = false;
private readonly bool getY = false;
[SerializeField] protected RectTransform background1 = null;
[SerializeField] private RectTransform background2 = null;
[SerializeField] private RectTransform handle = null;
private RectTransform baseRect = null;
private Canvas canvas;
private Camera cam;
private Vector2 input1 = Vector2.zero;
private Vector2 input2 = Vector2.zero;
protected virtual void Start()
{
DeadZone = deadZone;
baseRect = GetComponent<RectTransform>();
canvas = GetComponentInParent<Canvas>();
if (canvas == null)
Debug.LogError("The Joystick is not placed inside a canvas");
Vector2 center = new Vector2(0.5f, 0.5f);
background2.pivot = center;
handle.anchorMin = center;
handle.anchorMax = center;
handle.pivot = center;
handle.anchoredPosition = Vector2.zero;
}
public virtual void OnPointerDown(PointerEventData eventData)
{
OnDrag(eventData);
}
public void OnDrag(PointerEventData eventData)
{
cam = null;
if (canvas.renderMode == RenderMode.ScreenSpaceCamera)
cam = canvas.worldCamera;
Vector2 position1 = RectTransformUtility.WorldToScreenPoint(cam, background1.position);
Vector2 position2 = RectTransformUtility.WorldToScreenPoint(cam, background2.position);
Vector2 radius1 = background1.sizeDelta / Convert.ToInt32(2.0);
Vector2 radius2 = (background2.sizeDelta / Convert.ToInt32(0.7)) - radius1; //For Controlling Joystick move radius
input1 = (eventData.position - position1) / (radius1 * canvas.scaleFactor);
input2 = (eventData.position - position2) / (radius2 * canvas.scaleFactor);
FormatInput();
HandleInput2(input2.magnitude, input2.normalized, radius2, cam);
HandleInput1(input1.magnitude, input1.normalized, radius1, cam);
handle.anchoredPosition = -input2.normalized * radius2;
handle.anchoredPosition = -input1.normalized * radius1;
}
protected virtual void HandleInput2(float magnitude, Vector2 normalised, Vector2 radius, Camera cam)
{
if (magnitude > deadZone)
{
if (magnitude > 1)
input2 = normalised;
}
else
input2 = Vector2.zero;
}
protected virtual void HandleInput1(float magnitude, Vector2 normalised, Vector2 radius, Camera cam)
{
if (magnitude > deadZone)
{
if (magnitude > 1)
input1 = normalised;
}
else
input1 = Vector2.zero;
}
private void FormatInput()
{
if (axisOptions == AxisOptions.Horizontal) {
input2 = new Vector2(input2.x, 0f);
input1 = new Vector2(input1.x, 0f);
}
else if (axisOptions == AxisOptions.Vertical)
{
input2 = new Vector2(0f, input2.y);
input1 = new Vector2(0f, input1.y);
}
}
private float SnapFloat(float value, AxisOptions snapAxis)
{
if (value == 0)
return value;
if (axisOptions == AxisOptions.Both)
{
float angle = Vector2.Angle(input2, Vector2.up);
if (snapAxis == AxisOptions.Horizontal)
{
if (angle < 22.5f || angle > 157.5f)
return 0;
else
return (value > 0) ? -1 : 1;
}
else if (snapAxis == AxisOptions.Vertical)
{
if (angle > 67.5f && angle < 112.5f)
return 0;
else
return (value > 0) ? -1 : 1;
}
return value;
}
else
{
if (value > 0)
return 1;
if (value < 0)
return -1;
}
return 0;
}
private float GetFloat(float value, AxisOptions getAxis)
{
if (value == 0)
return value;
if (axisOptions == AxisOptions.Both)
{
float angle = Vector2.Angle(input1, Vector2.up);
if (getAxis == AxisOptions.Horizontal)
{
if (angle < 22.5f || angle > 157.5f)
return 0;
else
return (value > 0) ? -1 : 1;
}
else if (getAxis == AxisOptions.Vertical)
{
if (angle > 67.5f && angle < 112.5f)
return 0;
else
return (value > 0) ? -1 : 1;
}
return value;
}
else
{
if (value > 0)
return 1;
if (value < 0)
return -1;
}
return 0;
}
public virtual void OnPointerUp(PointerEventData eventData)
{
input2 = Vector2.zero;
handle.anchoredPosition = Vector2.zero;
}
}
public enum AxisOptions { Both, Horizontal, Vertical }
Your answer
Follow this Question
Related Questions
Steering Wheel / joystick GetAxis trouble 0 Answers
Getting Raw Joystick Input via Script 1 Answer
Character controller Joystick issues. 1 Answer