我正在为 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 中工作。
我怀疑当你抬起第一根手指时,第二根手指就会被分配为 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;
}