I’ve been scratching my head with this for a while and I’m stumped. I have an on screen joystick that gets enabled when the player touches the screen at point of touch (clamped to within screen bounds) and disabled when touch is released. During movement of the touch the knob moves around the circle of the joystick but it constrained to just slightly overlap the limits of the joystick without going further. Everything seems to be working as it should and it works flawlessly on the first touch and drag. Everything is smooth and crisp as you move the touch position around the screen. However, when you release the touch and then touch again it spawns a new joystick at the new touch location as it should, but when you move the touch, the knob goes haywire and is super jittery.
here is the code for the class that handles all the related code
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem.EnhancedTouch;
using ETouch = UnityEngine.InputSystem.EnhancedTouch;
public class FloatingJoystickUI : MonoBehaviour
{
[SerializeField] private GameObject playerJoystick;
[SerializeField] private RectTransform joystickRectTransform;
[SerializeField] private RectTransform joystickKnobRectTransform;
private Finger joystickFinger;
private Vector2 touchJoystickSize = new Vector2(200,200);
private float maxKnobMovement;
private Vector2 moveDirection;
private void OnEnable()
{
EnhancedTouchSupport.Enable();
ETouch.Touch.onFingerDown += Touch_onFingerDown;
ETouch.Touch.onFingerMove += Touch_onFingerMove;
ETouch.Touch.onFingerUp += Touch_onFingerUp;
moveDirection = Vector2.zero;
maxKnobMovement = touchJoystickSize.x / 3;
}
private void OnDisable()
{
ETouch.Touch.onFingerDown -= Touch_onFingerDown;
ETouch.Touch.onFingerMove -= Touch_onFingerMove;
ETouch.Touch.onFingerUp -= Touch_onFingerUp;
EnhancedTouchSupport.Disable();
moveDirection = Vector2.zero;
}
private void Touch_onFingerDown(Finger touchedFinger)
{
if (joystickFinger == null && touchedFinger.screenPosition.x <= Screen.width / 2f) // checks if null and akes sure touch is on left side of screen
{
joystickFinger = touchedFinger;
playerJoystick.SetActive(true);
joystickRectTransform.position = ClampJoystickStartPosition(touchedFinger.screenPosition);
joystickKnobRectTransform.position = joystickRectTransform.position;
}
}
private void Touch_onFingerMove(Finger movedFinger)
{
if (movedFinger == joystickFinger)
{
Vector2 knobPosition;
Vector2 joystickPosition = new Vector2(joystickRectTransform.position.x, joystickRectTransform.position.y);
if (Vector2.Distance(movedFinger.currentTouch.screenPosition, joystickPosition) > maxKnobMovement)
{
Vector2 preCenteredKnob;
preCenteredKnob = (joystickPosition - movedFinger.currentTouch.screenPosition).normalized * maxKnobMovement;
knobPosition = joystickPosition - preCenteredKnob;
moveDirection = preCenteredKnob.normalized;
}
else
{
knobPosition = movedFinger.currentTouch.screenPosition;
moveDirection = (joystickPosition - movedFinger.currentTouch.screenPosition).normalized;
}
joystickKnobRectTransform.position = knobPosition;
}
}
private void Update()
{
if (moveDirection != Vector2.zero)
{
Debug.Log(moveDirection);
}
}
private void Touch_onFingerUp(Finger liftedFinger)
{
if (joystickFinger == liftedFinger)
{
joystickFinger = null;
joystickKnobRectTransform.position = Vector2.zero;
moveDirection = Vector2.zero;
playerJoystick.SetActive(false);
}
}
private Vector2 ClampJoystickStartPosition(Vector2 startPosition)
{
if (startPosition.x < touchJoystickSize.x / 2)
{
startPosition.x = touchJoystickSize.x / 2;
}
if (startPosition.y < touchJoystickSize.y / 2)
{
startPosition.y = touchJoystickSize.y / 2;
}
else if (startPosition.y > (Screen.height - (touchJoystickSize.y / 2)))
{
startPosition.y = Screen.height - (touchJoystickSize.y / 2);
}
return startPosition;
}
}
It gets jittery when the touch is both within the bounds of the joystick and when the touch is outside the bounds.
Any help would be appreciated.
Thanks,