Search Unity

"floating joystick" in the joystick pack gives a different value on the first touch?

Discussion in 'Input System' started by Guga9, Aug 26, 2021.

  1. Guga9

    Guga9

    Joined:
    Oct 27, 2020
    Posts:
    4
    I'm using the "Floating Joystick" prefab found in the "Joystick", which is available for free in the Unity asset store (it appears when touched anywhere in the specified area)

    I will use this Joystick while shooting. There is no problem in general. However, the only problem is when I run the game for the first time and touch it only once with the mouse, I don't move the handle at all, the "Floating Joystick" value is high. Then it doesn't happen like this, but when I close the game and open it again, it happens again...

    Code (CSharp):
    1.  
    2. void Update()
    3.     {
    4.         if ((attakJoystick.Horizontal > 0.1f || attakJoystick.Vertical > 0.1f) || (attakJoystick.Horizontal < -0.1f || attakJoystick.Vertical < -0.1f))
    5.         {
    6.             float x = attakJoystick.Horizontal;
    7.             float y = attakJoystick.Vertical;
    8.             float z = Mathf.Atan2(y, x) * Mathf.Rad2Deg;
    9.             rbp.transform.eulerAngles = new Vector3(0, 0, z);
    10.         }
    11.     }
    12.  
    13.     private void FixedUpdate()
    14.     {
    15.         if ((Mathf.Abs(attakJoystick.Horizontal) > 0.7f || Mathf.Abs(attakJoystick.Vertical) > 0.7f) && (readyToShoot && !reloading && bulletsLeft > 0))
    16.         {
    17.            //When I run the game for the first time and only click on the screen once, it enters this block. It should not be entered because any of the values should not be above 0.7, but it happens.
    18.             Shoot();
    19.         }
    20.  

    https://imgur.com/mB5hCnw
    https://imgur.com/we7XhHl
    https://imgur.com/Sxn5Xzt

    And "JoystickPack" Scripts:
    Code (CSharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. using UnityEngine.EventSystems;
    6.  
    7. public class Joystick : MonoBehaviour, IPointerDownHandler, IDragHandler, IPointerUpHandler
    8. {
    9.     public float Horizontal { get { return (snapX) ? SnapFloat(input.x, AxisOptions.Horizontal) : input.x; } }
    10.     public float Vertical { get { return (snapY) ? SnapFloat(input.y, AxisOptions.Vertical) : input.y; } }
    11.     public Vector2 Direction { get { return new Vector2(Horizontal, Vertical); } }
    12.  
    13.     public float HandleRange
    14.     {
    15.         get { return handleRange; }
    16.         set { handleRange = Mathf.Abs(value); }
    17.     }
    18.  
    19.     public float DeadZone
    20.     {
    21.         get { return deadZone; }
    22.         set { deadZone = Mathf.Abs(value); }
    23.     }
    24.  
    25.     public AxisOptions AxisOptions { get { return AxisOptions; } set { axisOptions = value; } }
    26.     public bool SnapX { get { return snapX; } set { snapX = value; } }
    27.     public bool SnapY { get { return snapY; } set { snapY = value; } }
    28.  
    29.     [SerializeField] private float handleRange = 1;
    30.     [SerializeField] private float deadZone = 0;
    31.     [SerializeField] private AxisOptions axisOptions = AxisOptions.Both;
    32.     [SerializeField] private bool snapX = false;
    33.     [SerializeField] private bool snapY = false;
    34.  
    35.     [SerializeField] protected RectTransform background = null;
    36.     [SerializeField] private RectTransform handle = null;
    37.     private RectTransform baseRect = null;
    38.  
    39.     private Canvas canvas;
    40.     private Camera cam;
    41.  
    42.     private Vector2 input = Vector2.zero;
    43.  
    44.     protected virtual void Start()
    45.     {
    46.         HandleRange = handleRange;
    47.         DeadZone = deadZone;
    48.         baseRect = GetComponent<RectTransform>();
    49.         canvas = GetComponentInParent<Canvas>();
    50.         if (canvas == null)
    51.             Debug.LogError("The Joystick is not placed inside a canvas");
    52.  
    53.         Vector2 center = new Vector2(0.5f, 0.5f);
    54.         background.pivot = center;
    55.         handle.anchorMin = center;
    56.         handle.anchorMax = center;
    57.         handle.pivot = center;
    58.         handle.anchoredPosition = Vector2.zero;
    59.     }
    60.  
    61.     public virtual void OnPointerDown(PointerEventData eventData)
    62.     {
    63.         OnDrag(eventData);
    64.     }
    65.  
    66.     public void OnDrag(PointerEventData eventData)
    67.     {
    68.         cam = null;
    69.         if (canvas.renderMode == RenderMode.ScreenSpaceCamera)
    70.             cam = canvas.worldCamera;
    71.  
    72.         Vector2 position = RectTransformUtility.WorldToScreenPoint(cam, background.position);
    73.         Vector2 radius = background.sizeDelta / 2;
    74.         input = (eventData.position - position) / (radius * canvas.scaleFactor);
    75.         FormatInput();
    76.         HandleInput(input.magnitude, input.normalized, radius, cam);
    77.         handle.anchoredPosition = input * radius * handleRange;
    78.     }
    79.  
    80.     protected virtual void HandleInput(float magnitude, Vector2 normalised, Vector2 radius, Camera cam)
    81.     {
    82.         if (magnitude > deadZone)
    83.         {
    84.             if (magnitude > 1)
    85.                 input = normalised;
    86.         }
    87.         else
    88.             input = Vector2.zero;
    89.     }
    90.  
    91.     private void FormatInput()
    92.     {
    93.         if (axisOptions == AxisOptions.Horizontal)
    94.             input = new Vector2(input.x, 0f);
    95.         else if (axisOptions == AxisOptions.Vertical)
    96.             input = new Vector2(0f, input.y);
    97.     }
    98.  
    99.     private float SnapFloat(float value, AxisOptions snapAxis)
    100.     {
    101.         if (value == 0)
    102.             return value;
    103.  
    104.         if (axisOptions == AxisOptions.Both)
    105.         {
    106.             float angle = Vector2.Angle(input, Vector2.up);
    107.             if (snapAxis == AxisOptions.Horizontal)
    108.             {
    109.                 if (angle < 22.5f || angle > 157.5f)
    110.                     return 0;
    111.                 else
    112.                     return (value > 0) ? 1 : -1;
    113.             }
    114.             else if (snapAxis == AxisOptions.Vertical)
    115.             {
    116.                 if (angle > 67.5f && angle < 112.5f)
    117.                     return 0;
    118.                 else
    119.                     return (value > 0) ? 1 : -1;
    120.             }
    121.             return value;
    122.         }
    123.         else
    124.         {
    125.             if (value > 0)
    126.                 return 1;
    127.             if (value < 0)
    128.                 return -1;
    129.         }
    130.         return 0;
    131.     }
    132.  
    133.     public virtual void OnPointerUp(PointerEventData eventData)
    134.     {
    135.         input = Vector2.zero;
    136.         handle.anchoredPosition = Vector2.zero;
    137.     }
    138.  
    139.     protected Vector2 ScreenPointToAnchoredPosition(Vector2 screenPosition)
    140.     {
    141.         Vector2 localPoint = Vector2.zero;
    142.         if (RectTransformUtility.ScreenPointToLocalPointInRectangle(baseRect, screenPosition, cam, out localPoint))
    143.         {
    144.             Vector2 pivotOffset = baseRect.pivot * baseRect.sizeDelta;
    145.             return localPoint - (background.anchorMax * baseRect.sizeDelta) + pivotOffset;
    146.         }
    147.         return Vector2.zero;
    148.     }
    149. }
    150.  
    151. public enum AxisOptions { Both, Horizontal, Vertical }
    152.  
    Code (CSharp):
    1.  
    2. using UnityEngine.EventSystems;
    3.  
    4. public class FloatingJoystick : Joystick
    5. {
    6.     protected override void Start()
    7.     {
    8.         base.Start();
    9.         background.gameObject.SetActive(false);
    10.     }
    11.  
    12.     public override void OnPointerDown(PointerEventData eventData)
    13.     {
    14.         background.anchoredPosition = ScreenPointToAnchoredPosition(eventData.position);
    15.         background.gameObject.SetActive(true);
    16.         base.OnPointerDown(eventData);
    17.     }
    18.  
    19.     public override void OnPointerUp(PointerEventData eventData)
    20.     {
    21.         background.gameObject.SetActive(false);
    22.         base.OnPointerUp(eventData);
    23.     }
    24. }
    25.  
     
  2. Guga9

    Guga9

    Joined:
    Oct 27, 2020
    Posts:
    4
    By the way, I noticed something, Canvas "Render Mode" Screen Space - Overlay does not have such a problem. I was using Screen Space - Camera. But I don't understand why it does this.
     
  3. Scalisco

    Scalisco

    Joined:
    Feb 2, 2014
    Posts:
    20
    I had this problem too. I solved it by moving the following code from the beginning of Joystick.OnDrag to the end of Start. Not sure if it has other consequences though.

    Code (CSharp):
    1.         cam = null;
    2.         if (canvas.renderMode == RenderMode.ScreenSpaceCamera)
    3.             cam = canvas.worldCamera;
     
    Balkera, Irina-uk, gsoganci and 6 others like this.
  4. trandiep0218

    trandiep0218

    Joined:
    Mar 4, 2021
    Posts:
    2
    I found out that the problem does come from the variable "cam", its value is null the first time this code is executed:
    Code (CSharp):
    1.    
    2.     protected Vector2 ScreenPointToAnchoredPosition(Vector2 screenPosition)
    3.     {
    4.         Vector2 localPoint = Vector2.zero;
    5.         if (RectTransformUtility.ScreenPointToLocalPointInRectangle(baseRect, screenPosition, cam, out localPoint))
    6.         {
    7.             Vector2 pivotOffset = baseRect.pivot * baseRect.sizeDelta;
    8.             return localPoint - (background.anchorMax * baseRect.sizeDelta) + pivotOffset;
    9.         }
    10.         return Vector2.zero;
    11.     }
    12.  
    So instead of removing the code from Joystick as you did, we just need to copy it to the end of the Awake function and it works just fine. But I'm also not sure if it will cause any other problems.
     
    Olnipa likes this.
  5. Olnipa

    Olnipa

    Joined:
    Oct 27, 2022
    Posts:
    3
    I also had the same issue and your topic helped me. Thank you, guys! Just as a resume I'd like to put how the Start method in the Joystick class must be looked to solve above problem:

    protected virtual void Start()
    {
    HandleRange = handleRange;
    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);
    background.pivot = center;
    handle.anchorMin = center;
    handle.anchorMax = center;
    handle.pivot = center;
    handle.anchoredPosition = Vector2.zero;

    if (canvas.renderMode == RenderMode.ScreenSpaceCamera)
    cam = canvas.worldCamera;
    }