为什么手机上的轨道摄像头会抖动?

问题描述 投票:0回答:1

我正在为 webgl 创建一个游戏,目标是为手机创建一个轨道相机,我成功地为计算机做到了这一点,但我无法为手机做到这一点。我已经尝试这样做了几天了,但我仍然没有得到它。我需要你的帮助。目前我已经编写了一个脚本,其中有 1 个错误不允许我使用它。我遇到错误的地方:步骤 1。我将手指按在用户界面的任何元素上,并保持按住。步骤 2. 我将另一根手指按在自由区域中,然后在按住手指的同时在屏幕上滑动手指。步骤 3. 我举起用户界面上方的第一根手指,并仍然握住空闲区域中的手指。第 4 阶段。相机急剧抖动 1 次。如何避免这种相机跳跃?

我的剧本

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;

public class OrbitCamera : MonoBehaviour
{
   
    public Transform target; 
    public float distance = 30; 
    public float sensitivityX = 4.0f;
    public float sensitivityY = 1.0f; 
    public float minYAngle = -80.0f; 
    public float maxYAngle = 80.0f; 

    private float rotationX = 0.0f;
    private float rotationY = 0.0f;

    public bool CanRotateCamera;
    public float smoothSpeed = 5f;
    private Dictionary<int, bool> fingerIdToFirstTouchOverUI = new Dictionary<int, bool>();

    private Touch _touchcurrent;
 

    private void Start()
    {
        CanRotateCamera = true;
        if (Application.isMobilePlatform)
        {
            Input.multiTouchEnabled = true;
            sensitivityY = 7f;
            sensitivityX = 7f;
        }
        else
        {
            Cursor.lockState = CursorLockMode.Locked;
            Cursor.visible = false;
        }
    }

    private void LateUpdate()
    {
        if (Application.isMobilePlatform)
        {
            HandleMobileInput();
        }
        else
        {
            HandlePCInput();
        }
    }

    private void HandleMobileInput()
    {
        if (CanRotateCamera)
        {
            bool isAnyTouchMoving = false;

            for (int i = 0; i < Input.touchCount; i++)
            {
                Touch touch = Input.GetTouch(i);

                if (touch.phase == TouchPhase.Began)
                {
                    fingerIdToFirstTouchOverUI[touch.fingerId] = IsTouchOverUI(touch.position);
                    if (fingerIdToFirstTouchOverUI[touch.fingerId])
                    {
                        continue;
                    }
                }

                if (touch.phase == TouchPhase.Moved && !fingerIdToFirstTouchOverUI[touch.fingerId])
                {
                    rotationY -= touch.deltaPosition.x * sensitivityX * Time.deltaTime;
                    rotationX += touch.deltaPosition.y * sensitivityY * Time.deltaTime;
                    rotationX = Mathf.Clamp(rotationX, minYAngle, maxYAngle);
                    isAnyTouchMoving = true;
                }
            }

            if (isAnyTouchMoving)
            {
                transform.rotation = Quaternion.Euler(rotationX, rotationY, 0);
            }

            Vector3 newPosition = target.position - transform.forward * distance;
            newPosition.y += 7.0f;
            transform.position = newPosition;
        }
    }
   

    private void HandlePCInput()
    {
        if (CanRotateCamera)
        {
            float mouseX = Input.GetAxis("Mouse X");
            float mouseY = Input.GetAxis("Mouse Y");

            rotationY += mouseX * sensitivityX;
            rotationY = Mathf.Repeat(rotationY, 360);

            rotationX -= mouseY * sensitivityY;
            rotationX = Mathf.Clamp(rotationX, minYAngle, maxYAngle);

            distance -= Input.GetAxis("Mouse ScrollWheel");
            distance = Mathf.Clamp(distance, 8.0f, 30.0f);

            transform.rotation = Quaternion.Euler(rotationX, rotationY, 0);

            Vector3 newPosition = target.position - transform.forward * distance;
            newPosition.y += 7.0f;
            transform.position = newPosition;
        }
    }





    private bool IsTouchOverUI(Vector2 touchPosition)
    {
        PointerEventData eventData = new PointerEventData(EventSystem.current);
        eventData.position = touchPosition;

        List<RaycastResult> results = new List<RaycastResult>();
        EventSystem.current.RaycastAll(eventData, results);

        return results.Any(result => result.gameObject.layer == LayerMask.NameToLayer("UI"));
    }
}

我尝试了很多不同的选择,但连续很多天我都无能为力,我很失望,兜圈子,我真的需要了解如何实施的人的帮助。我只想要一个不会干扰 UI 的轨道相机,并且它可以通过手机在 webgl 中工作。

c# android unity-game-engine unity-webgl
1个回答
0
投票

我怀疑当你抬起第一根手指时,第二根手指就会被分配为 touchId 1,最终会得到一个非常大的 deltaPosition。您可以尝试仅检查并拒绝该触摸吗?

if (touch.phase == TouchPhase.Moved && !fingerIdToFirstTouchOverUI[touch.fingerId])
{
    // check for large delta and skip this time
    // experiment with the value so that it doesn't miss certain fast swipes
    if (touch.deltaPosition.magnitude > 100)
    {
        continue; // skip to next for loop
    }

    // delta looks good, handle normally
    rotationY -= touch.deltaPosition.x * sensitivityX * Time.deltaTime;
    rotationX += touch.deltaPosition.y * sensitivityY * Time.deltaTime;
    rotationX = Mathf.Clamp(rotationX, minYAngle, maxYAngle);
    isAnyTouchMoving = true;
}
© www.soinside.com 2019 - 2024. All rights reserved.