Files
ScienceLab.GravityForce/Assets/Materials/Scripts/CameraController.cs
2026-03-17 13:40:09 +02:00

242 lines
7.7 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraController : MonoBehaviour
{
public Camera mainCamera;
public float transitionSpeed = 3f;
public float planetDistance = 15f;
public float planetHeight = 5f;
public float rotationSpeed = 100f;
public float cameraLocalX = 1.76f;
public float cameraLocalY = 1.14f;
public float cameraLocalZ = -1.51f;
public Vector3 cameraLocalRotation;
public float sunZoomSpeed = 10f;
public float sunMinZ = -200f;
public float sunMaxZ = -5f;
private Dictionary<int, GameObject> _planets = new Dictionary<int, GameObject>();
private GameObject _sun;
private int _currentIndex = 0;
private bool _isTransitioning = false;
private float _currentPlanetDistance;
private float _planetRotationY = 0f;
private float _planetRotationX = 20f;
void Start()
{
_sun = GameObject.Find("Sun");
FindPlanetByName(1, "Mercury");
FindPlanetByName(2, "Venus");
FindPlanetByName(3, "Earth");
FindPlanetByName(4, "Mars");
FindPlanetByName(5, "Jupiter");
FindPlanetByName(6, "Saturn");
FindPlanetByName(7, "Uranus");
FindPlanetByName(8, "Neptune");
FindPlanetByName(9, "Pluto");
_currentPlanetDistance = planetDistance;
ShowOverview();
}
void FindPlanetByName(int key, string planetName)
{
GameObject planet = GameObject.Find(planetName);
if (planet != null)
_planets[key] = planet;
}
void Update()
{
HandleInput();
if (!_isTransitioning && _currentIndex != 0)
HandlePlanetCamera();
if (!_isTransitioning && _currentIndex == 0)
HandleSunZoom();
}
void HandleInput()
{
if (Input.GetKeyDown(KeyCode.Alpha0) || Input.GetKeyDown(KeyCode.Keypad0))
ShowOverview();
if (Input.GetKeyDown(KeyCode.Alpha1) || Input.GetKeyDown(KeyCode.Keypad1)) FocusPlanet(1);
if (Input.GetKeyDown(KeyCode.Alpha2) || Input.GetKeyDown(KeyCode.Keypad2)) FocusPlanet(2);
if (Input.GetKeyDown(KeyCode.Alpha3) || Input.GetKeyDown(KeyCode.Keypad3)) FocusPlanet(3);
if (Input.GetKeyDown(KeyCode.Alpha4) || Input.GetKeyDown(KeyCode.Keypad4)) FocusPlanet(4);
if (Input.GetKeyDown(KeyCode.Alpha5) || Input.GetKeyDown(KeyCode.Keypad5)) FocusPlanet(5);
if (Input.GetKeyDown(KeyCode.Alpha6) || Input.GetKeyDown(KeyCode.Keypad6)) FocusPlanet(6);
if (Input.GetKeyDown(KeyCode.Alpha7) || Input.GetKeyDown(KeyCode.Keypad7)) FocusPlanet(7);
if (Input.GetKeyDown(KeyCode.Alpha8) || Input.GetKeyDown(KeyCode.Keypad8)) FocusPlanet(8);
if (Input.GetKeyDown(KeyCode.Alpha9) || Input.GetKeyDown(KeyCode.Keypad9)) FocusPlanet(9);
if (Input.GetKeyDown(KeyCode.RightArrow)) NextPlanet();
if (Input.GetKeyDown(KeyCode.LeftArrow)) PreviousPlanet();
}
void ShowOverview()
{
_currentIndex = 0;
StopAllCoroutines();
StartCoroutine(TransitionToSun());
}
void FocusPlanet(int planetNumber)
{
if (!_planets.ContainsKey(planetNumber)) return;
_currentIndex = planetNumber;
StopAllCoroutines();
StartCoroutine(TransitionToPlanet(planetNumber));
}
void NextPlanet()
{
_currentIndex++;
if (_currentIndex > 9) _currentIndex = 0;
if (_currentIndex == 0) ShowOverview();
else FocusPlanet(_currentIndex);
}
void PreviousPlanet()
{
_currentIndex--;
if (_currentIndex < 0) _currentIndex = 9;
if (_currentIndex == 0) ShowOverview();
else FocusPlanet(_currentIndex);
}
IEnumerator TransitionToSun()
{
_isTransitioning = true;
if (_sun == null)
{
_isTransitioning = false;
yield break;
}
Vector3 startPos = mainCamera.transform.position;
Quaternion startRot = mainCamera.transform.rotation;
Vector3 targetWorldPos = _sun.transform.TransformPoint(
new Vector3(cameraLocalX, cameraLocalY, cameraLocalZ)
);
Quaternion targetWorldRot = _sun.transform.rotation * Quaternion.Euler(cameraLocalRotation);
float elapsed = 0f;
float duration = 1f / transitionSpeed;
while (elapsed < duration)
{
elapsed += Time.deltaTime;
float t = Mathf.SmoothStep(0, 1, elapsed / duration);
mainCamera.transform.position = Vector3.Lerp(startPos, targetWorldPos, t);
mainCamera.transform.rotation = Quaternion.Slerp(startRot, targetWorldRot, t);
yield return null;
}
mainCamera.transform.SetParent(_sun.transform);
mainCamera.transform.localPosition = new Vector3(cameraLocalX, cameraLocalY, cameraLocalZ);
mainCamera.transform.localRotation = Quaternion.Euler(cameraLocalRotation);
_isTransitioning = false;
}
void HandleSunZoom()
{
if (mainCamera.transform.parent != _sun.transform) return;
float scroll = Input.GetAxis("Mouse ScrollWheel");
if (Mathf.Abs(scroll) < 0.001f) return;
cameraLocalZ += scroll * sunZoomSpeed;
cameraLocalZ = Mathf.Clamp(cameraLocalZ, sunMinZ, sunMaxZ);
mainCamera.transform.localPosition = new Vector3(
cameraLocalX,
cameraLocalY,
cameraLocalZ
);
}
IEnumerator TransitionToPlanet(int planetNumber)
{
_isTransitioning = true;
Transform planet = _planets[planetNumber].transform;
mainCamera.transform.SetParent(null);
Vector3 startPos = mainCamera.transform.position;
Quaternion startRot = mainCamera.transform.rotation;
_currentPlanetDistance = planetDistance;
Vector3 localTargetPos = new Vector3(0, planetHeight, -_currentPlanetDistance);
Vector3 worldTargetPos = planet.TransformPoint(localTargetPos);
Quaternion targetRot = Quaternion.LookRotation(planet.position - worldTargetPos);
float elapsed = 0f;
float duration = 1f / transitionSpeed;
while (elapsed < duration)
{
elapsed += Time.deltaTime;
float t = Mathf.SmoothStep(0, 1, elapsed / duration);
mainCamera.transform.position = Vector3.Lerp(startPos, worldTargetPos, t);
mainCamera.transform.rotation = Quaternion.Slerp(startRot, targetRot, t);
yield return null;
}
mainCamera.transform.SetParent(planet);
mainCamera.transform.localPosition = localTargetPos;
mainCamera.transform.LookAt(planet.position);
_planetRotationY = 0f;
_planetRotationX = planetHeight > 0 ? 20f : 0f;
_isTransitioning = false;
}
void HandlePlanetCamera()
{
if (!_planets.ContainsKey(_currentIndex)) return;
Transform planet = _planets[_currentIndex].transform;
if (Input.GetMouseButton(1))
{
_planetRotationY += Input.GetAxis("Mouse X") * rotationSpeed * Time.deltaTime;
_planetRotationX -= Input.GetAxis("Mouse Y") * rotationSpeed * Time.deltaTime;
_planetRotationX = Mathf.Clamp(_planetRotationX, -85f, 85f);
}
float scroll = Input.GetAxis("Mouse ScrollWheel");
_currentPlanetDistance -= scroll * 10f;
_currentPlanetDistance = Mathf.Clamp(_currentPlanetDistance, 3f, 100f);
Quaternion rotation = Quaternion.Euler(_planetRotationX, _planetRotationY, 0);
Vector3 localPos = rotation * new Vector3(0, 0, -_currentPlanetDistance);
mainCamera.transform.localPosition = localPos;
Vector3 direction = planet.position - mainCamera.transform.position;
mainCamera.transform.rotation =
Quaternion.LookRotation(direction, planet.up);
}
}