Несколько дней пытаюсь реализовать орбитальную камеру, которая будет работать на телефоне, но всё никак не могу.
Подскажите готовое решение или как можно мой код переделать?
Перепробовал очень много вариаций, но постоянно баги ловлю
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 Dictionary<int, float> fingerIdToRotationX = new Dictionary<int, float>();
private Dictionary<int, float> fingerIdToRotationY = new Dictionary<int, float>();
public TextMeshProUGUI _testText;
public TextMeshProUGUI _testText2;
public TextMeshProUGUI _testText3;
public TextMeshProUGUI _testText4;
public TextMeshProUGUI _testText5;
public TextMeshProUGUI _testText6;
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 (isAnyTouchMoving)
{
continue;
}
fingerIdToRotationX[touch.fingerId] = rotationX;
fingerIdToRotationY[touch.fingerId] = rotationY;
}
if (fingerIdToFirstTouchOverUI[touch.fingerId])
{
continue;
}
if (touch.phase == TouchPhase.Moved)
{
if (fingerIdToFirstTouchOverUI[touch.fingerId])
{
continue;
}
if (isAnyTouchMoving)
{
continue;
}
_testText5.text = i.ToString();
fingerIdToRotationX[touch.fingerId] = rotationX;
fingerIdToRotationY[touch.fingerId] = rotationY;
fingerIdToRotationY[touch.fingerId] -= touch.deltaPosition.x * sensitivityX * Time.deltaTime;
fingerIdToRotationX[touch.fingerId] += touch.deltaPosition.y * sensitivityY * Time.deltaTime;
fingerIdToRotationX[touch.fingerId] = Mathf.Clamp(fingerIdToRotationX[touch.fingerId], minYAngle, maxYAngle);
isAnyTouchMoving = true;
}
}
if (isAnyTouchMoving)
{
var validRotationY = fingerIdToRotationY
.Where(pair => !fingerIdToFirstTouchOverUI.ContainsKey(pair.Key) || !fingerIdToFirstTouchOverUI[pair.Key])
.Select(pair => pair.Value)
.ToList();
var validRotationX = fingerIdToRotationX
.Where(pair => !fingerIdToFirstTouchOverUI.ContainsKey(pair.Key) || !fingerIdToFirstTouchOverUI[pair.Key])
.Select(pair => pair.Value)
.ToList();
if (validRotationY.Count > 0 && validRotationX.Count > 0)
{
rotationY = validRotationY.First();
rotationX = validRotationX.First();
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"));
}
}