Как правильно использовать fingerId в Unity? - PullRequest
0 голосов
/ 15 апреля 2020

РЕДАКТИРОВАТЬ: Как я выяснил, идентификатор пальца получает тот же номер, что и исходное значение индекса касания, я сделал метод сброса сохраненного идентификатора пальца от отброшенного касания до -1. Полный ответ опубликован.


Я пытаюсь реализовать мультитач-управление двумя пальцами для моей простой стрелялки, где один выстрел пальцем непрерывно влияет на вращение игрока, если его сначала удерживать в заданная область находится ниже на экране, а другая управляет кнопкой съемки, которая также может быть загружена для стрельбы более мощными пулями.

Сначала я попытался сохранить позицию касания, когда TouchPhase = Began в массиве Vector3 с двумя местами, при этом другие классы проверяют, соответствует ли и какое из значений в массиве правилу для начала их деятельности. Проблема заключалась в том, что указательный палец, по-видимому, падал при подъеме более раннего пальца, поэтому, если я нажал, например, кнопку прицеливания -> выстрел, а затем поднял прицеливание, кнопка прицеливания застряла при загрузке, когда он пытался отследить касание (1) который фактически стал (0).

Решение, которое, казалось, должно было использовать fingerId, который производит последовательное число для прикосновения независимо от его индекса. Дело в том, что то, что я пишу, работает даже хуже, чем раньше. Он активирует функции, даже когда я нажимаю в неправильных местах, поэтому кажется, что оператор if соответствует, даже если это не так. Что не так с кодом?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TouchControls : MonoBehaviour
{
    public static int aimID;
    public static int shootID;
    // Start is called before the first frame update
    void Start()
    {
        aimID = 0;
        shootID = 0;
    }

    // Update is called once per frame
    void Update()
    {
        for (int i = 0; i < Input.touchCount && i < 2; i++)
        {
            if (Input.GetTouch(i).phase == TouchPhase.Began)
            {
                Vector2 pos = Camera.main.ScreenToWorldPoint(Input.GetTouch(i).position);
                if (pos.x == Mathf.Clamp(pos.x, -2.5f * SceneScale.ratio, 2.5f * SceneScale.ratio) &&
                    pos.y <= Camera.main.ScreenToWorldPoint(new Vector3(0, 0, 0)).y + (2 * SceneScale.ratio))
                {
                    aimID = Input.GetTouch(i).fingerId;
                }
                else if (Vector2.Distance(pos, ShotButton.position) <= ShotButton.scale.x)
                {
                    shootID = Input.GetTouch(i).fingerId;
                }
            }
        }
    }
}

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Android;

public class ShotButton : MonoBehaviour
{
    public static bool[] time;
    static public Vector3 scale;
    static public Vector2 position;
    // Start is called before the first frame update
    void Start()
    {
        scale = gameObject.transform.localScale;
        position = new Vector2(gameObject.transform.position.x, gameObject.transform.position.y);
        time = new bool[2];
        time[0] = false;
        time[1] = false;
    }

    // Update is called once per frame
    public void FixedUpdate()
    {
        for (int i = 0; i < Input.touchCount && i < 2; i++)
        {
            time[i] = false;
            if (Input.GetTouch(i).fingerId == TouchControls.shootID)
            {
                time[i] = true;
            }
        }
    }
}

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    public GameObject player;
    public static bool isDead = false;

    public float rot;
    // Start is called before the first frame update
    void Start()
    {
    }

    // Update is called once per frame
    public void FixedUpdate()
    {
        for (int i = 0; i < Input.touchCount && i < 2; i++)
        {
            if (Input.GetTouch(i).fingerId == TouchControls.aimID)
            {
                rot = Camera.main.ScreenToWorldPoint(Input.GetTouch(i).position).x * 80 / (2.5f * SceneScale.ratio);
            }
        }
        rot = Mathf.Clamp(rot, -80, 80);
        player.transform.rotation = Quaternion.Euler(0, 0, rot);
    }
}

1 Ответ

0 голосов
/ 02 мая 2020

Поскольку на этот вопрос не было получено ответов, и я не нашел другого метода, я опубликую то, что я нашел для работы - даже при том, что могут быть другие более эффективные решения.

Соответствие идентификатора пальца исходный индекс касания, который может быть 0 или выше. Поэтому я сохранил уникальный целочисленный тип для каждого метода управления и инициализировал его значением -1. Когда касание с TouchPhase.Began попадает в границы, определенные для одной из кнопок или областей управления, я даю уникальному целочисленному типу записанное значение идентификатора пальца, которое затем используется соответствующим методом, чтобы найти индекс, в котором происходит касание каждый кадр, и когда прикосновение с этим идентификатором пальца возвращает TouchPhase.Ended, оно возвращает сохраненному целому числу значение -1 еще раз, которое не может быть найдено при любом касании, и, таким образом, останавливает метод управления.

...