Просто миллион разных попыток было в создании орбитальной камеры для телефона (для пк вышло легко и быстро). В данный момент я подошёл максимально близко к нужному варианту, но есть 1 проблема.
Я хочу, чтоб игрок на телефоне мог водить пальцем по экрану и тем самым вращать камеру, но чтоб на UI это не распространялось, а то иначе он будет водить по джойстику, а камера будет поворачиваться, а это не тот эффект.
Сейчас всё упёрлось в последнюю проблему: Если игрок нажимает сначала на UI Элемент и держит там палец, то потом он не может вторым пальцем двигать в свободном месте камеру, она просто не вращается. Но Если игрок нажал сначала в пустом месте и держит там палец, то потом он может нажать на UI элемент и тогда первый палец будет своим движением вращать камеру как мне надо.
Хочется исправить баг, чтоб даже если палец был на UI первый, то это не мешало бы второму пальцу, который нажал в свободном месте вращать камеру.
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;
private bool isFirstTouchOnUI = false;
public float smoothSpeed = 5f;
private bool isTouchOverUI = false;
private bool isFirstTouchOverUI = false;
private bool isTouchMovingOnUI = false;
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>();
private void Start()
{
CanRotateCamera = true;
if (Application.isMobilePlatform)
{
}
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 (!fingerIdToRotationX.ContainsKey(touch.fingerId))
fingerIdToRotationX[touch.fingerId] = rotationX;
if (!fingerIdToRotationY.ContainsKey(touch.fingerId))
fingerIdToRotationY[touch.fingerId] = rotationY;
}
if (fingerIdToFirstTouchOverUI[touch.fingerId])
{
continue;
}
if (touch.phase == TouchPhase.Moved)
{
if (!fingerIdToFirstTouchOverUI[touch.fingerId])
{
isAnyTouchMoving = true;
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);
}
}
}
if (isAnyTouchMoving)
{
rotationY = fingerIdToRotationY.Values.FirstOrDefault();
rotationX = fingerIdToRotationX.Values.FirstOrDefault();
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"));
}