Делаю уже несколько дней орбитальную камеру и происходит лишний поворот.
В чем суть, камера свободно вращается пальцем по свободному от UI месту (просто по экрану водится там где нет UI), но можно словить баг.
Если одним пальцем нажать и держать на UI элемент, после этого другим пальцем покрутить камеру в свободном от UI месте и отпустить первый палец, который был на UI, не отпуская второй, который в свободном месте, то тогда камера резко 1 раз дёрнется и изменит свое положение. Почему так происходит, если я блокирую любые повороты для 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;
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>();
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;
}
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 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"));
}