113 lines
2.7 KiB
C#
113 lines
2.7 KiB
C#
|
using UnityEngine;
|
||
|
using UnityEngine.EventSystems;
|
||
|
using UnityEngine.Events;
|
||
|
|
||
|
public class UIVirtualJoystick : MonoBehaviour, IPointerDownHandler, IDragHandler, IPointerUpHandler
|
||
|
{
|
||
|
[System.Serializable]
|
||
|
public class Event : UnityEvent<Vector2> { }
|
||
|
|
||
|
[Header("Rect References")]
|
||
|
public RectTransform containerRect;
|
||
|
public RectTransform handleRect;
|
||
|
|
||
|
[Header("Settings")]
|
||
|
public float joystickRange = 50f;
|
||
|
public float magnitudeMultiplier = 1f;
|
||
|
public bool invertXOutputValue;
|
||
|
public bool invertYOutputValue;
|
||
|
|
||
|
[Header("Output")]
|
||
|
public Event joystickOutputEvent;
|
||
|
|
||
|
void Start()
|
||
|
{
|
||
|
SetupHandle();
|
||
|
}
|
||
|
|
||
|
private void SetupHandle()
|
||
|
{
|
||
|
if(handleRect)
|
||
|
{
|
||
|
UpdateHandleRectPosition(Vector2.zero);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void OnPointerDown(PointerEventData eventData)
|
||
|
{
|
||
|
OnDrag(eventData);
|
||
|
}
|
||
|
|
||
|
public void OnDrag(PointerEventData eventData)
|
||
|
{
|
||
|
|
||
|
RectTransformUtility.ScreenPointToLocalPointInRectangle(containerRect, eventData.position, eventData.pressEventCamera, out Vector2 position);
|
||
|
|
||
|
position = ApplySizeDelta(position);
|
||
|
|
||
|
Vector2 clampedPosition = ClampValuesToMagnitude(position);
|
||
|
|
||
|
Vector2 outputPosition = ApplyInversionFilter(position);
|
||
|
|
||
|
OutputPointerEventValue(outputPosition * magnitudeMultiplier);
|
||
|
|
||
|
if(handleRect)
|
||
|
{
|
||
|
UpdateHandleRectPosition(clampedPosition * joystickRange);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
public void OnPointerUp(PointerEventData eventData)
|
||
|
{
|
||
|
OutputPointerEventValue(Vector2.zero);
|
||
|
|
||
|
if(handleRect)
|
||
|
{
|
||
|
UpdateHandleRectPosition(Vector2.zero);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void OutputPointerEventValue(Vector2 pointerPosition)
|
||
|
{
|
||
|
joystickOutputEvent.Invoke(pointerPosition);
|
||
|
}
|
||
|
|
||
|
private void UpdateHandleRectPosition(Vector2 newPosition)
|
||
|
{
|
||
|
handleRect.anchoredPosition = newPosition;
|
||
|
}
|
||
|
|
||
|
Vector2 ApplySizeDelta(Vector2 position)
|
||
|
{
|
||
|
float x = (position.x/containerRect.sizeDelta.x) * 2.5f;
|
||
|
float y = (position.y/containerRect.sizeDelta.y) * 2.5f;
|
||
|
return new Vector2(x, y);
|
||
|
}
|
||
|
|
||
|
Vector2 ClampValuesToMagnitude(Vector2 position)
|
||
|
{
|
||
|
return Vector2.ClampMagnitude(position, 1);
|
||
|
}
|
||
|
|
||
|
Vector2 ApplyInversionFilter(Vector2 position)
|
||
|
{
|
||
|
if(invertXOutputValue)
|
||
|
{
|
||
|
position.x = InvertValue(position.x);
|
||
|
}
|
||
|
|
||
|
if(invertYOutputValue)
|
||
|
{
|
||
|
position.y = InvertValue(position.y);
|
||
|
}
|
||
|
|
||
|
return position;
|
||
|
}
|
||
|
|
||
|
float InvertValue(float value)
|
||
|
{
|
||
|
return -value;
|
||
|
}
|
||
|
|
||
|
}
|