using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using UnityEngine.EventSystems;
public class InputJoystick : MonoBehaviour
{
//搖桿根節點
[SerializeField] RectTransform joystickRoot;
//搖桿節點
[SerializeField] RectTransform joystickNode;
//搖桿方向節點
[SerializeField] RectTransform joystickDirection;
//搖桿半徑
[SerializeField] int joystickRadius = 200;
//擡手搖桿復位速度
[SerializeField, Range(0.01f, 1)] float revertPositionSpeed = 0.75f;
//單擊判定時間範圍
[SerializeField] float tapDuration = 0.1f;
//搖桿事件回調
public static Action OnJoystickMoveStart;
public static Action<Vector2> OnJoystickMoving;
public static Action OnJoystickMoveEnd;
public static Action OnJoystickTap;
//屏幕寬高
private int screenWidth = Screen.width;
private int screenHeight = Screen.height;
//搖桿默認位置
private Vector3 joystickDefaultPos;
//按下時搖桿中心位置
private Vector3 curJoystickOrigin;
//按下時搖桿方向
private Vector3 curJoystickDirection;
private bool isInputing = false; //是否按下搖桿
private bool needToRevertRoot = false; //根節點是否需要回位
private bool needToRevertNode = false; //遙感節點是否需要回位
private bool isReadyToTap = false; //是否判定單擊
private bool isActived = true; //是否激活搖桿
//搖桿按下時間
private float startInputTime;
private void Awake()
{
joystickDefaultPos = joystickRoot.anchoredPosition;
}
private void Start()
{
joystickDirection.gameObject.SetActive(false);
}
private void Update()
{
if (!isActived)
return;
if (Input.GetMouseButtonDown(0))
{
if (IsRaycastUI())
return;
OnInputStart(Input.mousePosition);
isInputing = true;
}
else if (Input.GetMouseButton(0))
{
if (isInputing)
OnInputIng(Input.mousePosition);
}
else if (Input.GetMouseButtonUp(0))
{
if (isInputing)
{
OnInputEnd(Input.mousePosition);
isInputing = false;
}
}
else if (!isInputing)
{
if (needToRevertRoot)
{
RevertJoystickRootPos();
}
if (needToRevertNode)
{
RevertJoystickNodePos();
}
}
}
private bool IsRaycastUI()
{
//鼠標點擊事件
return (EventSystem.current != null && EventSystem.current.IsPointerOverGameObject());
}
//激活/取消激活 搖桿
public void ActiveJoystick(bool active)
{
if (isActived == active)
return;
isActived = active;
if (!isActived)
{
if (isInputing)
OnJoystickMoveEnd?.Invoke();
}
joystickRoot.gameObject.SetActive(active);
joystickRoot.anchoredPosition = joystickDefaultPos;
joystickNode.localPosition = Vector3.zero;
}
#region --- 輸入回調 ---
private void OnInputStart(Vector3 point)
{
curJoystickOrigin = point;
startInputTime = Time.unscaledTime;
isReadyToTap = true;
Vector3 joystickPos = Vector3.zero;
joystickPos.x = -0.5f * screenWidth + point.x;
joystickPos.y = -0.5f * screenHeight + point.y;
joystickRoot.anchoredPosition = joystickPos;
joystickNode.localPosition = Vector3.zero;
joystickDirection.gameObject.SetActive(true);
OnJoystickMoveStart?.Invoke();
}
float tempLength;
private void OnInputIng(Vector3 point)
{
tempLength = (point - curJoystickOrigin).magnitude;
if (tempLength < 0.01f)
{
curJoystickDirection = Vector3.zero;
OnJoystickMoving?.Invoke(curJoystickDirection);
if (isReadyToTap)
{
if (Time.unscaledTime - startInputTime >= tapDuration)
{
isReadyToTap = false;
}
}
}
else if (tempLength <= joystickRadius)
{
curJoystickDirection = (point - curJoystickOrigin).normalized * tempLength / joystickRadius;
isReadyToTap = false;
}
else
{
curJoystickDirection = (point - curJoystickOrigin).normalized;
isReadyToTap = false;
}
joystickNode.localPosition = curJoystickDirection * joystickRadius;
if (curJoystickDirection == Vector3.zero)
joystickDirection.up = Vector3.up;
else
joystickDirection.up = curJoystickDirection;
OnJoystickMoving?.Invoke(curJoystickDirection);
}
private void OnInputEnd(Vector3 point)
{
curJoystickOrigin = joystickDefaultPos;
needToRevertRoot = true;
needToRevertNode = true;
joystickDirection.gameObject.SetActive(false);
if (isReadyToTap)
{
OnJoystickTap?.Invoke();
isReadyToTap = false;
}
OnJoystickMoveEnd?.Invoke();
}
#endregion
#region --- 搖桿復位 ---
private void RevertJoystickRootPos()
{
if ((joystickRoot.position - joystickDefaultPos).sqrMagnitude > 0.1f)
{
joystickRoot.anchoredPosition = Vector3.Lerp(joystickRoot.anchoredPosition, joystickDefaultPos, revertPositionSpeed);
}
else
{
joystickRoot.anchoredPosition = joystickDefaultPos;
needToRevertRoot = false;
}
}
private void RevertJoystickNodePos()
{
if (joystickNode.localPosition.sqrMagnitude > 0.1f)
{
joystickNode.localPosition = Vector3.Lerp(joystickNode.localPosition, Vector3.zero, revertPositionSpeed);
}
else
{
joystickNode.localPosition = Vector3.zero;
needToRevertNode = false;
}
}
#endregion
}