简体   繁体   English

操纵杆和接触点未对准

[英]Joystick and touchpoint are misaligned

I'm having a problem with custom joystick I made by following this tutorial and making a couple of changes later to convert it to fixed joystick instead of floating one.我在按照本教程制作的自定义操纵杆上遇到问题,并在稍后进行了一些更改以将其转换为固定操纵杆而不是浮动操纵杆。

The joystick works as expected on 2640x1200 display (that's resolution I use for canvas scaler), but when testing on other screens with bigger or smaller resolution, joystick knob/mushroom and touchpoint are misaligned.操纵杆在 2640x1200 显示器(这是我用于画布缩放器的分辨率)上按预期工作,但在具有更大或更小分辨率的其他屏幕上测试时,操纵杆旋钮/蘑菇头和接触点未对齐。

Expected result.预期结果。

Example of misalignment.错位的例子。

Code:代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using ETouch = UnityEngine.InputSystem.EnhancedTouch;

public class UI_Game_Controls : MonoBehaviour
{
    [SerializeField] private GameObject Joystick_Walk_Area;
    [SerializeField] private GameObject Joystick_Walk_Mushroom;
    private ETouch.Finger Walking_Finger;

    Vector2 Walk_Area_Center;

    float Walk_Area_Width;
    float Walk_Area_Anchor_X;
    float Walk_Area_Height;
    float Walk_Area_Anchor_Y;

    float Scale_Factor;


    private void OnEnable()
    {
        //Debug.Log(Joystick_Walk_Mushroom.GetComponent<RectTransform>().anchoredPosition);
        //Walk_Area_Center = Joystick_Walk_Area.GetComponent<RectTransform>().anchoredPosition + new Vector2(250, 250);
        //Debug.Log(Walk_Area_Center);
        
        /*Gets 4 points used for checking if touchpoint is inside joystick area.*/
        Walk_Area_Width = Joystick_Walk_Area.GetComponent<RectTransform>().anchoredPosition.x + Joystick_Walk_Area.GetComponent<RectTransform>().rect.width;
        Walk_Area_Anchor_X = Joystick_Walk_Area.GetComponent<RectTransform>().anchoredPosition.x;
        Walk_Area_Height = Joystick_Walk_Area.GetComponent<RectTransform>().anchoredPosition.y + Joystick_Walk_Area.GetComponent<RectTransform>().rect.height;
        Walk_Area_Anchor_Y = Joystick_Walk_Area.GetComponent<RectTransform>().anchoredPosition.y;
        

        ETouch.EnhancedTouchSupport.Enable();
        ETouch.Touch.onFingerDown += HandleFingerDown;
        ETouch.Touch.onFingerMove += HandleFingerMove;
        ETouch.Touch.onFingerUp += Touch_onFingerUp;
    }

    private void OnDisable()
    {
        ETouch.Touch.onFingerDown -= HandleFingerDown;
        ETouch.Touch.onFingerMove -= HandleFingerMove;
        ETouch.Touch.onFingerUp -= Touch_onFingerUp;
        ETouch.EnhancedTouchSupport.Disable();
    }

    private void HandleFingerDown(ETouch.Finger FingerTouchDown)
    {
        // Checks if user has touched joystick.
        if (Walking_Finger == null &&
            FingerTouchDown.screenPosition.x >= Walk_Area_Anchor_X && FingerTouchDown.screenPosition.x <= Walk_Area_Width &&
            FingerTouchDown.screenPosition.y >= Walk_Area_Anchor_Y && FingerTouchDown.screenPosition.y <= Walk_Area_Height)
        {
            Walking_Finger = FingerTouchDown;
        }
    }

    private void HandleFingerMove(ETouch.Finger FingerTouchMove)
    {
        if(FingerTouchMove == Walking_Finger)
        {
            Vector2 Walk_Mushroom_Position;
            // Find size of joystick area in which knob should move.
            float Max_Movement = Joystick_Walk_Area.GetComponent<RectTransform>().sizeDelta.y / 2; // 250;

            /*if (Vector2.Distance(FingerTouchMove.currentTouch.screenPosition,Walk_Area_Center)
                > Max_Movement)*/
            if (false) // Disabled on purpose.
            {
                Walk_Mushroom_Position = (FingerTouchMove.currentTouch.screenPosition -
                    Walk_Area_Center).normalized * Max_Movement;
            }
            else
            {
                Walk_Mushroom_Position = FingerTouchMove.currentTouch.screenPosition - Walk_Area_Center;
            }
            Joystick_Walk_Mushroom.GetComponent<RectTransform>().anchoredPosition = Walk_Mushroom_Position;
        }
    }

    private void Touch_onFingerUp(ETouch.Finger obj)
    {
        Walking_Finger = null;
        Joystick_Walk_Mushroom.GetComponent<RectTransform>().anchoredPosition = Vector2.zero;
    }

    private void Start()
    {
        // Get scale factor of canvas.
        Scale_Factor = this.GetComponent<Canvas>().scaleFactor;
        // Calculate center of joystick area after scaling canvas.
        Walk_Area_Center = (Joystick_Walk_Area.GetComponent<RectTransform>().anchoredPosition + new Vector2(250, 250)) * Scale_Factor;

        // // Calculate 4 points after scaling canvas.
        Walk_Area_Width = Walk_Area_Width * Scale_Factor;
        Walk_Area_Anchor_X = Walk_Area_Anchor_X * Scale_Factor;
        Walk_Area_Height = Walk_Area_Height * Scale_Factor;
        Walk_Area_Anchor_Y = Walk_Area_Anchor_Y * Scale_Factor;
    }

    private void Update()
    {
        //Debug.Log(Joystick_Walk_Mushroom.GetComponent<RectTransform>().anchoredPosition.normalized);
        //Debug.Log("Vector.normalized" + (new Vector2(600,600) - new Vector2(300,300)).normalized);

        if (Walking_Finger != null)
        {
            Debug.Log("Finger" + Walking_Finger.currentTouch.screenPosition);
            Debug.Log("Joystick" + Joystick_Walk_Mushroom.GetComponent<RectTransform>().anchoredPosition);
        }
    }
}

I'm super inexperienced with both c# and unity so please excuse me if I'm making some obvious mistake.我对 c# 和 unity 都非常缺乏经验,所以如果我犯了一些明显的错误,请原谅。

PS Sorry for awful and barely commented code. PS 抱歉,代码很糟糕且几乎没有注释。

Got it, I added RectTransformUtility.ScreenPointToLocalPointInRectangle inside HandleFingerMove method.明白了,我在HandleFingerMove方法中添加了RectTransformUtility.ScreenPointToLocalPointInRectangle

Old:老的:

    private void HandleFingerMove(ETouch.Finger FingerTouchMove)
        {
            if(FingerTouchMove == Walking_Finger)
            {
                Vector2 Walk_Mushroom_Position;
                // Find size of joystick area in which knob should move.
                float Max_Movement = Joystick_Walk_Area.GetComponent<RectTransform>().sizeDelta.y / 2; // 250;
     
                /*if (Vector2.Distance(FingerTouchMove.currentTouch.screenPosition,Walk_Area_Center)
                    > Max_Movement)*/
                if (false) // Disabled on purpose.
                {
                    Walk_Mushroom_Position = (FingerTouchMove.currentTouch.screenPosition -
                        Walk_Area_Center).normalized * Max_Movement;
                }
                else
                {
                    Walk_Mushroom_Position = FingerTouchMove.currentTouch.screenPosition - Walk_Area_Center;
                }
                Joystick_Walk_Mushroom.GetComponent<RectTransform>().anchoredPosition = Walk_Mushroom_Position;
            }
        }

New:新的:

    private void HandleFingerMove(ETouch.Finger FingerTouchMove)
        {
            if(FingerTouchMove == Walking_Finger)
            {
                Vector2 Walk_Mushroom_Position;
              // Find size of joystick area in which knob should move.
                float Max_Movement = Joystick_Walk_Area.GetComponent<RectTransform>().sizeDelta.y / 2; // 250;
     
                if (Vector2.Distance(FingerTouchMove.currentTouch.screenPosition,Walk_Area_Center)
                    > Max_Movement)
                //if (false)
                {
                    //TO DO
                    Debug.Log("Finger out");
                    Walk_Mushroom_Position = (FingerTouchMove.currentTouch.screenPosition -
                        Walk_Area_Center).normalized * Max_Movement;
                }
                else
                {
                    RectTransformUtility.ScreenPointToLocalPointInRectangle(
                        Joystick_Walk_Area.GetComponent<RectTransform>(),
                        FingerTouchMove.currentTouch.screenPosition,
                        this.GetComponent<Canvas>().worldCamera,
                        out Walk_Mushroom_Position);
     
                    Debug.Log(Screen.currentResolution);
     
                    Walk_Mushroom_Position.x -= Max_Movement;
                    Walk_Mushroom_Position.y -= Max_Movement;
                }
                Joystick_Walk_Mushroom.GetComponent<RectTransform>().anchoredPosition = Walk_Mushroom_Position;
            }
        }

Edit:编辑:

I will try to explain what (I think) I did and why I did things this way.我将尝试解释(我认为)我做了什么以及为什么我这样做。

My scene is organised like this:我的场景是这样组织的:

Scene

|

> Canvas_UI

  |

  > Joystick_Walk_Area

    |

    > Joystick_Walk_Mushroom

Class which contains HandleFingerMove method is part of Canvas_UI .包含HandleFingerMove方法的类是Canvas_UI的一部分。 Canvas_UI is referenced as this inside class. Canvas_UI被引用为this内部类。

Joystick_Walk_Area is child of Canvas_UI . Joystick_Walk_AreaCanvas_UI的子项。 Joystick_Walk_Area is anchored in bottom left corner of canvas (75px from left edge and 50px above bottom edge of canvas) and has dimensions of 500px x 500px. Joystick_Walk_Area锚定在画布的左下角(距左边缘 75 像素,距画布底部边缘 50 像素),尺寸为 500 像素 x 500 像素。

Joystick_Walk_Mushroom is child of Joystick_Walk_Area and its anchor is in center of Joystick_Walk_Area . Joystick_Walk_Mushroom是 Joystick_Walk_Area 的子Joystick_Walk_Area ,它的锚位于Joystick_Walk_Area的中心。

I used RectTransformUtility.ScreenPointToLocalPointInRectangle to convert FingerTouchMove.currentTouch.screenPosition (user touch input) into local point of Joystick_Walk_Area which made Joystick_Walk_Mushroom appear +250px in X & Y directions away from FingerTouchMove.currentTouch.screenPosition , I fixed this by subtracting touch coordinates (lines 28 and 29)我使用RectTransformUtility.ScreenPointToLocalPointInRectangleFingerTouchMove.currentTouch.screenPosition (用户触摸输入)转换为Joystick_Walk_Area的局部点,这使得Joystick_Walk_Mushroom在远离FingerTouchMove.currentTouch.screenPosition的 X 和 Y 方向上出现 +250px,我通过减去触摸坐标(线28 和 29)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM