119 lines
2.8 KiB
C#
119 lines
2.8 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Unity.VisualScripting;
|
|
using UnityEngine;
|
|
using UnityEngine.Rendering.Universal;
|
|
using static UnityEngine.Mathf;
|
|
|
|
public class CameraOperator : MonoBehaviour
|
|
{
|
|
private Dictionary<int, GameObject> players = new Dictionary<int, GameObject>();
|
|
|
|
[SerializeField]
|
|
private int MaxAdditionalDistance = 15;
|
|
|
|
|
|
private float InitialDistance = 0;
|
|
private float MaxDistance;
|
|
|
|
private Camera cam;
|
|
|
|
private void Awake()
|
|
{
|
|
cam = gameObject.GetComponent<Camera>();
|
|
// Distance here is in the negative direction on the z axis
|
|
InitialDistance = transform.localPosition.z;
|
|
MaxDistance = InitialDistance - MaxAdditionalDistance;
|
|
}
|
|
|
|
public void AddPlayer(GameObject player)
|
|
{
|
|
players[player.GetInstanceID()] = player;
|
|
}
|
|
|
|
public void RemovePlayer(int id)
|
|
{
|
|
players.Remove(id);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Rotates the camera to point at the center between the players.
|
|
/// </summary>
|
|
private void LateUpdate()
|
|
{
|
|
CenterBetweenPlayers();
|
|
AdjustZoom();
|
|
}
|
|
|
|
private void CenterBetweenPlayers()
|
|
{
|
|
if (players.Count < 1)
|
|
{
|
|
return;
|
|
}
|
|
float x = transform.localPosition.x;
|
|
float y = transform.localPosition.y;
|
|
float z = transform.localPosition.z;
|
|
foreach (GameObject p in players.Values)
|
|
{
|
|
if (p.IsDestroyed())
|
|
continue;
|
|
Vector3 position = p.transform.localPosition;
|
|
z = position.z;
|
|
x += position.x;
|
|
y += position.y;
|
|
}
|
|
x /= players.Count();
|
|
y /= players.Count();
|
|
float a = z - InitialDistance;
|
|
float cXAxis = (float)Sqrt(Pow(a, 2) + Pow(x, 2));
|
|
float cYAxis = (float)Sqrt(Pow(a, 2) + Pow(y, 2));
|
|
Vector3 xyRotation = new Vector3(Rad2Deg * Acos(a / cYAxis) * -Math.Sign(y),
|
|
Rad2Deg * Acos(a / cXAxis) * Math.Sign(x), 0);
|
|
if (transform.localEulerAngles != xyRotation / 2)
|
|
{
|
|
transform.localEulerAngles = xyRotation / 2;
|
|
}
|
|
}
|
|
private void AdjustZoom()
|
|
{
|
|
if (players.Count < 2)
|
|
{
|
|
return;
|
|
}
|
|
float Margin = Screen.height / 2;
|
|
|
|
float maxXDistance = 0;
|
|
float maxYDistance = 0;
|
|
|
|
foreach (GameObject player in players.Values)
|
|
{
|
|
var screenPos1 = cam.WorldToScreenPoint(player.transform.position);
|
|
foreach (GameObject p in players.Values)
|
|
{
|
|
if (p == player)
|
|
continue;
|
|
var screenPos2 = cam.WorldToScreenPoint(p.transform.position);
|
|
var distance = screenPos2 - screenPos1;
|
|
float xDistance = Abs(distance.x);
|
|
if (maxXDistance < xDistance)
|
|
maxXDistance = xDistance;
|
|
float yDistance = Abs(distance.y);
|
|
if (maxYDistance < yDistance)
|
|
maxYDistance = Abs(distance.y);
|
|
}
|
|
}
|
|
if (maxXDistance < Screen.width - Margin
|
|
&& maxYDistance < Screen.height - Margin)
|
|
{
|
|
if (transform.localPosition.z < InitialDistance + 0.1f)
|
|
transform.localPosition += new Vector3(0, 0, 0.1f);
|
|
return;
|
|
}
|
|
|
|
if (transform.localPosition.z > MaxDistance - 0.1f)
|
|
transform.localPosition -= new Vector3(0, 0, 0.1f);
|
|
|
|
}
|
|
} |