Initial commit
This commit is contained in:
39
Assets/Scripts/AirTrailController.cs
Normal file
39
Assets/Scripts/AirTrailController.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class AirTrailController : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private TrailRenderer trail;
|
||||
|
||||
private bool _active;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
trail.emitting = false;
|
||||
trail.Clear();
|
||||
}
|
||||
|
||||
void LateUpdate()
|
||||
{
|
||||
if (!_active) return;
|
||||
}
|
||||
|
||||
public void Activate(Vector3 startPos)
|
||||
{
|
||||
transform.position = startPos;
|
||||
|
||||
trail.Clear();
|
||||
trail.emitting = false;
|
||||
trail.emitting = true;
|
||||
_active = true;
|
||||
}
|
||||
|
||||
public void Deactivate()
|
||||
{
|
||||
_active = false;
|
||||
trail.emitting = false;
|
||||
trail.Clear();
|
||||
}
|
||||
|
||||
}
|
||||
11
Assets/Scripts/AirTrailController.cs.meta
Normal file
11
Assets/Scripts/AirTrailController.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c4fc423f8b56a3c49b0465f34ef591fb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
172
Assets/Scripts/AnimalChase.cs
Normal file
172
Assets/Scripts/AnimalChase.cs
Normal file
@@ -0,0 +1,172 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class AnimalChase : MonoBehaviour
|
||||
{ public enum AnimalType
|
||||
{
|
||||
Cat,
|
||||
Dog
|
||||
}
|
||||
|
||||
public AnimalType animalType;
|
||||
public AnimalChase otherAnimal;
|
||||
public PlayZone zone;
|
||||
|
||||
public float walkSpeed = 2f;
|
||||
public float runSpeed = 4f;
|
||||
public float catchDistance = 1.5f;
|
||||
public float restTime = 1f;
|
||||
|
||||
private CharacterController _controller;
|
||||
private Animator _animator;
|
||||
|
||||
private bool _isChasing;
|
||||
private bool _isResting;
|
||||
private bool _isRunningAway;
|
||||
|
||||
private Vector3 _targetPoint;
|
||||
|
||||
private float _gravity = -9.8f;
|
||||
private float _verticalVelocity;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_controller = GetComponent<CharacterController>();
|
||||
_animator = GetComponent<Animator>();
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (animalType == AnimalType.Dog)
|
||||
StartChasing();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (zone == null || otherAnimal == null)
|
||||
return;
|
||||
|
||||
ApplyGravity();
|
||||
|
||||
if (_isResting)
|
||||
{
|
||||
UpdateAnimator(0f, 0f);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_isChasing)
|
||||
{
|
||||
ChaseTarget();
|
||||
}
|
||||
else if (_isRunningAway)
|
||||
{
|
||||
RunToPoint();
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateAnimator(0f, 0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void ChaseTarget()
|
||||
{
|
||||
MoveTo(otherAnimal.transform.position, runSpeed);
|
||||
|
||||
float dist = Vector3.Distance(transform.position, otherAnimal.transform.position);
|
||||
|
||||
if (dist <= catchDistance)
|
||||
{
|
||||
StartCoroutine(RestAndSwitch());
|
||||
}
|
||||
}
|
||||
|
||||
private void RunToPoint()
|
||||
{
|
||||
MoveTo(_targetPoint, walkSpeed);
|
||||
|
||||
if (Vector3.Distance(transform.position, _targetPoint) < 0.5f)
|
||||
{
|
||||
_isRunningAway = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void MoveTo(Vector3 worldTarget, float speed)
|
||||
{
|
||||
worldTarget = zone.ClampToZone(worldTarget);
|
||||
|
||||
Vector3 dir = worldTarget - transform.position;
|
||||
dir.y = 0f;
|
||||
|
||||
float distance = dir.magnitude;
|
||||
|
||||
if (distance < 0.1f)
|
||||
{
|
||||
UpdateAnimator(0f, 0f);
|
||||
return;
|
||||
}
|
||||
|
||||
dir.Normalize();
|
||||
|
||||
Vector3 move = dir * speed;
|
||||
move.y = _verticalVelocity;
|
||||
|
||||
_controller.Move(move * Time.deltaTime);
|
||||
|
||||
transform.rotation = Quaternion.LookRotation(dir);
|
||||
|
||||
|
||||
if (speed >= runSpeed * 0.9f)
|
||||
{
|
||||
UpdateAnimator(1f, 1f);
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateAnimator(1f, 0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private IEnumerator RestAndSwitch()
|
||||
{
|
||||
_isChasing = false;
|
||||
_isResting = true;
|
||||
|
||||
UpdateAnimator(0f, 0f);
|
||||
|
||||
yield return new WaitForSeconds(restTime);
|
||||
|
||||
_isResting = false;
|
||||
|
||||
_targetPoint = zone.GetRandomPoint();
|
||||
_isRunningAway = true;
|
||||
|
||||
otherAnimal.StartChasing();
|
||||
}
|
||||
|
||||
public void StartChasing()
|
||||
{
|
||||
_isChasing = true;
|
||||
_isRunningAway = false;
|
||||
_isResting = false;
|
||||
}
|
||||
|
||||
private void UpdateAnimator(float vert, float state)
|
||||
{
|
||||
_animator.SetFloat("Vert", vert);
|
||||
_animator.SetFloat("State", state);
|
||||
}
|
||||
|
||||
private void ApplyGravity()
|
||||
{
|
||||
if (_controller.isGrounded)
|
||||
{
|
||||
_verticalVelocity = -1f;
|
||||
}
|
||||
else
|
||||
{
|
||||
_verticalVelocity += _gravity * Time.deltaTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/AnimalChase.cs.meta
Normal file
11
Assets/Scripts/AnimalChase.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5446c8c63a2e04747afba2dbcca3b363
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
36
Assets/Scripts/Billboard.cs
Normal file
36
Assets/Scripts/Billboard.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class Billboard : MonoBehaviour
|
||||
{
|
||||
private Transform _parentObject;
|
||||
public float heightOffset = 1.5f;
|
||||
|
||||
void Start()
|
||||
{
|
||||
_parentObject = transform.parent;
|
||||
|
||||
transform.SetParent(null);
|
||||
}
|
||||
|
||||
void LateUpdate()
|
||||
{
|
||||
if (_parentObject == null) return;
|
||||
|
||||
if (Camera.main == null) return;
|
||||
|
||||
transform.position = _parentObject.position + Vector3.up * heightOffset;
|
||||
|
||||
transform.LookAt(Camera.main.transform);
|
||||
transform.Rotate(0, 180, 0);
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
if (_parentObject == null)
|
||||
{
|
||||
Destroy(gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/Billboard.cs.meta
Normal file
11
Assets/Scripts/Billboard.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c82cf7b3ebf181e4599af2d56540458b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
19
Assets/Scripts/BillboardToCamera.cs
Normal file
19
Assets/Scripts/BillboardToCamera.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class BillboardToCamera : MonoBehaviour
|
||||
{
|
||||
private Transform _camera;
|
||||
void Start()
|
||||
{
|
||||
_camera = Camera.main.transform;
|
||||
}
|
||||
|
||||
void LateUpdate()
|
||||
{
|
||||
if (_camera == null) return;
|
||||
|
||||
transform.LookAt(transform.position + _camera.forward);
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/BillboardToCamera.cs.meta
Normal file
11
Assets/Scripts/BillboardToCamera.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3e08748da6c5082438f35abfc8b8bf43
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
137
Assets/Scripts/Calendar.cs
Normal file
137
Assets/Scripts/Calendar.cs
Normal file
@@ -0,0 +1,137 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using TMPro;
|
||||
using UnityEngine.UI;
|
||||
using System;
|
||||
|
||||
public class Calendar : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private TextMeshProUGUI monthText;
|
||||
[SerializeField] private Transform daysParent;
|
||||
[SerializeField] private GameObject dayPrefab;
|
||||
|
||||
private DateTime _currentDate;
|
||||
|
||||
private List<GameObject> _currentMonthButtons =
|
||||
new List<GameObject>();
|
||||
|
||||
private int _lastMonth = -1;
|
||||
private int _lastYear = -1;
|
||||
|
||||
public void SetDate(DateTime newDate)
|
||||
{
|
||||
_currentDate = newDate;
|
||||
|
||||
if (_currentDate.Month != _lastMonth ||
|
||||
_currentDate.Year != _lastYear)
|
||||
{
|
||||
_lastMonth = _currentDate.Month;
|
||||
_lastYear = _currentDate.Year;
|
||||
|
||||
GenerateCalendar();
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateVisual();
|
||||
}
|
||||
}
|
||||
|
||||
private void GenerateCalendar()
|
||||
{
|
||||
for (int i = daysParent.childCount - 1; i >= 0; i--)
|
||||
{
|
||||
Destroy(daysParent.GetChild(i).gameObject);
|
||||
}
|
||||
|
||||
_currentMonthButtons.Clear();
|
||||
|
||||
monthText.text = _currentDate.ToString("MMMM yyyy");
|
||||
|
||||
DateTime firstDay =
|
||||
new DateTime(_currentDate.Year,
|
||||
_currentDate.Month,
|
||||
1);
|
||||
|
||||
int daysInMonth =
|
||||
DateTime.DaysInMonth(_currentDate.Year,
|
||||
_currentDate.Month);
|
||||
|
||||
int startDayOfWeek =
|
||||
((int)firstDay.DayOfWeek + 6) % 7;
|
||||
|
||||
DateTime prevMonth =
|
||||
_currentDate.AddMonths(-1);
|
||||
|
||||
int daysInPrevMonth =
|
||||
DateTime.DaysInMonth(prevMonth.Year,
|
||||
prevMonth.Month);
|
||||
|
||||
for (int i = startDayOfWeek; i > 0; i--)
|
||||
{
|
||||
int dayNumber =
|
||||
daysInPrevMonth - i + 1;
|
||||
|
||||
GameObject dayObj =
|
||||
Instantiate(dayPrefab, daysParent);
|
||||
|
||||
dayObj.GetComponentInChildren<TextMeshProUGUI>()
|
||||
.text = dayNumber.ToString();
|
||||
|
||||
Image img =
|
||||
dayObj.GetComponent<Image>();
|
||||
|
||||
img.color = Color.gray;
|
||||
}
|
||||
|
||||
for (int day = 1; day <= daysInMonth; day++)
|
||||
{
|
||||
GameObject dayObj =
|
||||
Instantiate(dayPrefab, daysParent);
|
||||
|
||||
dayObj.GetComponentInChildren<TextMeshProUGUI>()
|
||||
.text = day.ToString();
|
||||
|
||||
_currentMonthButtons.Add(dayObj);
|
||||
}
|
||||
|
||||
UpdateVisual();
|
||||
}
|
||||
|
||||
private void UpdateVisual()
|
||||
{
|
||||
int today = _currentDate.Day;
|
||||
|
||||
for (int i = 0; i < _currentMonthButtons.Count; i++)
|
||||
{
|
||||
Image img =
|
||||
_currentMonthButtons[i]
|
||||
.GetComponent<Image>();
|
||||
|
||||
Transform marker =
|
||||
_currentMonthButtons[i]
|
||||
.transform.Find("CurrentData");
|
||||
|
||||
int dayNumber = i + 1;
|
||||
|
||||
if (dayNumber < today)
|
||||
{
|
||||
img.color = Color.gray;
|
||||
if (marker != null)
|
||||
marker.gameObject.SetActive(false);
|
||||
}
|
||||
else if (dayNumber == today)
|
||||
{
|
||||
img.color = Color.white;
|
||||
if (marker != null)
|
||||
marker.gameObject.SetActive(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
img.color = Color.white;
|
||||
if (marker != null)
|
||||
marker.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/Calendar.cs.meta
Normal file
11
Assets/Scripts/Calendar.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0280349c718ed9246a7ea331113f1dc6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
156
Assets/Scripts/CalendarManager.cs
Normal file
156
Assets/Scripts/CalendarManager.cs
Normal file
@@ -0,0 +1,156 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using System;
|
||||
|
||||
public enum PlanetType
|
||||
{
|
||||
Mercury,
|
||||
Venus,
|
||||
Earth,
|
||||
Mars,
|
||||
Jupiter,
|
||||
Saturn,
|
||||
Uranus,
|
||||
Neptune,
|
||||
Pluto
|
||||
}
|
||||
|
||||
public class CalendarManager : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Calendar calendar;
|
||||
[SerializeField] private PlanetSpin planetSpin;
|
||||
|
||||
[SerializeField] private PlanetType planetType = PlanetType.Earth;
|
||||
|
||||
private DateTime _currentDate;
|
||||
|
||||
private float _timer = 0f;
|
||||
private float _planetDayProgress = 0f;
|
||||
|
||||
private float _baseRotationSpeed;
|
||||
|
||||
private Dictionary<PlanetType, float> _planetDayLength =
|
||||
new Dictionary<PlanetType, float>()
|
||||
{
|
||||
{ PlanetType.Mercury, 58.6f },
|
||||
{ PlanetType.Venus, 243f },
|
||||
{ PlanetType.Earth, 1f },
|
||||
{ PlanetType.Mars, 1.03f },
|
||||
{ PlanetType.Jupiter, 0.41f },
|
||||
{ PlanetType.Saturn, 0.44f },
|
||||
{ PlanetType.Uranus, 0.72f },
|
||||
{ PlanetType.Neptune, 0.67f },
|
||||
{ PlanetType.Pluto, 6.39f }
|
||||
};
|
||||
|
||||
private Dictionary<PlanetType, float> _baseRotationSpeeds =
|
||||
new Dictionary<PlanetType, float>()
|
||||
{
|
||||
{ PlanetType.Mercury, 0.26f },
|
||||
{ PlanetType.Venus, -0.025f },
|
||||
{ PlanetType.Earth, 15f },
|
||||
{ PlanetType.Mars, 14.6f },
|
||||
{ PlanetType.Jupiter, 36.4f },
|
||||
{ PlanetType.Saturn, 33.6f },
|
||||
{ PlanetType.Uranus, -20.9f },
|
||||
{ PlanetType.Neptune, 22.4f },
|
||||
{ PlanetType.Pluto, -2.35f }
|
||||
};
|
||||
|
||||
void Start()
|
||||
{
|
||||
_currentDate = DateTime.Now;
|
||||
|
||||
ApplyPlanetSettings();
|
||||
|
||||
if (calendar != null)
|
||||
calendar.SetDate(_currentDate);
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
CheckResetInput();
|
||||
|
||||
if (planetSpin == null) return;
|
||||
|
||||
if (Mathf.Abs(_baseRotationSpeed) < 0.0001f) return;
|
||||
|
||||
float currentSpeed = planetSpin.RotationSpeed;
|
||||
|
||||
float speedRatio = currentSpeed / _baseRotationSpeed;
|
||||
|
||||
if (Mathf.Abs(speedRatio) < 0.0001f) return;
|
||||
|
||||
float secondsPerEarthDay = 1f / Mathf.Abs(speedRatio);
|
||||
|
||||
_timer += Time.deltaTime;
|
||||
|
||||
if (_timer >= secondsPerEarthDay)
|
||||
{
|
||||
_timer = 0f;
|
||||
|
||||
float planetMultiplier =
|
||||
1f / _planetDayLength[planetType];
|
||||
|
||||
_planetDayProgress += planetMultiplier;
|
||||
|
||||
if (_planetDayProgress >= 1f)
|
||||
{
|
||||
int daysToAdd =
|
||||
Mathf.FloorToInt(_planetDayProgress);
|
||||
|
||||
_currentDate =
|
||||
_currentDate.AddDays(daysToAdd);
|
||||
|
||||
_planetDayProgress -= daysToAdd;
|
||||
|
||||
if (calendar != null)
|
||||
calendar.SetDate(_currentDate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ChangePlanet(PlanetType newPlanet)
|
||||
{
|
||||
planetType = newPlanet;
|
||||
ApplyPlanetSettings();
|
||||
}
|
||||
|
||||
private void ApplyPlanetSettings()
|
||||
{
|
||||
_baseRotationSpeed =
|
||||
_baseRotationSpeeds[planetType];
|
||||
|
||||
if (planetSpin != null)
|
||||
planetSpin.SetRotationSpeed(
|
||||
_baseRotationSpeed);
|
||||
|
||||
_planetDayProgress = 0f;
|
||||
_timer = 0f;
|
||||
}
|
||||
|
||||
private void CheckResetInput()
|
||||
{
|
||||
for (int i = 0; i <= 9; i++)
|
||||
{
|
||||
if (Input.GetKeyDown(KeyCode.Alpha0 + i) ||
|
||||
Input.GetKeyDown(KeyCode.Keypad0 + i))
|
||||
{
|
||||
ResetToBaseSpeed();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ResetToBaseSpeed()
|
||||
{
|
||||
if (planetSpin == null) return;
|
||||
|
||||
planetSpin.SetRotationSpeed(
|
||||
_baseRotationSpeed);
|
||||
|
||||
_timer = 0f;
|
||||
_planetDayProgress = 0f;
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/CalendarManager.cs.meta
Normal file
11
Assets/Scripts/CalendarManager.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 417b78b32d1a42443891caffbd20b9bf
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
241
Assets/Scripts/CameraController.cs
Normal file
241
Assets/Scripts/CameraController.cs
Normal file
@@ -0,0 +1,241 @@
|
||||
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, Vector3.up);
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/CameraController.cs.meta
Normal file
11
Assets/Scripts/CameraController.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 09215415902ffb443a9218882c828949
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
45
Assets/Scripts/CameraManager.cs
Normal file
45
Assets/Scripts/CameraManager.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class CameraManager : MonoBehaviour
|
||||
{
|
||||
[Header("Cameras")]
|
||||
[SerializeField] private Camera planetCamera;
|
||||
[SerializeField] private Camera zodiacCamera;
|
||||
|
||||
[Header("Modes")]
|
||||
public bool planetsMode = true;
|
||||
public bool zodiacMode = false;
|
||||
|
||||
void Start()
|
||||
{
|
||||
ApplyMode();
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (Input.GetKeyDown(KeyCode.P))
|
||||
{
|
||||
planetsMode = true;
|
||||
zodiacMode = false;
|
||||
ApplyMode();
|
||||
}
|
||||
|
||||
if (Input.GetKeyDown(KeyCode.Z))
|
||||
{
|
||||
planetsMode = false;
|
||||
zodiacMode = true;
|
||||
ApplyMode();
|
||||
}
|
||||
}
|
||||
|
||||
public void ApplyMode()
|
||||
{
|
||||
if (planetCamera != null)
|
||||
planetCamera.enabled = planetsMode;
|
||||
|
||||
if (zodiacCamera != null)
|
||||
zodiacCamera.enabled = zodiacMode;
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/CameraManager.cs.meta
Normal file
11
Assets/Scripts/CameraManager.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 18092287e6b14e74ea4080a9936907b1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
26
Assets/Scripts/CanvasFollowPlanet.cs
Normal file
26
Assets/Scripts/CanvasFollowPlanet.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class CanvasFollowPlanet : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Transform planet;
|
||||
[SerializeField] private Vector3 worldOffset = new Vector3(0, 5, 0);
|
||||
[SerializeField] private Camera mainCamera;
|
||||
|
||||
void Start()
|
||||
{
|
||||
if (mainCamera == null)
|
||||
mainCamera = Camera.main;
|
||||
}
|
||||
|
||||
void LateUpdate()
|
||||
{
|
||||
if (mainCamera == null || planet == null) return;
|
||||
|
||||
transform.position = planet.position + worldOffset;
|
||||
|
||||
Vector3 lookDirection = mainCamera.transform.position - transform.position;
|
||||
transform.rotation = Quaternion.LookRotation(-lookDirection, Vector3.up);
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/CanvasFollowPlanet.cs.meta
Normal file
11
Assets/Scripts/CanvasFollowPlanet.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 67de00eb09b341c4c8960857471bec30
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
168
Assets/Scripts/CarPatrol.cs
Normal file
168
Assets/Scripts/CarPatrol.cs
Normal file
@@ -0,0 +1,168 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
public class CarPatrol : MonoBehaviour
|
||||
{
|
||||
[Header("Waypoints")]
|
||||
[SerializeField] private Transform[] waypoints;
|
||||
|
||||
[Header("Movement")]
|
||||
[SerializeField] private float patrolSpeed = 5f;
|
||||
[SerializeField] private float chaseSpeed = 12f;
|
||||
[SerializeField] private float acceleration = 3f;
|
||||
[SerializeField] private float rotationSpeed = 6f;
|
||||
|
||||
[Header("Detection")]
|
||||
[SerializeField] private float detectionDistance = 20f;
|
||||
|
||||
[Header("Siren Reference")]
|
||||
[SerializeField] private PoliceSiren siren;
|
||||
|
||||
private Transform _player;
|
||||
private int _currentWaypointIndex;
|
||||
private float _currentSpeed;
|
||||
private bool _isChasing;
|
||||
|
||||
void Start()
|
||||
{
|
||||
_player = GameObject.FindGameObjectWithTag("Player")?.transform;
|
||||
|
||||
_currentSpeed = patrolSpeed;
|
||||
|
||||
if (siren != null)
|
||||
siren.isSirenOn = false;
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (_player == null || waypoints.Length == 0) return;
|
||||
|
||||
DetectPlayer();
|
||||
|
||||
if (_isChasing)
|
||||
ChasePlayer();
|
||||
else
|
||||
Patrol();
|
||||
}
|
||||
|
||||
private void Patrol()
|
||||
{
|
||||
_currentSpeed = patrolSpeed;
|
||||
|
||||
Vector3 target = waypoints[_currentWaypointIndex].position;
|
||||
|
||||
MoveTowards(target);
|
||||
RotateTowards(target);
|
||||
|
||||
if (Vector3.Distance(transform.position, target) < 0.5f)
|
||||
{
|
||||
_currentWaypointIndex++;
|
||||
if (_currentWaypointIndex >= waypoints.Length)
|
||||
_currentWaypointIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void ChasePlayer()
|
||||
{
|
||||
_currentSpeed = Mathf.MoveTowards(
|
||||
_currentSpeed,
|
||||
chaseSpeed,
|
||||
acceleration * Time.deltaTime
|
||||
);
|
||||
|
||||
MoveTowards(_player.position);
|
||||
RotateTowards(_player.position);
|
||||
}
|
||||
|
||||
private void DetectPlayer()
|
||||
{
|
||||
if (_player == null) return;
|
||||
|
||||
Vector3 toPlayer = _player.position - transform.position;
|
||||
|
||||
float distance = toPlayer.magnitude;
|
||||
if (distance > detectionDistance)
|
||||
{
|
||||
StopChase();
|
||||
return;
|
||||
}
|
||||
|
||||
Vector3 direction = toPlayer.normalized;
|
||||
float dot = Vector3.Dot(transform.forward, direction);
|
||||
if (dot < 0.5f)
|
||||
{
|
||||
StopChase();
|
||||
return;
|
||||
}
|
||||
|
||||
float lateralDistance = Vector3.Cross(transform.forward, toPlayer).magnitude;
|
||||
|
||||
if (lateralDistance > 2f)
|
||||
{
|
||||
StopChase();
|
||||
return;
|
||||
}
|
||||
|
||||
StartChase();
|
||||
}
|
||||
|
||||
private void StartChase()
|
||||
{
|
||||
if (_isChasing) return;
|
||||
|
||||
_isChasing = true;
|
||||
|
||||
if (siren != null)
|
||||
siren.isSirenOn = true;
|
||||
}
|
||||
|
||||
private void StopChase()
|
||||
{
|
||||
if (!_isChasing) return;
|
||||
|
||||
_isChasing = false;
|
||||
_currentSpeed = patrolSpeed;
|
||||
|
||||
if (siren != null)
|
||||
siren.isSirenOn = false;
|
||||
}
|
||||
|
||||
private void MoveTowards(Vector3 target)
|
||||
{
|
||||
Vector3 targetPos = new Vector3(target.x, transform.position.y, target.z);
|
||||
Vector3 direction = (targetPos - transform.position).normalized;
|
||||
|
||||
transform.position += direction * _currentSpeed * Time.deltaTime;
|
||||
}
|
||||
|
||||
private void RotateTowards(Vector3 target)
|
||||
{
|
||||
Vector3 direction = new Vector3(
|
||||
target.x - transform.position.x,
|
||||
0f,
|
||||
target.z - transform.position.z
|
||||
);
|
||||
|
||||
if (direction == Vector3.zero) return;
|
||||
|
||||
Quaternion targetRotation = Quaternion.LookRotation(direction);
|
||||
|
||||
transform.rotation = Quaternion.Slerp(
|
||||
transform.rotation,
|
||||
targetRotation,
|
||||
rotationSpeed * Time.deltaTime
|
||||
);
|
||||
}
|
||||
|
||||
private void OnCollisionEnter(Collision collision)
|
||||
{
|
||||
|
||||
if (collision.gameObject.CompareTag("Player"))
|
||||
{
|
||||
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
11
Assets/Scripts/CarPatrol.cs.meta
Normal file
11
Assets/Scripts/CarPatrol.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a2d5c5ea5a3d02249a65c2a26c37afbf
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
38
Assets/Scripts/CarouselRotate.cs
Normal file
38
Assets/Scripts/CarouselRotate.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class CarouselRotate : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Transform swing;
|
||||
[SerializeField] private float rotationSpeed = 60f;
|
||||
[SerializeField] private Vector3 rotationAxis = Vector3.up;
|
||||
|
||||
private bool _isActive;
|
||||
|
||||
private void Reset()
|
||||
{
|
||||
swing = transform.parent;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (!_isActive || swing == null) return;
|
||||
|
||||
swing.Rotate(rotationAxis.normalized * rotationSpeed * Time.deltaTime, Space.Self);
|
||||
}
|
||||
|
||||
private void OnTriggerEnter(Collider other)
|
||||
{
|
||||
if (!other.CompareTag("Player")) return;
|
||||
|
||||
_isActive = true;
|
||||
}
|
||||
|
||||
private void OnTriggerExit(Collider other)
|
||||
{
|
||||
if (!other.CompareTag("Player")) return;
|
||||
|
||||
_isActive = false;
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/CarouselRotate.cs.meta
Normal file
11
Assets/Scripts/CarouselRotate.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 82753284bf0791c4f969ff2cdafb37ec
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
141
Assets/Scripts/CelestialCalendarController.cs
Normal file
141
Assets/Scripts/CelestialCalendarController.cs
Normal file
@@ -0,0 +1,141 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class CelestialCalendarController : MonoBehaviour
|
||||
{
|
||||
[System.Serializable]
|
||||
public class PlanetCalendar
|
||||
{
|
||||
public GameObject planet;
|
||||
public GameObject calendar;
|
||||
public GameObject monthText;
|
||||
public GameObject daysGrid;
|
||||
public GameObject infoText;
|
||||
}
|
||||
|
||||
[SerializeField] private List<PlanetCalendar> planetCalendars;
|
||||
private GameObject _activeCalendar;
|
||||
private PlanetCalendar _activeItem;
|
||||
private Camera _activeCamera;
|
||||
|
||||
void Start()
|
||||
{
|
||||
foreach (var item in planetCalendars)
|
||||
{
|
||||
if (item.calendar != null)
|
||||
item.calendar.SetActive(false);
|
||||
if (item.infoText != null)
|
||||
item.infoText.SetActive(false);
|
||||
}
|
||||
UpdateActiveCamera();
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
UpdateActiveCamera();
|
||||
if (_activeCamera == null) return;
|
||||
|
||||
for (int i = 0; i <= 9; i++)
|
||||
{
|
||||
if (Input.GetKeyDown(KeyCode.Alpha0 + i) ||
|
||||
Input.GetKeyDown(KeyCode.Keypad0 + i))
|
||||
{
|
||||
HideActive();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (Input.GetKeyDown(KeyCode.UpArrow) || Input.GetKeyDown(KeyCode.DownArrow))
|
||||
{
|
||||
ToggleInfoMode();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Input.GetMouseButtonDown(0)) return;
|
||||
|
||||
Ray ray = _activeCamera.ScreenPointToRay(Input.mousePosition);
|
||||
RaycastHit hit;
|
||||
|
||||
if (!Physics.Raycast(ray, out hit))
|
||||
{
|
||||
HideActive();
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var item in planetCalendars)
|
||||
{
|
||||
if (item.planet == null) continue;
|
||||
if (hit.collider.gameObject == item.planet ||
|
||||
hit.collider.transform.IsChildOf(item.planet.transform))
|
||||
{
|
||||
ToggleCalendar(item);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
HideActive();
|
||||
}
|
||||
|
||||
void UpdateActiveCamera()
|
||||
{
|
||||
Camera[] cameras = Camera.allCameras;
|
||||
foreach (var cam in cameras)
|
||||
{
|
||||
if (cam.enabled && cam.gameObject.activeInHierarchy)
|
||||
{
|
||||
_activeCamera = cam;
|
||||
return;
|
||||
}
|
||||
}
|
||||
_activeCamera = null;
|
||||
}
|
||||
|
||||
void ToggleCalendar(PlanetCalendar item)
|
||||
{
|
||||
if (item.calendar == null) return;
|
||||
|
||||
if (_activeCalendar == item.calendar)
|
||||
{
|
||||
HideActive();
|
||||
return;
|
||||
}
|
||||
|
||||
HideActive();
|
||||
item.calendar.SetActive(true);
|
||||
|
||||
if (item.monthText != null) item.monthText.SetActive(true);
|
||||
if (item.daysGrid != null) item.daysGrid.SetActive(true);
|
||||
if (item.infoText != null) item.infoText.SetActive(false);
|
||||
|
||||
_activeCalendar = item.calendar;
|
||||
_activeItem = item;
|
||||
}
|
||||
|
||||
void ToggleInfoMode()
|
||||
{
|
||||
if (_activeItem == null) return;
|
||||
|
||||
bool infoActive = _activeItem.infoText != null && _activeItem.infoText.activeSelf;
|
||||
|
||||
if (_activeItem.monthText != null) _activeItem.monthText.SetActive(infoActive);
|
||||
if (_activeItem.daysGrid != null) _activeItem.daysGrid.SetActive(infoActive);
|
||||
if (_activeItem.infoText != null) _activeItem.infoText.SetActive(!infoActive);
|
||||
}
|
||||
|
||||
void HideActive()
|
||||
{
|
||||
if (_activeCalendar != null)
|
||||
{
|
||||
if (_activeItem != null)
|
||||
{
|
||||
if (_activeItem.monthText != null) _activeItem.monthText.SetActive(true);
|
||||
if (_activeItem.daysGrid != null) _activeItem.daysGrid.SetActive(true);
|
||||
if (_activeItem.infoText != null) _activeItem.infoText.SetActive(false);
|
||||
}
|
||||
_activeCalendar.SetActive(false);
|
||||
_activeCalendar = null;
|
||||
_activeItem = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/CelestialCalendarController.cs.meta
Normal file
11
Assets/Scripts/CelestialCalendarController.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d8a2451b673893c4da97804e208be5a8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
242
Assets/Scripts/ChildAnimController.cs
Normal file
242
Assets/Scripts/ChildAnimController.cs
Normal file
@@ -0,0 +1,242 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using TMPro;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class ChildAnimController : MonoBehaviour
|
||||
{
|
||||
[Header("Animations")]
|
||||
[SerializeField] private string idleAnimation1 = "idle_m_2_220f";
|
||||
[SerializeField] private string idleAnimation2 = "idle_selfcheck_1_300f";
|
||||
[SerializeField] private string walkAnimation = "locom_m_basicWalk_30f";
|
||||
[SerializeField] private string talkingAnimation = "idle_phoneTalking_180f";
|
||||
|
||||
[Header("Movement Points")]
|
||||
[SerializeField] private Transform targetPoint1;
|
||||
[SerializeField] private Transform targetPoint2;
|
||||
|
||||
[Header("Light Check")]
|
||||
[SerializeField] private LightManager lightManager;
|
||||
[SerializeField] private int requiredLights = 9;
|
||||
[SerializeField] private string successMessage = "×óäîâî! Ïðåçåíòóé ïåðåä êëàñîì ñâîþ äóìêó!";
|
||||
[SerializeField] private string failMessage = "Òè ùå íå çàâåðøèâ çàâäàííÿ, ñïðîáóé ùå!";
|
||||
|
||||
[Header("Movement Settings")]
|
||||
[SerializeField] private float walkSpeed = 1f;
|
||||
[SerializeField] private float waitTime = 3f;
|
||||
[SerializeField] private float rotationSpeed = 5f;
|
||||
[SerializeField] private float gravity = 9.81f;
|
||||
[SerializeField] private float stopDistance = 0.25f;
|
||||
|
||||
[Header("Dialogue Settings")]
|
||||
[SerializeField] private float talkDuration = 7f;
|
||||
[SerializeField] private float interactionCooldown = 10f;
|
||||
[SerializeField] private float textHeight = 1f;
|
||||
[SerializeField] private GameObject existingCanvas;
|
||||
[SerializeField] private TextMeshProUGUI existingTextMesh;
|
||||
|
||||
private Animator _animator;
|
||||
private CharacterController _characterController;
|
||||
|
||||
private bool _isTalking;
|
||||
private bool _canInteract = true;
|
||||
private float _verticalVelocity;
|
||||
private Transform _player;
|
||||
|
||||
private Coroutine _walkRoutine;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
_animator = GetComponent<Animator>();
|
||||
|
||||
_characterController = GetComponent<CharacterController>();
|
||||
if (_characterController == null)
|
||||
{
|
||||
_characterController = gameObject.AddComponent<CharacterController>();
|
||||
_characterController.height = 1f;
|
||||
_characterController.radius = 0.3f;
|
||||
_characterController.center = new Vector3(0f, 0.5f, 0f);
|
||||
}
|
||||
|
||||
if (existingCanvas != null)
|
||||
{
|
||||
existingCanvas.transform.SetParent(transform);
|
||||
existingCanvas.transform.localPosition = new Vector3(0f, textHeight, 0f);
|
||||
existingCanvas.SetActive(false);
|
||||
}
|
||||
|
||||
_walkRoutine = StartCoroutine(WalkRoutine());
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (existingCanvas != null && existingCanvas.activeSelf)
|
||||
{
|
||||
Camera cam = Camera.main;
|
||||
if (cam != null)
|
||||
{
|
||||
Vector3 dir = existingCanvas.transform.position - cam.transform.position;
|
||||
if (dir != Vector3.zero)
|
||||
existingCanvas.transform.rotation = Quaternion.LookRotation(dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator WalkRoutine()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (_isTalking)
|
||||
{
|
||||
yield return null;
|
||||
continue;
|
||||
}
|
||||
|
||||
PlayAnimation(idleAnimation1);
|
||||
yield return new WaitForSeconds(waitTime);
|
||||
|
||||
if (targetPoint1 != null)
|
||||
{
|
||||
yield return WalkToPoint(targetPoint1.position);
|
||||
yield return TurnToFaceDirection(targetPoint2 != null ? targetPoint2.position : transform.forward);
|
||||
}
|
||||
|
||||
if (_isTalking) continue;
|
||||
|
||||
PlayAnimation(idleAnimation2);
|
||||
yield return new WaitForSeconds(waitTime);
|
||||
|
||||
if (targetPoint2 != null)
|
||||
{
|
||||
yield return WalkToPoint(targetPoint2.position);
|
||||
yield return TurnToFaceDirection(targetPoint1 != null ? targetPoint1.position : transform.forward);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator WalkToPoint(Vector3 targetPosition)
|
||||
{
|
||||
PlayAnimation(walkAnimation);
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (_isTalking) yield break;
|
||||
|
||||
Vector3 fromXZ = new Vector3(transform.position.x, 0f, transform.position.z);
|
||||
Vector3 toXZ = new Vector3(targetPosition.x, 0f, targetPosition.z);
|
||||
|
||||
float dist = Vector3.Distance(fromXZ, toXZ);
|
||||
if (dist <= stopDistance)
|
||||
{
|
||||
_verticalVelocity = -0.5f;
|
||||
yield break;
|
||||
}
|
||||
|
||||
Vector3 dir = (toXZ - fromXZ).normalized;
|
||||
|
||||
if (dir != Vector3.zero)
|
||||
{
|
||||
Quaternion look = Quaternion.LookRotation(dir);
|
||||
transform.rotation = Quaternion.Slerp(transform.rotation, look, rotationSpeed * Time.deltaTime);
|
||||
}
|
||||
|
||||
if (_characterController.isGrounded)
|
||||
_verticalVelocity = -0.5f;
|
||||
else
|
||||
_verticalVelocity -= gravity * Time.deltaTime;
|
||||
|
||||
Vector3 move = dir * walkSpeed;
|
||||
move.y = _verticalVelocity;
|
||||
|
||||
_characterController.Move(move * Time.deltaTime);
|
||||
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator TurnToFaceDirection(Vector3 targetPosition)
|
||||
{
|
||||
Vector3 dir = targetPosition - transform.position;
|
||||
dir.y = 0f;
|
||||
|
||||
if (dir == Vector3.zero) yield break;
|
||||
|
||||
Quaternion targetRot = Quaternion.LookRotation(dir.normalized);
|
||||
|
||||
while (Quaternion.Angle(transform.rotation, targetRot) > 1f)
|
||||
{
|
||||
if (_isTalking) yield break;
|
||||
transform.rotation = Quaternion.Slerp(transform.rotation, targetRot, rotationSpeed * Time.deltaTime);
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTriggerEnter(Collider other)
|
||||
{
|
||||
if (!other.CompareTag("Player")) return;
|
||||
if (!_canInteract) return;
|
||||
if (_isTalking) return;
|
||||
|
||||
_player = other.transform;
|
||||
StartCoroutine(TalkToPlayer());
|
||||
}
|
||||
|
||||
private IEnumerator TalkToPlayer()
|
||||
{
|
||||
_isTalking = true;
|
||||
_canInteract = false;
|
||||
|
||||
if (_walkRoutine != null)
|
||||
StopCoroutine(_walkRoutine);
|
||||
|
||||
if (_player != null)
|
||||
{
|
||||
Vector3 dir = _player.position - transform.position;
|
||||
dir.y = 0f;
|
||||
if (dir != Vector3.zero)
|
||||
transform.rotation = Quaternion.LookRotation(dir.normalized);
|
||||
}
|
||||
|
||||
PlayAnimation(talkingAnimation);
|
||||
|
||||
if (existingTextMesh != null)
|
||||
{
|
||||
if (lightManager != null && lightManager.CurrentLights >= requiredLights)
|
||||
existingTextMesh.text = successMessage;
|
||||
else
|
||||
existingTextMesh.text = failMessage;
|
||||
}
|
||||
|
||||
if (existingCanvas != null)
|
||||
existingCanvas.SetActive(true);
|
||||
|
||||
yield return new WaitForSeconds(talkDuration);
|
||||
|
||||
EndTalk();
|
||||
}
|
||||
|
||||
private void EndTalk()
|
||||
{
|
||||
if (existingCanvas != null)
|
||||
existingCanvas.SetActive(false);
|
||||
|
||||
_isTalking = false;
|
||||
|
||||
StartCoroutine(CooldownRoutine());
|
||||
_walkRoutine = StartCoroutine(WalkRoutine());
|
||||
}
|
||||
|
||||
private IEnumerator CooldownRoutine()
|
||||
{
|
||||
yield return new WaitForSeconds(interactionCooldown);
|
||||
_canInteract = true;
|
||||
}
|
||||
|
||||
private void PlayAnimation(string animationName)
|
||||
{
|
||||
if (_animator == null) return;
|
||||
if (string.IsNullOrEmpty(animationName)) return;
|
||||
_animator.CrossFade(animationName, 0.2f);
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/ChildAnimController.cs.meta
Normal file
11
Assets/Scripts/ChildAnimController.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fc8be32ead36a674c91ed85d24f20c51
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
196
Assets/Scripts/Constellation.cs
Normal file
196
Assets/Scripts/Constellation.cs
Normal file
@@ -0,0 +1,196 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class Constellation : MonoBehaviour
|
||||
{
|
||||
[Header("Режим малювання")]
|
||||
public bool editMode = false;
|
||||
[Header("Максимальна кількіссть зірок")]
|
||||
public int maxStars = 10;
|
||||
|
||||
[Header("Матеріали")]
|
||||
[SerializeField] private GameObject starPrefab;
|
||||
[SerializeField] private Material lineMaterial;
|
||||
|
||||
[Header("Відстань")]
|
||||
[SerializeField] private float planeDistance = 8f;
|
||||
|
||||
[Header("Розміри")]
|
||||
[SerializeField] private float starScaleMin = 0.06f;
|
||||
[SerializeField] private float starScaleMax = 0.14f;
|
||||
[SerializeField] private float lineWidth = 0.02f;
|
||||
|
||||
private readonly List<Transform> _stars = new List<Transform>();
|
||||
private readonly List<LineRenderer> _lines = new List<LineRenderer>();
|
||||
|
||||
private Transform _root;
|
||||
private Camera _cam;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
EnsureCameraAndRoot();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (!editMode) return;
|
||||
|
||||
EnsureCameraAndRoot();
|
||||
|
||||
if (_cam == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Input.GetMouseButtonDown(0))
|
||||
{
|
||||
TryAddStarByClick(Input.mousePosition);
|
||||
}
|
||||
|
||||
UpdateAllLines();
|
||||
}
|
||||
|
||||
private void EnsureCameraAndRoot()
|
||||
{
|
||||
if (_cam == null || !_cam.enabled)
|
||||
{
|
||||
_cam = FindEnabledCamera();
|
||||
}
|
||||
|
||||
if (_cam != null && (_root == null || _root.parent != _cam.transform))
|
||||
{
|
||||
if (_root == null)
|
||||
{
|
||||
GameObject go = new GameObject("ConstellationRoot");
|
||||
_root = go.transform;
|
||||
}
|
||||
|
||||
_root.SetParent(_cam.transform);
|
||||
_root.localPosition = new Vector3(0f, 0f, planeDistance);
|
||||
_root.localRotation = Quaternion.identity;
|
||||
_root.localScale = Vector3.one;
|
||||
}
|
||||
}
|
||||
|
||||
private Camera FindEnabledCamera()
|
||||
{
|
||||
Camera[] cams = Camera.allCameras;
|
||||
for (int i = 0; i < cams.Length; i++)
|
||||
{
|
||||
if (cams[i] != null && cams[i].enabled && cams[i].gameObject.activeInHierarchy)
|
||||
return cams[i];
|
||||
}
|
||||
|
||||
if (Camera.main != null && Camera.main.enabled)
|
||||
return Camera.main;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void TryAddStarByClick(Vector3 screenPos)
|
||||
{
|
||||
Ray ray = _cam.ScreenPointToRay(screenPos);
|
||||
|
||||
Plane plane = new Plane(_cam.transform.forward, _cam.transform.position + _cam.transform.forward * planeDistance);
|
||||
|
||||
if (!plane.Raycast(ray, out float enter))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Vector3 worldHit = ray.GetPoint(enter);
|
||||
Vector3 localHit = _root.InverseTransformPoint(worldHit);
|
||||
|
||||
GameObject starGo = Instantiate(starPrefab, _root);
|
||||
starGo.name = "Star_" + _stars.Count;
|
||||
|
||||
Transform starT = starGo.transform;
|
||||
starT.localPosition = localHit;
|
||||
|
||||
float rndScale = Random.Range(starScaleMin, starScaleMax);
|
||||
starT.localScale = Vector3.one * rndScale;
|
||||
|
||||
_stars.Add(starT);
|
||||
|
||||
if (_stars.Count >= 2)
|
||||
{
|
||||
CreateLine(_stars[_stars.Count - 2], _stars[_stars.Count - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateLine(Transform a, Transform b)
|
||||
{
|
||||
if (a == null || b == null) return;
|
||||
|
||||
GameObject lineGo = new GameObject("Line_" + _lines.Count);
|
||||
lineGo.transform.SetParent(_root);
|
||||
lineGo.transform.localPosition = Vector3.zero;
|
||||
lineGo.transform.localRotation = Quaternion.identity;
|
||||
lineGo.transform.localScale = Vector3.one;
|
||||
|
||||
LineRenderer lr = lineGo.AddComponent<LineRenderer>();
|
||||
|
||||
if (lineMaterial != null)
|
||||
{
|
||||
lr.material = lineMaterial;
|
||||
}
|
||||
else
|
||||
{
|
||||
Material fallback = new Material(Shader.Find("Unlit/Color"));
|
||||
fallback.color = new Color(0.7f, 0.85f, 1f, 1f);
|
||||
lr.material = fallback;
|
||||
}
|
||||
|
||||
lr.useWorldSpace = false;
|
||||
lr.positionCount = 2;
|
||||
lr.startWidth = lineWidth;
|
||||
lr.endWidth = lineWidth;
|
||||
|
||||
lr.numCapVertices = 6;
|
||||
lr.numCornerVertices = 6;
|
||||
|
||||
_lines.Add(lr);
|
||||
|
||||
lr.SetPosition(0, a.localPosition);
|
||||
lr.SetPosition(1, b.localPosition);
|
||||
}
|
||||
|
||||
private void UpdateAllLines()
|
||||
{
|
||||
int needed = Mathf.Max(0, _stars.Count - 1);
|
||||
if (_lines.Count < needed) return;
|
||||
|
||||
for (int i = 0; i < needed; i++)
|
||||
{
|
||||
LineRenderer lr = _lines[i];
|
||||
if (lr == null) continue;
|
||||
|
||||
Transform a = _stars[i];
|
||||
Transform b = _stars[i + 1];
|
||||
|
||||
if (a == null || b == null) continue;
|
||||
|
||||
lr.SetPosition(0, a.localPosition);
|
||||
lr.SetPosition(1, b.localPosition);
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearAll()
|
||||
{
|
||||
for (int i = 0; i < _lines.Count; i++)
|
||||
{
|
||||
if (_lines[i] != null) Destroy(_lines[i].gameObject);
|
||||
}
|
||||
|
||||
for (int i = 0; i < _stars.Count; i++)
|
||||
{
|
||||
if (_stars[i] != null) Destroy(_stars[i].gameObject);
|
||||
}
|
||||
|
||||
_lines.Clear();
|
||||
_stars.Clear();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
11
Assets/Scripts/Constellation.cs.meta
Normal file
11
Assets/Scripts/Constellation.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 88f4e4721ea8d144cac21d732d053f30
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Scripts/ConstellationManager.cs
Normal file
8
Assets/Scripts/ConstellationManager.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class ConstellationManager : MonoBehaviour
|
||||
{
|
||||
|
||||
}
|
||||
11
Assets/Scripts/ConstellationManager.cs.meta
Normal file
11
Assets/Scripts/ConstellationManager.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8357f6bd3c528a4479c2717bd97bf93f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
50
Assets/Scripts/CustomCursor.cs
Normal file
50
Assets/Scripts/CustomCursor.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class CustomCursor : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Texture2D cursorTexture;
|
||||
[SerializeField] private Vector2 hotspot = Vector2.zero;
|
||||
[SerializeField] private CursorMode cursorMode = CursorMode.Auto;
|
||||
[SerializeField] private LightManager lightManager;
|
||||
|
||||
private bool _isCustomCursorActive = false;
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (lightManager != null)
|
||||
{
|
||||
GameObject lightPanel = lightManager.GetLightPanel();
|
||||
|
||||
if (lightPanel != null && lightPanel.activeSelf && !_isCustomCursorActive)
|
||||
{
|
||||
SetCustomCursor();
|
||||
}
|
||||
else if ((lightPanel == null || !lightPanel.activeSelf) && _isCustomCursorActive)
|
||||
{
|
||||
SetDefaultCursor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SetCustomCursor()
|
||||
{
|
||||
if (cursorTexture != null)
|
||||
{
|
||||
Cursor.SetCursor(cursorTexture, hotspot, cursorMode);
|
||||
_isCustomCursorActive = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetDefaultCursor()
|
||||
{
|
||||
Cursor.SetCursor(null, Vector2.zero, CursorMode.Auto);
|
||||
_isCustomCursorActive = false;
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
SetDefaultCursor();
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/CustomCursor.cs.meta
Normal file
11
Assets/Scripts/CustomCursor.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dd18cf7247b9f1e43a75c310cc405f22
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
111
Assets/Scripts/ElectricGenerator.cs
Normal file
111
Assets/Scripts/ElectricGenerator.cs
Normal file
@@ -0,0 +1,111 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using TMPro;
|
||||
|
||||
public class ElectricGenerator : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private GameObject canvasObject;
|
||||
[SerializeField] private TextMeshProUGUI messageText;
|
||||
|
||||
[Header("Optional")]
|
||||
[SerializeField] private string lampTag = "LampLight";
|
||||
[SerializeField] private string lockChildName = "Lock";
|
||||
|
||||
private string[] _randomMessages =
|
||||
{
|
||||
"Õìì... ö³êàâî äëÿ ÷îãî öåé çàìîê...",
|
||||
"Õìì... ñõîæå ùîñü çàãóáèëîñÿ...",
|
||||
"Òóò òî÷íî ùîñü íå âèñòà÷àº..."
|
||||
};
|
||||
|
||||
private List<GameObject> _lamps = new List<GameObject>();
|
||||
private bool _activated;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (canvasObject != null) canvasObject.SetActive(false);
|
||||
|
||||
_lamps = FindSceneObjectsWithTagIncludingInactive(lampTag);
|
||||
|
||||
for (int i = 0; i < _lamps.Count; i++)
|
||||
{
|
||||
if (_lamps[i] != null)
|
||||
_lamps[i].SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTriggerEnter(Collider other)
|
||||
{
|
||||
if (!other.CompareTag("Player")) return;
|
||||
|
||||
if (!KeyPickup.HasKey)
|
||||
{
|
||||
ShowRandomMessage();
|
||||
return;
|
||||
}
|
||||
|
||||
if (_activated) return;
|
||||
|
||||
ActivateLights();
|
||||
}
|
||||
|
||||
private void OnTriggerExit(Collider other)
|
||||
{
|
||||
if (!other.CompareTag("Player")) return;
|
||||
if (canvasObject != null) canvasObject.SetActive(false);
|
||||
}
|
||||
|
||||
private void ShowRandomMessage()
|
||||
{
|
||||
if (canvasObject != null) canvasObject.SetActive(true);
|
||||
|
||||
int index = Random.Range(0, _randomMessages.Length);
|
||||
if (messageText != null) messageText.text = _randomMessages[index];
|
||||
}
|
||||
|
||||
private void ActivateLights()
|
||||
{
|
||||
if (canvasObject != null) canvasObject.SetActive(false);
|
||||
|
||||
if (_lamps == null || _lamps.Count == 0)
|
||||
_lamps = FindSceneObjectsWithTagIncludingInactive(lampTag);
|
||||
|
||||
int activatedCount = 0;
|
||||
|
||||
for (int i = 0; i < _lamps.Count; i++)
|
||||
{
|
||||
GameObject lamp = _lamps[i];
|
||||
if (lamp == null) continue;
|
||||
|
||||
lamp.SetActive(true);
|
||||
activatedCount++;
|
||||
}
|
||||
|
||||
Transform lockTr = transform.Find(lockChildName);
|
||||
if (lockTr != null)
|
||||
Destroy(lockTr.gameObject);
|
||||
|
||||
_activated = true;
|
||||
}
|
||||
|
||||
private List<GameObject> FindSceneObjectsWithTagIncludingInactive(string tag)
|
||||
{
|
||||
var result = new List<GameObject>();
|
||||
|
||||
GameObject[] all = Resources.FindObjectsOfTypeAll<GameObject>();
|
||||
|
||||
for (int i = 0; i < all.Length; i++)
|
||||
{
|
||||
GameObject go = all[i];
|
||||
if (go == null) continue;
|
||||
if (!go.scene.IsValid() || !go.scene.isLoaded) continue;
|
||||
if (go.hideFlags != HideFlags.None) continue;
|
||||
|
||||
if (go.CompareTag(tag))
|
||||
result.Add(go);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/ElectricGenerator.cs.meta
Normal file
11
Assets/Scripts/ElectricGenerator.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 045af4e607b49b4409a99b27ac6a9b4f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
73
Assets/Scripts/GirlExercise.cs
Normal file
73
Assets/Scripts/GirlExercise.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class GirlExercise : MonoBehaviour
|
||||
{
|
||||
[Header("Àí³ìàö³¿")]
|
||||
[SerializeField] private string idleAnimation = "idle_selfcheck_1_300f";
|
||||
[SerializeField] private string exerciseAnimation = "exercise_warmingUp_170f";
|
||||
|
||||
private Animator animator;
|
||||
private AnimationClip[] animationClips;
|
||||
private float currentAnimationLength;
|
||||
private float animationTimer;
|
||||
private bool isPlaying = false;
|
||||
|
||||
void Start()
|
||||
{
|
||||
animator = GetComponent<Animator>();
|
||||
|
||||
if (animator != null)
|
||||
{
|
||||
animationClips = animator.runtimeAnimatorController.animationClips;
|
||||
PlayRandomAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (isPlaying)
|
||||
{
|
||||
animationTimer += Time.deltaTime;
|
||||
|
||||
if (animationTimer >= currentAnimationLength)
|
||||
{
|
||||
PlayRandomAnimation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void PlayRandomAnimation()
|
||||
{
|
||||
string selectedAnimation;
|
||||
|
||||
if (Random.value > 0.5f)
|
||||
{
|
||||
selectedAnimation = idleAnimation;
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedAnimation = exerciseAnimation;
|
||||
}
|
||||
|
||||
animator.Play(selectedAnimation);
|
||||
|
||||
currentAnimationLength = GetAnimationLength(selectedAnimation);
|
||||
animationTimer = 0f;
|
||||
isPlaying = true;
|
||||
}
|
||||
|
||||
private float GetAnimationLength(string animationName)
|
||||
{
|
||||
foreach (AnimationClip clip in animationClips)
|
||||
{
|
||||
if (clip.name == animationName)
|
||||
{
|
||||
return clip.length;
|
||||
}
|
||||
}
|
||||
|
||||
return 5f;
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/GirlExercise.cs.meta
Normal file
11
Assets/Scripts/GirlExercise.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d9a88bbd7a6f58b4fb2738dcdd53821c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
88
Assets/Scripts/HeroCameraController.cs
Normal file
88
Assets/Scripts/HeroCameraController.cs
Normal file
@@ -0,0 +1,88 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class HeroCameraController : MonoBehaviour
|
||||
{
|
||||
[Header("Íàëàøòóâàííÿ ìèø³")]
|
||||
[Range(1f, 10f)]
|
||||
[SerializeField] private float _mouseSensitivityX = 2f;
|
||||
|
||||
[Range(1f, 10f)]
|
||||
[Tooltip("×óòëèâ³ñòü ìèø³ ïî âåðòèêàë³")]
|
||||
[SerializeField] private float _mouseSensitivityY = 2f;
|
||||
|
||||
[Range(0f, 0.5f)]
|
||||
[SerializeField] private float _smoothTime = 0.1f;
|
||||
|
||||
[Header("Îáìåæåííÿ êóò³â")]
|
||||
[SerializeField] private float _minVerticalAngle = -75f;
|
||||
|
||||
[SerializeField] private float _maxVerticalAngle = 45f;
|
||||
|
||||
[Header("Ïîñèëàííÿ")]
|
||||
[SerializeField] private Transform _controller;
|
||||
|
||||
|
||||
private float _xRotation = 0f;
|
||||
private float _yRotation = 0f;
|
||||
|
||||
private Vector2 _currentMouseDelta;
|
||||
private Vector2 _currentMouseVelocity;
|
||||
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
HandleCameraRotation();
|
||||
}
|
||||
|
||||
private void HandleCameraRotation()
|
||||
{
|
||||
Vector2 targetMouseDelta = new Vector2(
|
||||
Input.GetAxis("Mouse X") * _mouseSensitivityX,
|
||||
Input.GetAxis("Mouse Y") * _mouseSensitivityY
|
||||
);
|
||||
|
||||
_currentMouseDelta = Vector2.SmoothDamp(
|
||||
_currentMouseDelta,
|
||||
targetMouseDelta,
|
||||
ref _currentMouseVelocity,
|
||||
_smoothTime
|
||||
);
|
||||
|
||||
_yRotation += _currentMouseDelta.x;
|
||||
_xRotation -= _currentMouseDelta.y;
|
||||
|
||||
_xRotation = Mathf.Clamp(_xRotation, _minVerticalAngle, _maxVerticalAngle);
|
||||
|
||||
transform.localRotation = Quaternion.Euler(_xRotation, 0f, 0f);
|
||||
|
||||
if (_controller != null)
|
||||
{
|
||||
_controller.rotation = Quaternion.Euler(0f, _yRotation, 0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void SetSensitivityX(float sensitivity)
|
||||
{
|
||||
_mouseSensitivityX = Mathf.Clamp(sensitivity, 1f, 10f);
|
||||
}
|
||||
|
||||
public void SetSensitivityY(float sensitivity)
|
||||
{
|
||||
_mouseSensitivityY = Mathf.Clamp(sensitivity, 1f, 10f);
|
||||
}
|
||||
|
||||
public void SetSmoothTime(float smoothTime)
|
||||
{
|
||||
_smoothTime = Mathf.Clamp(smoothTime, 0f, 0.5f);
|
||||
}
|
||||
|
||||
public void SetSensitivity(float sensitivity)
|
||||
{
|
||||
_mouseSensitivityX = Mathf.Clamp(sensitivity, 1f, 10f);
|
||||
_mouseSensitivityY = Mathf.Clamp(sensitivity, 1f, 10f);
|
||||
}
|
||||
}
|
||||
|
||||
11
Assets/Scripts/HeroCameraController.cs.meta
Normal file
11
Assets/Scripts/HeroCameraController.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7670a57d9592c0e4d9cb3fa85786b01a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
31
Assets/Scripts/KeyPickup.cs
Normal file
31
Assets/Scripts/KeyPickup.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class KeyPickup : MonoBehaviour
|
||||
{
|
||||
public static bool HasKey = false;
|
||||
|
||||
[SerializeField] private GameObject pickupEffect;
|
||||
|
||||
private void OnTriggerEnter(Collider other)
|
||||
{
|
||||
if (!other.CompareTag("Player")) return;
|
||||
|
||||
HasKey = true;
|
||||
|
||||
if (pickupEffect != null)
|
||||
{
|
||||
GameObject effect = Instantiate(
|
||||
pickupEffect,
|
||||
transform.position,
|
||||
Quaternion.identity
|
||||
);
|
||||
|
||||
Destroy(effect, 3f);
|
||||
}
|
||||
|
||||
Destroy(gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
11
Assets/Scripts/KeyPickup.cs.meta
Normal file
11
Assets/Scripts/KeyPickup.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 047289474bff9cf41bcb7572559fb4c0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
146
Assets/Scripts/LightManager.cs
Normal file
146
Assets/Scripts/LightManager.cs
Normal file
@@ -0,0 +1,146 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class LightManager : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private GameObject lightPanel;
|
||||
public int maxLights = 15;
|
||||
[SerializeField] private float maxDistance = 200f;
|
||||
|
||||
private int _currentLights = 0;
|
||||
public int CurrentLights => _currentLights;
|
||||
|
||||
private Color _selectedColor;
|
||||
private GameObject _previewObject;
|
||||
private List<GameObject> _placedLights = new List<GameObject>();
|
||||
public GameObject GetLightPanel() => lightPanel;
|
||||
|
||||
void Start()
|
||||
{
|
||||
lightPanel.SetActive(false);
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (Input.GetKeyDown(KeyCode.R))
|
||||
{
|
||||
lightPanel.SetActive(!lightPanel.activeSelf);
|
||||
|
||||
if (!lightPanel.activeSelf)
|
||||
CancelPreview();
|
||||
}
|
||||
|
||||
if (_previewObject != null)
|
||||
{
|
||||
UpdatePreviewPosition();
|
||||
|
||||
if (Input.GetMouseButtonDown(0))
|
||||
PlaceLight();
|
||||
|
||||
if (Input.GetMouseButtonDown(1))
|
||||
CancelPreview();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Input.GetMouseButtonDown(1))
|
||||
TryRemoveLight();
|
||||
}
|
||||
}
|
||||
|
||||
public void SetWhite() => CreatePreview(Color.white);
|
||||
public void SetRed() => CreatePreview(Color.red);
|
||||
public void SetBlue() => CreatePreview(Color.blue);
|
||||
public void SetGreen() => CreatePreview(Color.green);
|
||||
|
||||
private void CreatePreview(Color color)
|
||||
{
|
||||
if (_currentLights >= maxLights) return;
|
||||
|
||||
CancelPreview();
|
||||
_selectedColor = color;
|
||||
|
||||
_previewObject = new GameObject("Preview Light");
|
||||
|
||||
Light l = _previewObject.AddComponent<Light>();
|
||||
l.type = LightType.Point;
|
||||
l.range = 8f;
|
||||
l.intensity = 3f;
|
||||
l.color = _selectedColor;
|
||||
}
|
||||
|
||||
private void CancelPreview()
|
||||
{
|
||||
if (_previewObject != null)
|
||||
{
|
||||
Destroy(_previewObject);
|
||||
_previewObject = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdatePreviewPosition()
|
||||
{
|
||||
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
|
||||
|
||||
if (Physics.Raycast(ray, out RaycastHit hit, maxDistance))
|
||||
{
|
||||
_previewObject.transform.position = hit.point + hit.normal * 0.1f;
|
||||
}
|
||||
}
|
||||
|
||||
private void PlaceLight()
|
||||
{
|
||||
if (_currentLights >= maxLights) return;
|
||||
|
||||
GameObject lightGO = new GameObject("New Light");
|
||||
lightGO.transform.position = _previewObject.transform.position;
|
||||
|
||||
Light l = lightGO.AddComponent<Light>();
|
||||
l.type = LightType.Point;
|
||||
l.range = 8f;
|
||||
l.intensity = 5f;
|
||||
l.color = _selectedColor;
|
||||
|
||||
SphereCollider col = lightGO.AddComponent<SphereCollider>();
|
||||
col.radius = 0.5f;
|
||||
|
||||
_placedLights.Add(lightGO);
|
||||
_currentLights++;
|
||||
}
|
||||
|
||||
private void TryRemoveLight()
|
||||
{
|
||||
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
|
||||
|
||||
if (!Physics.Raycast(ray, out RaycastHit hit, maxDistance))
|
||||
return;
|
||||
|
||||
GameObject hitObject = hit.collider.gameObject;
|
||||
|
||||
if (_placedLights.Contains(hitObject))
|
||||
{
|
||||
RemoveLight(hitObject);
|
||||
return;
|
||||
}
|
||||
|
||||
float removeRadius = 1f;
|
||||
Collider[] nearby = Physics.OverlapSphere(hit.point, removeRadius);
|
||||
|
||||
foreach (Collider col in nearby)
|
||||
{
|
||||
if (_placedLights.Contains(col.gameObject))
|
||||
{
|
||||
RemoveLight(col.gameObject);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveLight(GameObject lightObject)
|
||||
{
|
||||
_placedLights.Remove(lightObject);
|
||||
Destroy(lightObject);
|
||||
_currentLights--;
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/LightManager.cs.meta
Normal file
11
Assets/Scripts/LightManager.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 67a050f101faa2843abd5970ee277916
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
161
Assets/Scripts/MarsmoonsOrbit.cs
Normal file
161
Assets/Scripts/MarsmoonsOrbit.cs
Normal file
@@ -0,0 +1,161 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class MarsmoonsOrbit : MonoBehaviour
|
||||
{
|
||||
public Transform mars;
|
||||
|
||||
public MoonType moonType = MoonType.Phobos;
|
||||
public bool autoCalculateOrbit = true;
|
||||
public float manualOrbitRadius = 9.4f;
|
||||
|
||||
public float orbitInclination = 1.08f;
|
||||
public float startAngleDegrees = 0f;
|
||||
|
||||
public float timeScale = 10f;
|
||||
|
||||
public bool showDebugInfo = false;
|
||||
|
||||
private const float MARS_RADIUS_KM = 3390f;
|
||||
private const float PHOBOS_DISTANCE_KM = 9376f;
|
||||
private const float PHOBOS_PERIOD_HOURS = 7.65f;
|
||||
private const float DEIMOS_DISTANCE_KM = 23463f;
|
||||
private const float DEIMOS_PERIOD_HOURS = 30.3f;
|
||||
|
||||
private float orbitRadius;
|
||||
private float angularSpeed;
|
||||
private float currentAngle = 0f;
|
||||
private float orbitCount = 0f;
|
||||
private float debugTimer = 0f;
|
||||
|
||||
public enum MoonType
|
||||
{
|
||||
Phobos,
|
||||
Deimos
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
if (mars == null)
|
||||
{
|
||||
mars = GameObject.Find("Mars")?.transform;
|
||||
if (mars == null)
|
||||
{
|
||||
enabled = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
CalculateOrbit();
|
||||
SetInitialPosition();
|
||||
|
||||
}
|
||||
|
||||
void CalculateOrbit()
|
||||
{
|
||||
float marsRadius = mars.localScale.x / 2f;
|
||||
|
||||
if (autoCalculateOrbit)
|
||||
{
|
||||
if (moonType == MoonType.Phobos)
|
||||
{
|
||||
orbitRadius = marsRadius * (PHOBOS_DISTANCE_KM / MARS_RADIUS_KM);
|
||||
float period = PHOBOS_PERIOD_HOURS * 3600f;
|
||||
angularSpeed = (2f * Mathf.PI / period) * timeScale;
|
||||
orbitInclination = 1.08f;
|
||||
}
|
||||
else
|
||||
{
|
||||
orbitRadius = marsRadius * (DEIMOS_DISTANCE_KM / MARS_RADIUS_KM);
|
||||
float period = DEIMOS_PERIOD_HOURS * 3600f;
|
||||
angularSpeed = (2f * Mathf.PI / period) * timeScale;
|
||||
orbitInclination = 1.79f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
orbitRadius = manualOrbitRadius;
|
||||
float period = (moonType == MoonType.Phobos ? PHOBOS_PERIOD_HOURS : DEIMOS_PERIOD_HOURS) * 3600f;
|
||||
angularSpeed = (2f * Mathf.PI / period) * timeScale;
|
||||
}
|
||||
}
|
||||
|
||||
void SetInitialPosition()
|
||||
{
|
||||
currentAngle = startAngleDegrees * Mathf.Deg2Rad;
|
||||
UpdatePosition();
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (mars == null) return;
|
||||
|
||||
currentAngle += angularSpeed * Time.deltaTime;
|
||||
|
||||
if (currentAngle >= 2f * Mathf.PI)
|
||||
{
|
||||
currentAngle -= 2f * Mathf.PI;
|
||||
orbitCount++;
|
||||
|
||||
if (showDebugInfo)
|
||||
{
|
||||
Debug.Log(moonType + " orbit " + orbitCount);
|
||||
}
|
||||
}
|
||||
|
||||
UpdatePosition();
|
||||
|
||||
if (showDebugInfo)
|
||||
{
|
||||
debugTimer += Time.deltaTime;
|
||||
if (debugTimer >= 10f)
|
||||
{
|
||||
debugTimer = 0f;
|
||||
float progress = (currentAngle / (2f * Mathf.PI)) * 100f;
|
||||
Debug.Log(moonType + ": R=" + orbitRadius.ToString("F2") + " P=" + progress.ToString("F1") + "%");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdatePosition()
|
||||
{
|
||||
float x = Mathf.Cos(currentAngle) * orbitRadius;
|
||||
float z = Mathf.Sin(currentAngle) * orbitRadius;
|
||||
|
||||
float inclinationRad = orbitInclination * Mathf.Deg2Rad;
|
||||
float y = z * Mathf.Sin(inclinationRad);
|
||||
z = z * Mathf.Cos(inclinationRad);
|
||||
|
||||
transform.position = mars.position + new Vector3(x, y, z);
|
||||
}
|
||||
|
||||
void OnDrawGizmos()
|
||||
{
|
||||
if (mars == null) return;
|
||||
|
||||
Gizmos.color = moonType == MoonType.Phobos ? new Color(1f, 0.5f, 0.5f, 0.5f) : new Color(0.5f, 0.7f, 1f, 0.5f);
|
||||
|
||||
int segments = 64;
|
||||
Vector3 prevPos = GetOrbitPoint(0);
|
||||
|
||||
for (int i = 1; i <= segments; i++)
|
||||
{
|
||||
Vector3 newPos = GetOrbitPoint(i * 2f * Mathf.PI / segments);
|
||||
Gizmos.DrawLine(prevPos, newPos);
|
||||
prevPos = newPos;
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 GetOrbitPoint(float angle)
|
||||
{
|
||||
float x = Mathf.Cos(angle) * orbitRadius;
|
||||
float z = Mathf.Sin(angle) * orbitRadius;
|
||||
|
||||
float inclinationRad = orbitInclination * Mathf.Deg2Rad;
|
||||
float y = z * Mathf.Sin(inclinationRad);
|
||||
z = z * Mathf.Cos(inclinationRad);
|
||||
|
||||
return mars.position + new Vector3(x, y, z);
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/MarsmoonsOrbit.cs.meta
Normal file
11
Assets/Scripts/MarsmoonsOrbit.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 88294a843778ac649973a306a1c356d4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
35
Assets/Scripts/MassInspectorController.cs
Normal file
35
Assets/Scripts/MassInspectorController.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
[System.Serializable]
|
||||
public class MassTarget
|
||||
{
|
||||
[Header("Назва")]
|
||||
public string ukrainianName;
|
||||
|
||||
[Header("Rigidbody обʼєкта")]
|
||||
public Rigidbody rigidbody;
|
||||
|
||||
[HideInInspector]
|
||||
public float baseMass;
|
||||
}
|
||||
|
||||
public class MassInspectorController : MonoBehaviour
|
||||
{
|
||||
[Header("Список обʼєктів")]
|
||||
public List<MassTarget> targets = new List<MassTarget>();
|
||||
|
||||
private void OnValidate()
|
||||
{
|
||||
for (int i = 0; i < targets.Count; i++)
|
||||
{
|
||||
if (targets[i] == null) continue;
|
||||
if (targets[i].rigidbody == null) continue;
|
||||
|
||||
if (targets[i].baseMass <= 0f)
|
||||
targets[i].baseMass = targets[i].rigidbody.mass;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/MassInspectorController.cs.meta
Normal file
11
Assets/Scripts/MassInspectorController.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e883c09c525351e49a1618558df234e1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
18
Assets/Scripts/MassSliderController.cs
Normal file
18
Assets/Scripts/MassSliderController.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class MassSliderController : MonoBehaviour
|
||||
{
|
||||
// Start is called before the first frame update
|
||||
void Start()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/MassSliderController.cs.meta
Normal file
11
Assets/Scripts/MassSliderController.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 88bd81e4a6167454ba115b8ba06aa071
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
19
Assets/Scripts/MoonGravity.cs
Normal file
19
Assets/Scripts/MoonGravity.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class MoonGravity : MonoBehaviour
|
||||
{
|
||||
private Rigidbody _rb;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_rb = GetComponent<Rigidbody>();
|
||||
_rb.useGravity = false;
|
||||
}
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
_rb.AddForce(Vector3.down * 1.62f, ForceMode.Acceleration);
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/MoonGravity.cs.meta
Normal file
11
Assets/Scripts/MoonGravity.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8d410bad46ab98044b782c737e5b183a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
41
Assets/Scripts/MoonGravityForce.cs
Normal file
41
Assets/Scripts/MoonGravityForce.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class MoonGravityForce : MonoBehaviour
|
||||
{
|
||||
[Header("Швидкість обертання навколо Землі")]
|
||||
[Range(0f, 100f)]
|
||||
[SerializeField] private float orbitSpeed = 0.55f;
|
||||
|
||||
[Header("Нахил осі Місяця")]
|
||||
[Range(0f, 180f)]
|
||||
[SerializeField] private float axialTilt = 6.68f;
|
||||
|
||||
private PlanetSpin _parentSpin;
|
||||
private Transform _parentTransform;
|
||||
|
||||
void Start()
|
||||
{
|
||||
_parentTransform = transform.parent;
|
||||
_parentSpin = _parentTransform.GetComponent<PlanetSpin>();
|
||||
|
||||
transform.localRotation = Quaternion.Euler(0f, 0f, axialTilt);
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
float parentRotationSpeed = _parentSpin != null ? _parentSpin.RotationSpeed : 0f;
|
||||
|
||||
float compensatedOrbit = orbitSpeed - parentRotationSpeed;
|
||||
|
||||
transform.RotateAround(
|
||||
_parentTransform.position,
|
||||
Vector3.up,
|
||||
compensatedOrbit * Time.deltaTime
|
||||
);
|
||||
|
||||
transform.LookAt(_parentTransform.position);
|
||||
}
|
||||
}
|
||||
|
||||
11
Assets/Scripts/MoonGravityForce.cs.meta
Normal file
11
Assets/Scripts/MoonGravityForce.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1219dc08a36c7914c94a80ac0d2be6b8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
88
Assets/Scripts/MoonObjectInfo.cs
Normal file
88
Assets/Scripts/MoonObjectInfo.cs
Normal file
@@ -0,0 +1,88 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using TMPro;
|
||||
public class MoonObjectInfo : MonoBehaviour
|
||||
{
|
||||
public TextMeshProUGUI infoText;
|
||||
private Rigidbody _rb;
|
||||
|
||||
private float _startTime;
|
||||
private float _startHeight;
|
||||
private bool _isFalling = false;
|
||||
private bool _hasLanded = false;
|
||||
private float _startMass;
|
||||
|
||||
private const float moonGravity = 1.62f;
|
||||
|
||||
void Start()
|
||||
{
|
||||
_rb = GetComponent<Rigidbody>();
|
||||
_startMass = _rb.mass;
|
||||
|
||||
if (infoText != null)
|
||||
infoText.text = "";
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (infoText != null)
|
||||
{
|
||||
infoText.transform.parent.LookAt(Camera.main.transform);
|
||||
infoText.transform.parent.Rotate(0, 180, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnRelease()
|
||||
{
|
||||
_startTime = Time.time;
|
||||
_startHeight = transform.position.y;
|
||||
_isFalling = true;
|
||||
_hasLanded = false;
|
||||
|
||||
if (infoText != null)
|
||||
infoText.text = "";
|
||||
}
|
||||
|
||||
void OnCollisionEnter(Collision collision)
|
||||
{
|
||||
if (_isFalling && !_hasLanded && collision.gameObject.CompareTag("Ground"))
|
||||
{
|
||||
_hasLanded = true;
|
||||
_isFalling = false;
|
||||
|
||||
float fallTime = Time.time - _startTime;
|
||||
float dropHeight = _startHeight - transform.position.y;
|
||||
float impactSpeed = _rb.velocity.magnitude;
|
||||
float mass = _rb.mass;
|
||||
|
||||
float gravityForce = mass * moonGravity;
|
||||
float theoreticalTime = Mathf.Sqrt((2 * dropHeight) / moonGravity);
|
||||
|
||||
if (infoText != null)
|
||||
{
|
||||
infoText.text =
|
||||
$"Висота: {dropHeight:F2} м\n" +
|
||||
$"Час падіння: {fallTime:F2} с\n" +
|
||||
$"Швидкість удару: {impactSpeed:F2} м/с\n" +
|
||||
$"Маса: {mass:F2} кг\n" +
|
||||
$"Сила тяжіння: {mass:F2} × {moonGravity} = ?? Н\n" +
|
||||
$"Прискорення: {moonGravity} м/с² (Місяць)";
|
||||
}
|
||||
|
||||
AirTrailController trail = GetComponentInChildren<AirTrailController>();
|
||||
if (trail != null)
|
||||
{
|
||||
trail.Deactivate();
|
||||
}
|
||||
|
||||
Invoke("ClearText", 15f);
|
||||
}
|
||||
}
|
||||
|
||||
void ClearText()
|
||||
{
|
||||
if (infoText != null)
|
||||
infoText.text = "";
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/MoonObjectInfo.cs.meta
Normal file
11
Assets/Scripts/MoonObjectInfo.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e37c77ea429da2c48b3bb501598e8101
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
216
Assets/Scripts/MoonOrbitJupiter.cs
Normal file
216
Assets/Scripts/MoonOrbitJupiter.cs
Normal file
@@ -0,0 +1,216 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class MoonOrbitJupiter : MonoBehaviour
|
||||
{
|
||||
public Transform jupiter;
|
||||
|
||||
public JupiterMoonType moonType = JupiterMoonType.Io;
|
||||
public bool autoCalculateOrbit = true;
|
||||
public float manualOrbitRadius = 10f;
|
||||
|
||||
public float orbitInclination = 0.04f;
|
||||
public float startAngleDegrees = 0f;
|
||||
|
||||
public float timeScale = 10f;
|
||||
|
||||
public bool showDebugInfo = false;
|
||||
|
||||
private const float JUPITER_RADIUS_KM = 69911f;
|
||||
|
||||
private const float IO_RADIUS_KM = 1821f;
|
||||
private const float IO_DISTANCE_KM = 421700f;
|
||||
private const float IO_PERIOD_HOURS = 42.5f;
|
||||
|
||||
private const float EUROPA_RADIUS_KM = 1560f;
|
||||
private const float EUROPA_DISTANCE_KM = 671100f;
|
||||
private const float EUROPA_PERIOD_HOURS = 85.2f;
|
||||
|
||||
private const float GANYMEDE_RADIUS_KM = 2634f;
|
||||
private const float GANYMEDE_DISTANCE_KM = 1070400f;
|
||||
private const float GANYMEDE_PERIOD_HOURS = 171.7f;
|
||||
|
||||
private const float CALLISTO_RADIUS_KM = 2410f;
|
||||
private const float CALLISTO_DISTANCE_KM = 1882700f;
|
||||
private const float CALLISTO_PERIOD_HOURS = 400.5f;
|
||||
|
||||
private float orbitRadius;
|
||||
private float angularSpeed;
|
||||
private float currentAngle = 0f;
|
||||
private float orbitCount = 0f;
|
||||
private float debugTimer = 0f;
|
||||
|
||||
public enum JupiterMoonType
|
||||
{
|
||||
Io,
|
||||
Europa,
|
||||
Ganymede,
|
||||
Callisto
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
if (jupiter == null)
|
||||
{
|
||||
jupiter = GameObject.Find("Jupiter")?.transform;
|
||||
if (jupiter == null)
|
||||
{
|
||||
enabled = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
CalculateOrbit();
|
||||
SetInitialPosition();
|
||||
|
||||
}
|
||||
|
||||
void CalculateOrbit()
|
||||
{
|
||||
float jupiterRadius = jupiter.localScale.x / 2f;
|
||||
|
||||
if (autoCalculateOrbit)
|
||||
{
|
||||
switch (moonType)
|
||||
{
|
||||
case JupiterMoonType.Io:
|
||||
orbitRadius = jupiterRadius * (IO_DISTANCE_KM / JUPITER_RADIUS_KM);
|
||||
angularSpeed = (2f * Mathf.PI / (IO_PERIOD_HOURS * 3600f)) * timeScale;
|
||||
orbitInclination = 0.04f;
|
||||
break;
|
||||
|
||||
case JupiterMoonType.Europa:
|
||||
orbitRadius = jupiterRadius * (EUROPA_DISTANCE_KM / JUPITER_RADIUS_KM);
|
||||
angularSpeed = (2f * Mathf.PI / (EUROPA_PERIOD_HOURS * 3600f)) * timeScale;
|
||||
orbitInclination = 0.47f;
|
||||
break;
|
||||
|
||||
case JupiterMoonType.Ganymede:
|
||||
orbitRadius = jupiterRadius * (GANYMEDE_DISTANCE_KM / JUPITER_RADIUS_KM);
|
||||
angularSpeed = (2f * Mathf.PI / (GANYMEDE_PERIOD_HOURS * 3600f)) * timeScale;
|
||||
orbitInclination = 0.20f;
|
||||
break;
|
||||
|
||||
case JupiterMoonType.Callisto:
|
||||
orbitRadius = jupiterRadius * (CALLISTO_DISTANCE_KM / JUPITER_RADIUS_KM);
|
||||
angularSpeed = (2f * Mathf.PI / (CALLISTO_PERIOD_HOURS * 3600f)) * timeScale;
|
||||
orbitInclination = 0.51f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
orbitRadius = manualOrbitRadius;
|
||||
float period = GetPeriod() * 3600f;
|
||||
angularSpeed = (2f * Mathf.PI / period) * timeScale;
|
||||
}
|
||||
}
|
||||
|
||||
float GetPeriod()
|
||||
{
|
||||
switch (moonType)
|
||||
{
|
||||
case JupiterMoonType.Io: return IO_PERIOD_HOURS;
|
||||
case JupiterMoonType.Europa: return EUROPA_PERIOD_HOURS;
|
||||
case JupiterMoonType.Ganymede: return GANYMEDE_PERIOD_HOURS;
|
||||
case JupiterMoonType.Callisto: return CALLISTO_PERIOD_HOURS;
|
||||
default: return IO_PERIOD_HOURS;
|
||||
}
|
||||
}
|
||||
|
||||
void SetInitialPosition()
|
||||
{
|
||||
currentAngle = startAngleDegrees * Mathf.Deg2Rad;
|
||||
UpdatePosition();
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (jupiter == null) return;
|
||||
|
||||
currentAngle += angularSpeed * Time.deltaTime;
|
||||
|
||||
if (currentAngle >= 2f * Mathf.PI)
|
||||
{
|
||||
currentAngle -= 2f * Mathf.PI;
|
||||
orbitCount++;
|
||||
|
||||
if (showDebugInfo)
|
||||
{
|
||||
Debug.Log(moonType + " orbit " + orbitCount);
|
||||
}
|
||||
}
|
||||
|
||||
UpdatePosition();
|
||||
|
||||
if (showDebugInfo)
|
||||
{
|
||||
debugTimer += Time.deltaTime;
|
||||
if (debugTimer >= 10f)
|
||||
{
|
||||
debugTimer = 0f;
|
||||
float progress = (currentAngle / (2f * Mathf.PI)) * 100f;
|
||||
Debug.Log(moonType + ": R=" + orbitRadius.ToString("F2") + " P=" + progress.ToString("F1") + "%");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdatePosition()
|
||||
{
|
||||
float x = Mathf.Cos(currentAngle) * orbitRadius;
|
||||
float z = Mathf.Sin(currentAngle) * orbitRadius;
|
||||
|
||||
float inclinationRad = orbitInclination * Mathf.Deg2Rad;
|
||||
float y = z * Mathf.Sin(inclinationRad);
|
||||
z = z * Mathf.Cos(inclinationRad);
|
||||
|
||||
transform.position = jupiter.position + new Vector3(x, y, z);
|
||||
}
|
||||
|
||||
void OnDrawGizmos()
|
||||
{
|
||||
if (jupiter == null) return;
|
||||
|
||||
Color gizmoColor = Color.white;
|
||||
switch (moonType)
|
||||
{
|
||||
case JupiterMoonType.Io:
|
||||
gizmoColor = new Color(1f, 0.9f, 0.3f, 0.5f);
|
||||
break;
|
||||
case JupiterMoonType.Europa:
|
||||
gizmoColor = new Color(0.8f, 0.9f, 1f, 0.5f);
|
||||
break;
|
||||
case JupiterMoonType.Ganymede:
|
||||
gizmoColor = new Color(0.7f, 0.6f, 0.5f, 0.5f);
|
||||
break;
|
||||
case JupiterMoonType.Callisto:
|
||||
gizmoColor = new Color(0.5f, 0.5f, 0.5f, 0.5f);
|
||||
break;
|
||||
}
|
||||
|
||||
Gizmos.color = gizmoColor;
|
||||
|
||||
int segments = 64;
|
||||
Vector3 prevPos = GetOrbitPoint(0);
|
||||
|
||||
for (int i = 1; i <= segments; i++)
|
||||
{
|
||||
Vector3 newPos = GetOrbitPoint(i * 2f * Mathf.PI / segments);
|
||||
Gizmos.DrawLine(prevPos, newPos);
|
||||
prevPos = newPos;
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 GetOrbitPoint(float angle)
|
||||
{
|
||||
float x = Mathf.Cos(angle) * orbitRadius;
|
||||
float z = Mathf.Sin(angle) * orbitRadius;
|
||||
|
||||
float inclinationRad = orbitInclination * Mathf.Deg2Rad;
|
||||
float y = z * Mathf.Sin(inclinationRad);
|
||||
z = z * Mathf.Cos(inclinationRad);
|
||||
|
||||
return jupiter.position + new Vector3(x, y, z);
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/MoonOrbitJupiter.cs.meta
Normal file
11
Assets/Scripts/MoonOrbitJupiter.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b7d9f13d9ad753643b82e5a6011ab53d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
164
Assets/Scripts/MoonOrbitNeptune.cs
Normal file
164
Assets/Scripts/MoonOrbitNeptune.cs
Normal file
@@ -0,0 +1,164 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class MoonOrbitNeptune : MonoBehaviour
|
||||
{
|
||||
public Transform neptune;
|
||||
|
||||
public NeptuneMoonType moonType = NeptuneMoonType.Triton;
|
||||
public bool autoCalculateOrbit = true;
|
||||
public float manualOrbitRadius = 10f;
|
||||
|
||||
public float orbitInclination = 156.8f;
|
||||
public float startAngleDegrees = 0f;
|
||||
|
||||
public float timeScale = 10f;
|
||||
|
||||
public bool showDebugInfo = false;
|
||||
|
||||
private const float NEPTUNE_RADIUS_KM = 24622f;
|
||||
|
||||
private const float TRITON_RADIUS_KM = 1353f;
|
||||
private const float TRITON_DISTANCE_KM = 354759f;
|
||||
private const float TRITON_PERIOD_HOURS = 141.0f;
|
||||
|
||||
private float orbitRadius;
|
||||
private float angularSpeed;
|
||||
private float currentAngle = 0f;
|
||||
private float orbitCount = 0f;
|
||||
private float debugTimer = 0f;
|
||||
|
||||
public enum NeptuneMoonType
|
||||
{
|
||||
Triton
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
if (neptune == null)
|
||||
{
|
||||
neptune = GameObject.Find("Neptune")?.transform;
|
||||
if (neptune == null)
|
||||
{
|
||||
enabled = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
CalculateOrbit();
|
||||
SetInitialPosition();
|
||||
}
|
||||
|
||||
void CalculateOrbit()
|
||||
{
|
||||
float neptuneRadius = neptune.localScale.x / 2f;
|
||||
|
||||
if (autoCalculateOrbit)
|
||||
{
|
||||
switch (moonType)
|
||||
{
|
||||
case NeptuneMoonType.Triton:
|
||||
orbitRadius = neptuneRadius * (TRITON_DISTANCE_KM / NEPTUNE_RADIUS_KM);
|
||||
angularSpeed = -(2f * Mathf.PI / (TRITON_PERIOD_HOURS * 3600f)) * timeScale;
|
||||
orbitInclination = 156.8f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
orbitRadius = manualOrbitRadius;
|
||||
float period = GetPeriod() * 3600f;
|
||||
angularSpeed = -(2f * Mathf.PI / period) * timeScale;
|
||||
}
|
||||
}
|
||||
|
||||
float GetPeriod()
|
||||
{
|
||||
switch (moonType)
|
||||
{
|
||||
case NeptuneMoonType.Triton: return TRITON_PERIOD_HOURS;
|
||||
default: return TRITON_PERIOD_HOURS;
|
||||
}
|
||||
}
|
||||
|
||||
void SetInitialPosition()
|
||||
{
|
||||
currentAngle = startAngleDegrees * Mathf.Deg2Rad;
|
||||
UpdatePosition();
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (neptune == null) return;
|
||||
|
||||
currentAngle += angularSpeed * Time.deltaTime;
|
||||
|
||||
if (currentAngle <= -2f * Mathf.PI)
|
||||
{
|
||||
currentAngle += 2f * Mathf.PI;
|
||||
orbitCount++;
|
||||
|
||||
if (showDebugInfo)
|
||||
{
|
||||
Debug.Log(moonType + " orbit " + orbitCount + " (retrograde)");
|
||||
}
|
||||
}
|
||||
|
||||
UpdatePosition();
|
||||
|
||||
if (showDebugInfo)
|
||||
{
|
||||
debugTimer += Time.deltaTime;
|
||||
if (debugTimer >= 10f)
|
||||
{
|
||||
debugTimer = 0f;
|
||||
float progress = (Mathf.Abs(currentAngle) / (2f * Mathf.PI)) * 100f;
|
||||
Debug.Log(moonType + ": R=" + orbitRadius.ToString("F2") + " P=" + progress.ToString("F1") + "% RETROGRADE");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdatePosition()
|
||||
{
|
||||
float x = Mathf.Cos(currentAngle) * orbitRadius;
|
||||
float z = Mathf.Sin(currentAngle) * orbitRadius;
|
||||
|
||||
float inclinationRad = orbitInclination * Mathf.Deg2Rad;
|
||||
float y = z * Mathf.Sin(inclinationRad);
|
||||
z = z * Mathf.Cos(inclinationRad);
|
||||
|
||||
transform.position = neptune.position + new Vector3(x, y, z);
|
||||
}
|
||||
|
||||
void OnDrawGizmos()
|
||||
{
|
||||
if (neptune == null) return;
|
||||
|
||||
Color gizmoColor = new Color(0.4f, 0.7f, 1f, 0.5f);
|
||||
|
||||
Gizmos.color = gizmoColor;
|
||||
|
||||
int segments = 64;
|
||||
Vector3 prevPos = GetOrbitPoint(0);
|
||||
|
||||
for (int i = 1; i <= segments; i++)
|
||||
{
|
||||
Vector3 newPos = GetOrbitPoint(i * 2f * Mathf.PI / segments);
|
||||
Gizmos.DrawLine(prevPos, newPos);
|
||||
prevPos = newPos;
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 GetOrbitPoint(float angle)
|
||||
{
|
||||
float x = Mathf.Cos(angle) * orbitRadius;
|
||||
float z = Mathf.Sin(angle) * orbitRadius;
|
||||
|
||||
float inclinationRad = orbitInclination * Mathf.Deg2Rad;
|
||||
float y = z * Mathf.Sin(inclinationRad);
|
||||
z = z * Mathf.Cos(inclinationRad);
|
||||
|
||||
return neptune.position + new Vector3(x, y, z);
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/MoonOrbitNeptune.cs.meta
Normal file
11
Assets/Scripts/MoonOrbitNeptune.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 14332449173ef1340b37742922c8ca0f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
164
Assets/Scripts/MoonOrbitPluto.cs
Normal file
164
Assets/Scripts/MoonOrbitPluto.cs
Normal file
@@ -0,0 +1,164 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class MoonOrbitPluto : MonoBehaviour
|
||||
{
|
||||
public Transform pluto;
|
||||
|
||||
public PlutoMoonType moonType = PlutoMoonType.Charon;
|
||||
public bool autoCalculateOrbit = true;
|
||||
public float manualOrbitRadius = 10f;
|
||||
|
||||
public float orbitInclination = 0.08f;
|
||||
public float startAngleDegrees = 0f;
|
||||
|
||||
public float timeScale = 10f;
|
||||
|
||||
public bool showDebugInfo = false;
|
||||
|
||||
private const float PLUTO_RADIUS_KM = 1188f;
|
||||
|
||||
private const float CHARON_RADIUS_KM = 606f;
|
||||
private const float CHARON_DISTANCE_KM = 19591f;
|
||||
private const float CHARON_PERIOD_HOURS = 153.3f;
|
||||
|
||||
private float orbitRadius;
|
||||
private float angularSpeed;
|
||||
private float currentAngle = 0f;
|
||||
private float orbitCount = 0f;
|
||||
private float debugTimer = 0f;
|
||||
|
||||
public enum PlutoMoonType
|
||||
{
|
||||
Charon
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
if (pluto == null)
|
||||
{
|
||||
pluto = GameObject.Find("Pluto")?.transform;
|
||||
if (pluto == null)
|
||||
{
|
||||
enabled = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
CalculateOrbit();
|
||||
SetInitialPosition();
|
||||
}
|
||||
|
||||
void CalculateOrbit()
|
||||
{
|
||||
float plutoRadius = pluto.localScale.x / 2f;
|
||||
|
||||
if (autoCalculateOrbit)
|
||||
{
|
||||
switch (moonType)
|
||||
{
|
||||
case PlutoMoonType.Charon:
|
||||
orbitRadius = plutoRadius * (CHARON_DISTANCE_KM / PLUTO_RADIUS_KM);
|
||||
angularSpeed = (2f * Mathf.PI / (CHARON_PERIOD_HOURS * 3600f)) * timeScale;
|
||||
orbitInclination = 0.08f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
orbitRadius = manualOrbitRadius;
|
||||
float period = GetPeriod() * 3600f;
|
||||
angularSpeed = (2f * Mathf.PI / period) * timeScale;
|
||||
}
|
||||
}
|
||||
|
||||
float GetPeriod()
|
||||
{
|
||||
switch (moonType)
|
||||
{
|
||||
case PlutoMoonType.Charon: return CHARON_PERIOD_HOURS;
|
||||
default: return CHARON_PERIOD_HOURS;
|
||||
}
|
||||
}
|
||||
|
||||
void SetInitialPosition()
|
||||
{
|
||||
currentAngle = startAngleDegrees * Mathf.Deg2Rad;
|
||||
UpdatePosition();
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (pluto == null) return;
|
||||
|
||||
currentAngle += angularSpeed * Time.deltaTime;
|
||||
|
||||
if (currentAngle >= 2f * Mathf.PI)
|
||||
{
|
||||
currentAngle -= 2f * Mathf.PI;
|
||||
orbitCount++;
|
||||
|
||||
if (showDebugInfo)
|
||||
{
|
||||
Debug.Log(moonType + " orbit " + orbitCount);
|
||||
}
|
||||
}
|
||||
|
||||
UpdatePosition();
|
||||
|
||||
if (showDebugInfo)
|
||||
{
|
||||
debugTimer += Time.deltaTime;
|
||||
if (debugTimer >= 10f)
|
||||
{
|
||||
debugTimer = 0f;
|
||||
float progress = (currentAngle / (2f * Mathf.PI)) * 100f;
|
||||
Debug.Log(moonType + ": R=" + orbitRadius.ToString("F2") + " P=" + progress.ToString("F1") + "%");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdatePosition()
|
||||
{
|
||||
float x = Mathf.Cos(currentAngle) * orbitRadius;
|
||||
float z = Mathf.Sin(currentAngle) * orbitRadius;
|
||||
|
||||
float inclinationRad = orbitInclination * Mathf.Deg2Rad;
|
||||
float y = z * Mathf.Sin(inclinationRad);
|
||||
z = z * Mathf.Cos(inclinationRad);
|
||||
|
||||
transform.position = pluto.position + new Vector3(x, y, z);
|
||||
}
|
||||
|
||||
void OnDrawGizmos()
|
||||
{
|
||||
if (pluto == null) return;
|
||||
|
||||
Color gizmoColor = new Color(0.7f, 0.7f, 0.7f, 0.5f);
|
||||
|
||||
Gizmos.color = gizmoColor;
|
||||
|
||||
int segments = 64;
|
||||
Vector3 prevPos = GetOrbitPoint(0);
|
||||
|
||||
for (int i = 1; i <= segments; i++)
|
||||
{
|
||||
Vector3 newPos = GetOrbitPoint(i * 2f * Mathf.PI / segments);
|
||||
Gizmos.DrawLine(prevPos, newPos);
|
||||
prevPos = newPos;
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 GetOrbitPoint(float angle)
|
||||
{
|
||||
float x = Mathf.Cos(angle) * orbitRadius;
|
||||
float z = Mathf.Sin(angle) * orbitRadius;
|
||||
|
||||
float inclinationRad = orbitInclination * Mathf.Deg2Rad;
|
||||
float y = z * Mathf.Sin(inclinationRad);
|
||||
z = z * Mathf.Cos(inclinationRad);
|
||||
|
||||
return pluto.position + new Vector3(x, y, z);
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/MoonOrbitPluto.cs.meta
Normal file
11
Assets/Scripts/MoonOrbitPluto.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b9f8500565a110f4b94b56329e24c0cc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
204
Assets/Scripts/MoonOrbitSaturn.cs
Normal file
204
Assets/Scripts/MoonOrbitSaturn.cs
Normal file
@@ -0,0 +1,204 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class MoonOrbitSaturn : MonoBehaviour
|
||||
{
|
||||
public Transform saturn;
|
||||
|
||||
public SaturnMoonType moonType = SaturnMoonType.Mimas;
|
||||
public bool autoCalculateOrbit = true;
|
||||
public float manualOrbitRadius = 10f;
|
||||
|
||||
public float orbitInclination = 0f;
|
||||
public float startAngleDegrees = 0f;
|
||||
|
||||
public float timeScale = 10f;
|
||||
|
||||
public float orbitScaleMultiplier = 4f;
|
||||
|
||||
public bool showDebugInfo = false;
|
||||
|
||||
private const float SATURN_RADIUS_KM = 58232f;
|
||||
|
||||
private const float MIMAS_DISTANCE_KM = 185539f;
|
||||
private const float MIMAS_PERIOD_HOURS = 22.6f;
|
||||
|
||||
private const float ENCELADUS_DISTANCE_KM = 237948f;
|
||||
private const float ENCELADUS_PERIOD_HOURS = 32.9f;
|
||||
|
||||
private const float TETHYS_DISTANCE_KM = 294619f;
|
||||
private const float TETHYS_PERIOD_HOURS = 45.3f;
|
||||
|
||||
private const float DIONE_DISTANCE_KM = 377396f;
|
||||
private const float DIONE_PERIOD_HOURS = 65.7f;
|
||||
|
||||
private const float RHEA_DISTANCE_KM = 527108f;
|
||||
private const float RHEA_PERIOD_HOURS = 108.4f;
|
||||
|
||||
private const float TITAN_DISTANCE_KM = 1221870f;
|
||||
private const float TITAN_PERIOD_HOURS = 382.7f;
|
||||
|
||||
private const float IAPETUS_DISTANCE_KM = 3560820f;
|
||||
private const float IAPETUS_PERIOD_HOURS = 1903.7f;
|
||||
|
||||
private float orbitRadius;
|
||||
private float angularSpeed;
|
||||
private float currentAngle;
|
||||
|
||||
public enum SaturnMoonType
|
||||
{
|
||||
Mimas,
|
||||
Enceladus,
|
||||
Tethys,
|
||||
Dione,
|
||||
Rhea,
|
||||
Titan,
|
||||
Iapetus
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
if (saturn == null)
|
||||
{
|
||||
saturn = GameObject.Find("Saturn")?.transform;
|
||||
if (saturn == null)
|
||||
{
|
||||
enabled = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
CalculateOrbit();
|
||||
SetInitialPosition();
|
||||
}
|
||||
|
||||
void CalculateOrbit()
|
||||
{
|
||||
float saturnRadius = saturn.localScale.x / 2f;
|
||||
|
||||
if (autoCalculateOrbit)
|
||||
{
|
||||
switch (moonType)
|
||||
{
|
||||
case SaturnMoonType.Mimas:
|
||||
orbitRadius = saturnRadius * (MIMAS_DISTANCE_KM / SATURN_RADIUS_KM);
|
||||
angularSpeed = (2f * Mathf.PI / (MIMAS_PERIOD_HOURS * 3600f)) * timeScale;
|
||||
orbitInclination = 1.57f;
|
||||
break;
|
||||
|
||||
case SaturnMoonType.Enceladus:
|
||||
orbitRadius = saturnRadius * (ENCELADUS_DISTANCE_KM / SATURN_RADIUS_KM);
|
||||
angularSpeed = (2f * Mathf.PI / (ENCELADUS_PERIOD_HOURS * 3600f)) * timeScale;
|
||||
orbitInclination = 0.02f;
|
||||
break;
|
||||
|
||||
case SaturnMoonType.Tethys:
|
||||
orbitRadius = saturnRadius * (TETHYS_DISTANCE_KM / SATURN_RADIUS_KM);
|
||||
angularSpeed = (2f * Mathf.PI / (TETHYS_PERIOD_HOURS * 3600f)) * timeScale;
|
||||
orbitInclination = 1.09f;
|
||||
break;
|
||||
|
||||
case SaturnMoonType.Dione:
|
||||
orbitRadius = saturnRadius * (DIONE_DISTANCE_KM / SATURN_RADIUS_KM);
|
||||
angularSpeed = (2f * Mathf.PI / (DIONE_PERIOD_HOURS * 3600f)) * timeScale;
|
||||
orbitInclination = 0.02f;
|
||||
break;
|
||||
|
||||
case SaturnMoonType.Rhea:
|
||||
orbitRadius = saturnRadius * (RHEA_DISTANCE_KM / SATURN_RADIUS_KM);
|
||||
angularSpeed = (2f * Mathf.PI / (RHEA_PERIOD_HOURS * 3600f)) * timeScale;
|
||||
orbitInclination = 0.35f;
|
||||
break;
|
||||
|
||||
case SaturnMoonType.Titan:
|
||||
orbitRadius = saturnRadius * (TITAN_DISTANCE_KM / SATURN_RADIUS_KM);
|
||||
angularSpeed = (2f * Mathf.PI / (TITAN_PERIOD_HOURS * 3600f)) * timeScale;
|
||||
orbitInclination = 0.33f;
|
||||
break;
|
||||
|
||||
case SaturnMoonType.Iapetus:
|
||||
orbitRadius = saturnRadius * (IAPETUS_DISTANCE_KM / SATURN_RADIUS_KM);
|
||||
angularSpeed = (2f * Mathf.PI / (IAPETUS_PERIOD_HOURS * 3600f)) * timeScale;
|
||||
orbitInclination = 15.47f;
|
||||
break;
|
||||
}
|
||||
|
||||
orbitRadius *= orbitScaleMultiplier;
|
||||
}
|
||||
else
|
||||
{
|
||||
orbitRadius = manualOrbitRadius;
|
||||
float period = GetPeriod() * 3600f;
|
||||
angularSpeed = (2f * Mathf.PI / period) * timeScale;
|
||||
}
|
||||
}
|
||||
|
||||
float GetPeriod()
|
||||
{
|
||||
switch (moonType)
|
||||
{
|
||||
case SaturnMoonType.Mimas: return MIMAS_PERIOD_HOURS;
|
||||
case SaturnMoonType.Enceladus: return ENCELADUS_PERIOD_HOURS;
|
||||
case SaturnMoonType.Tethys: return TETHYS_PERIOD_HOURS;
|
||||
case SaturnMoonType.Dione: return DIONE_PERIOD_HOURS;
|
||||
case SaturnMoonType.Rhea: return RHEA_PERIOD_HOURS;
|
||||
case SaturnMoonType.Titan: return TITAN_PERIOD_HOURS;
|
||||
case SaturnMoonType.Iapetus: return IAPETUS_PERIOD_HOURS;
|
||||
default: return MIMAS_PERIOD_HOURS;
|
||||
}
|
||||
}
|
||||
|
||||
void SetInitialPosition()
|
||||
{
|
||||
currentAngle = startAngleDegrees * Mathf.Deg2Rad;
|
||||
UpdatePosition();
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
currentAngle += angularSpeed * Time.deltaTime;
|
||||
UpdatePosition();
|
||||
}
|
||||
|
||||
void UpdatePosition()
|
||||
{
|
||||
float x = Mathf.Cos(currentAngle) * orbitRadius;
|
||||
float z = Mathf.Sin(currentAngle) * orbitRadius;
|
||||
|
||||
float inclinationRad = orbitInclination * Mathf.Deg2Rad;
|
||||
float y = z * Mathf.Sin(inclinationRad);
|
||||
z = z * Mathf.Cos(inclinationRad);
|
||||
|
||||
transform.position = saturn.position + new Vector3(x, y, z);
|
||||
}
|
||||
|
||||
void OnDrawGizmos()
|
||||
{
|
||||
if (saturn == null) return;
|
||||
|
||||
Gizmos.color = Color.white;
|
||||
|
||||
int segments = 64;
|
||||
Vector3 prevPos = GetOrbitPoint(0f);
|
||||
|
||||
for (int i = 1; i <= segments; i++)
|
||||
{
|
||||
Vector3 newPos = GetOrbitPoint(i * 2f * Mathf.PI / segments);
|
||||
Gizmos.DrawLine(prevPos, newPos);
|
||||
prevPos = newPos;
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 GetOrbitPoint(float angle)
|
||||
{
|
||||
float x = Mathf.Cos(angle) * orbitRadius;
|
||||
float z = Mathf.Sin(angle) * orbitRadius;
|
||||
|
||||
float inclinationRad = orbitInclination * Mathf.Deg2Rad;
|
||||
float y = z * Mathf.Sin(inclinationRad);
|
||||
z = z * Mathf.Cos(inclinationRad);
|
||||
|
||||
return saturn.position + new Vector3(x, y, z);
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/MoonOrbitSaturn.cs.meta
Normal file
11
Assets/Scripts/MoonOrbitSaturn.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 99fc8b42758bbdb4384937e769a73dce
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
230
Assets/Scripts/MoonOrbitUranus.cs
Normal file
230
Assets/Scripts/MoonOrbitUranus.cs
Normal file
@@ -0,0 +1,230 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class MoonOrbitUranus : MonoBehaviour
|
||||
{
|
||||
public Transform uranus;
|
||||
|
||||
public UranusMoonType moonType = UranusMoonType.Miranda;
|
||||
public bool autoCalculateOrbit = true;
|
||||
public float manualOrbitRadius = 10f;
|
||||
|
||||
public float orbitInclination = 4.34f;
|
||||
public float startAngleDegrees = 0f;
|
||||
|
||||
public float timeScale = 10f;
|
||||
|
||||
public bool showDebugInfo = false;
|
||||
|
||||
private const float URANUS_RADIUS_KM = 25362f;
|
||||
|
||||
private const float MIRANDA_RADIUS_KM = 236f;
|
||||
private const float MIRANDA_DISTANCE_KM = 129900f;
|
||||
private const float MIRANDA_PERIOD_HOURS = 33.9f;
|
||||
|
||||
private const float ARIEL_RADIUS_KM = 579f;
|
||||
private const float ARIEL_DISTANCE_KM = 190900f;
|
||||
private const float ARIEL_PERIOD_HOURS = 60.5f;
|
||||
|
||||
private const float UMBRIEL_RADIUS_KM = 585f;
|
||||
private const float UMBRIEL_DISTANCE_KM = 266000f;
|
||||
private const float UMBRIEL_PERIOD_HOURS = 99.5f;
|
||||
|
||||
private const float TITANIA_RADIUS_KM = 789f;
|
||||
private const float TITANIA_DISTANCE_KM = 436300f;
|
||||
private const float TITANIA_PERIOD_HOURS = 209.0f;
|
||||
|
||||
private const float OBERON_RADIUS_KM = 761f;
|
||||
private const float OBERON_DISTANCE_KM = 583500f;
|
||||
private const float OBERON_PERIOD_HOURS = 323.1f;
|
||||
|
||||
private float orbitRadius;
|
||||
private float angularSpeed;
|
||||
private float currentAngle = 0f;
|
||||
private float orbitCount = 0f;
|
||||
private float debugTimer = 0f;
|
||||
|
||||
public enum UranusMoonType
|
||||
{
|
||||
Miranda,
|
||||
Ariel,
|
||||
Umbriel,
|
||||
Titania,
|
||||
Oberon
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
if (uranus == null)
|
||||
{
|
||||
uranus = GameObject.Find("Uranus")?.transform;
|
||||
if (uranus == null)
|
||||
{
|
||||
enabled = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
CalculateOrbit();
|
||||
SetInitialPosition();
|
||||
}
|
||||
|
||||
void CalculateOrbit()
|
||||
{
|
||||
float uranusRadius = uranus.localScale.x / 2f;
|
||||
|
||||
if (autoCalculateOrbit)
|
||||
{
|
||||
switch (moonType)
|
||||
{
|
||||
case UranusMoonType.Miranda:
|
||||
orbitRadius = uranusRadius * (MIRANDA_DISTANCE_KM / URANUS_RADIUS_KM);
|
||||
angularSpeed = (2f * Mathf.PI / (MIRANDA_PERIOD_HOURS * 3600f)) * timeScale;
|
||||
orbitInclination = 4.34f;
|
||||
break;
|
||||
|
||||
case UranusMoonType.Ariel:
|
||||
orbitRadius = uranusRadius * (ARIEL_DISTANCE_KM / URANUS_RADIUS_KM);
|
||||
angularSpeed = (2f * Mathf.PI / (ARIEL_PERIOD_HOURS * 3600f)) * timeScale;
|
||||
orbitInclination = 0.04f;
|
||||
break;
|
||||
|
||||
case UranusMoonType.Umbriel:
|
||||
orbitRadius = uranusRadius * (UMBRIEL_DISTANCE_KM / URANUS_RADIUS_KM);
|
||||
angularSpeed = (2f * Mathf.PI / (UMBRIEL_PERIOD_HOURS * 3600f)) * timeScale;
|
||||
orbitInclination = 0.13f;
|
||||
break;
|
||||
|
||||
case UranusMoonType.Titania:
|
||||
orbitRadius = uranusRadius * (TITANIA_DISTANCE_KM / URANUS_RADIUS_KM);
|
||||
angularSpeed = (2f * Mathf.PI / (TITANIA_PERIOD_HOURS * 3600f)) * timeScale;
|
||||
orbitInclination = 0.08f;
|
||||
break;
|
||||
|
||||
case UranusMoonType.Oberon:
|
||||
orbitRadius = uranusRadius * (OBERON_DISTANCE_KM / URANUS_RADIUS_KM);
|
||||
angularSpeed = (2f * Mathf.PI / (OBERON_PERIOD_HOURS * 3600f)) * timeScale;
|
||||
orbitInclination = 0.07f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
orbitRadius = manualOrbitRadius;
|
||||
float period = GetPeriod() * 3600f;
|
||||
angularSpeed = (2f * Mathf.PI / period) * timeScale;
|
||||
}
|
||||
}
|
||||
|
||||
float GetPeriod()
|
||||
{
|
||||
switch (moonType)
|
||||
{
|
||||
case UranusMoonType.Miranda: return MIRANDA_PERIOD_HOURS;
|
||||
case UranusMoonType.Ariel: return ARIEL_PERIOD_HOURS;
|
||||
case UranusMoonType.Umbriel: return UMBRIEL_PERIOD_HOURS;
|
||||
case UranusMoonType.Titania: return TITANIA_PERIOD_HOURS;
|
||||
case UranusMoonType.Oberon: return OBERON_PERIOD_HOURS;
|
||||
default: return MIRANDA_PERIOD_HOURS;
|
||||
}
|
||||
}
|
||||
|
||||
void SetInitialPosition()
|
||||
{
|
||||
currentAngle = startAngleDegrees * Mathf.Deg2Rad;
|
||||
UpdatePosition();
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (uranus == null) return;
|
||||
|
||||
currentAngle += angularSpeed * Time.deltaTime;
|
||||
|
||||
if (currentAngle >= 2f * Mathf.PI)
|
||||
{
|
||||
currentAngle -= 2f * Mathf.PI;
|
||||
orbitCount++;
|
||||
|
||||
if (showDebugInfo)
|
||||
{
|
||||
Debug.Log(moonType + " orbit " + orbitCount);
|
||||
}
|
||||
}
|
||||
|
||||
UpdatePosition();
|
||||
|
||||
if (showDebugInfo)
|
||||
{
|
||||
debugTimer += Time.deltaTime;
|
||||
if (debugTimer >= 10f)
|
||||
{
|
||||
debugTimer = 0f;
|
||||
float progress = (currentAngle / (2f * Mathf.PI)) * 100f;
|
||||
Debug.Log(moonType + ": R=" + orbitRadius.ToString("F2") + " P=" + progress.ToString("F1") + "%");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdatePosition()
|
||||
{
|
||||
float x = Mathf.Cos(currentAngle) * orbitRadius;
|
||||
float z = Mathf.Sin(currentAngle) * orbitRadius;
|
||||
|
||||
float inclinationRad = orbitInclination * Mathf.Deg2Rad;
|
||||
float y = z * Mathf.Sin(inclinationRad);
|
||||
z = z * Mathf.Cos(inclinationRad);
|
||||
|
||||
transform.position = uranus.position + new Vector3(x, y, z);
|
||||
}
|
||||
|
||||
void OnDrawGizmos()
|
||||
{
|
||||
if (uranus == null) return;
|
||||
|
||||
Color gizmoColor = Color.white;
|
||||
switch (moonType)
|
||||
{
|
||||
case UranusMoonType.Miranda:
|
||||
gizmoColor = new Color(0.9f, 0.85f, 0.8f, 0.5f);
|
||||
break;
|
||||
case UranusMoonType.Ariel:
|
||||
gizmoColor = new Color(0.95f, 0.95f, 0.9f, 0.5f);
|
||||
break;
|
||||
case UranusMoonType.Umbriel:
|
||||
gizmoColor = new Color(0.4f, 0.4f, 0.4f, 0.5f);
|
||||
break;
|
||||
case UranusMoonType.Titania:
|
||||
gizmoColor = new Color(0.8f, 0.75f, 0.7f, 0.5f);
|
||||
break;
|
||||
case UranusMoonType.Oberon:
|
||||
gizmoColor = new Color(0.7f, 0.7f, 0.65f, 0.5f);
|
||||
break;
|
||||
}
|
||||
|
||||
Gizmos.color = gizmoColor;
|
||||
|
||||
int segments = 64;
|
||||
Vector3 prevPos = GetOrbitPoint(0);
|
||||
|
||||
for (int i = 1; i <= segments; i++)
|
||||
{
|
||||
Vector3 newPos = GetOrbitPoint(i * 2f * Mathf.PI / segments);
|
||||
Gizmos.DrawLine(prevPos, newPos);
|
||||
prevPos = newPos;
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 GetOrbitPoint(float angle)
|
||||
{
|
||||
float x = Mathf.Cos(angle) * orbitRadius;
|
||||
float z = Mathf.Sin(angle) * orbitRadius;
|
||||
|
||||
float inclinationRad = orbitInclination * Mathf.Deg2Rad;
|
||||
float y = z * Mathf.Sin(inclinationRad);
|
||||
z = z * Mathf.Cos(inclinationRad);
|
||||
|
||||
return uranus.position + new Vector3(x, y, z);
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/MoonOrbitUranus.cs.meta
Normal file
11
Assets/Scripts/MoonOrbitUranus.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5fa6b567046ab6a478f19625610abf20
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
90
Assets/Scripts/ObjectAirProperties.cs
Normal file
90
Assets/Scripts/ObjectAirProperties.cs
Normal file
@@ -0,0 +1,90 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class ObjectAirProperties : MonoBehaviour
|
||||
{
|
||||
[Header("Âëàñòèâîñò³")]
|
||||
public float crossSectionArea = 0.05f;
|
||||
public float dragCoefficient = 0.47f;
|
||||
|
||||
void Start()
|
||||
{
|
||||
AnalyzeObject();
|
||||
}
|
||||
|
||||
void AnalyzeObject()
|
||||
{
|
||||
Renderer renderer = GetComponent<Renderer>();
|
||||
if (renderer == null) return;
|
||||
|
||||
Bounds bounds = renderer.bounds;
|
||||
Vector3 size = bounds.size;
|
||||
float[] dimensions = new float[] { size.x, size.y, size.z };
|
||||
System.Array.Sort(dimensions);
|
||||
System.Array.Reverse(dimensions);
|
||||
float largest = dimensions[0];
|
||||
float middle = dimensions[1];
|
||||
float smallest = dimensions[2];
|
||||
float ratio1 = middle / largest;
|
||||
float ratio2 = smallest / largest;
|
||||
|
||||
if (ratio1 > 0.8f && ratio2 > 0.8f)
|
||||
{
|
||||
DetectSphereOrCube(bounds);
|
||||
}
|
||||
else if (ratio2 < 0.3f)
|
||||
{
|
||||
crossSectionArea = largest * middle;
|
||||
dragCoefficient = 1.28f;
|
||||
}
|
||||
else if (ratio1 > 0.7f && ratio2 < 0.7f)
|
||||
{
|
||||
float radius = Mathf.Max(largest, middle) * 0.5f;
|
||||
crossSectionArea = Mathf.PI * radius * radius;
|
||||
dragCoefficient = 0.82f;
|
||||
}
|
||||
else
|
||||
{
|
||||
crossSectionArea = Mathf.Max(
|
||||
size.x * size.y,
|
||||
size.x * size.z,
|
||||
size.y * size.z
|
||||
);
|
||||
dragCoefficient = 1.05f;
|
||||
}
|
||||
}
|
||||
|
||||
void DetectSphereOrCube(Bounds bounds)
|
||||
{
|
||||
MeshFilter meshFilter = GetComponent<MeshFilter>();
|
||||
if (meshFilter != null && meshFilter.sharedMesh != null)
|
||||
{
|
||||
int vertexCount = meshFilter.sharedMesh.vertexCount;
|
||||
if (vertexCount > 100)
|
||||
{
|
||||
float radius = Mathf.Max(bounds.size.x, bounds.size.y, bounds.size.z) * 0.5f;
|
||||
crossSectionArea = Mathf.PI * radius * radius;
|
||||
dragCoefficient = 0.47f;
|
||||
}
|
||||
else
|
||||
{
|
||||
crossSectionArea = Mathf.Max(
|
||||
bounds.size.x * bounds.size.y,
|
||||
bounds.size.x * bounds.size.z,
|
||||
bounds.size.y * bounds.size.z
|
||||
);
|
||||
dragCoefficient = 1.05f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
crossSectionArea = Mathf.Max(
|
||||
bounds.size.x * bounds.size.y,
|
||||
bounds.size.x * bounds.size.z,
|
||||
bounds.size.y * bounds.size.z
|
||||
);
|
||||
dragCoefficient = 1.05f;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/ObjectAirProperties.cs.meta
Normal file
11
Assets/Scripts/ObjectAirProperties.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f9961d795d590eb4c816e070425a736b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
87
Assets/Scripts/ObjectPhysicsInfo.cs
Normal file
87
Assets/Scripts/ObjectPhysicsInfo.cs
Normal file
@@ -0,0 +1,87 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using TMPro;
|
||||
|
||||
public class ObjectPhysicsInfo : MonoBehaviour
|
||||
{
|
||||
|
||||
public TextMeshProUGUI infoText;
|
||||
private Rigidbody _rb;
|
||||
|
||||
private float _startTime;
|
||||
private float _startHeight;
|
||||
private bool _isFalling = false;
|
||||
private bool _hasLanded = false;
|
||||
private float _startMass;
|
||||
|
||||
void Start()
|
||||
{
|
||||
_rb = GetComponent<Rigidbody>();
|
||||
_startMass = _rb.mass;
|
||||
|
||||
if (infoText != null) infoText.text = "";
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (infoText != null)
|
||||
{
|
||||
infoText.transform.parent.LookAt(Camera.main.transform);
|
||||
infoText.transform.parent.Rotate(0, 180, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnRelease()
|
||||
{
|
||||
_startTime = Time.time;
|
||||
_startHeight = transform.position.y;
|
||||
_isFalling = true;
|
||||
_hasLanded = false;
|
||||
|
||||
if (infoText != null) infoText.text = "";
|
||||
}
|
||||
|
||||
void OnCollisionEnter(Collision collision)
|
||||
{
|
||||
|
||||
if (_isFalling && !_hasLanded && collision.gameObject.CompareTag("Ground"))
|
||||
{
|
||||
_hasLanded = true;
|
||||
_isFalling = false;
|
||||
|
||||
float fallTime = Time.time - _startTime;
|
||||
float dropHeight = _startHeight - transform.position.y;
|
||||
float impactSpeed = _rb.velocity.magnitude;
|
||||
float mass = _startMass;
|
||||
float gravityForce = mass * 9.8f;
|
||||
|
||||
float theoreticalTime = Mathf.Sqrt((2 * dropHeight) / 9.8f);
|
||||
|
||||
if (infoText != null)
|
||||
{
|
||||
infoText.text =
|
||||
$"Висота: {dropHeight:F2} м\n" +
|
||||
$"Час падіння: {fallTime:F2} с\n" +
|
||||
$"Швидкість: {impactSpeed:F2} м/с\n" +
|
||||
$"Маса: {mass:F2} кг\n" +
|
||||
$"Сила тяжіння: {mass:F2} × 9.8 = ?? Н\n" +
|
||||
$"Прискорення: 9.8 м/с²";
|
||||
}
|
||||
|
||||
AirTrailController trail = GetComponentInChildren<AirTrailController>();
|
||||
if (trail != null)
|
||||
{
|
||||
trail.Deactivate();
|
||||
}
|
||||
|
||||
Invoke("ClearText", 15f);
|
||||
}
|
||||
}
|
||||
|
||||
void ClearText()
|
||||
{
|
||||
if (infoText != null)
|
||||
infoText.text = "";
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/ObjectPhysicsInfo.cs.meta
Normal file
11
Assets/Scripts/ObjectPhysicsInfo.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b86a5bfdc1f551f45939ce4249726c51
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
131
Assets/Scripts/PlanetInfoDisplay.cs
Normal file
131
Assets/Scripts/PlanetInfoDisplay.cs
Normal file
@@ -0,0 +1,131 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using TMPro;
|
||||
|
||||
|
||||
public class PlanetInfoDisplay : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private PlanetType planetType;
|
||||
[SerializeField] private PlanetSpin planetSpin;
|
||||
[SerializeField] private TextMeshProUGUI infoText;
|
||||
[SerializeField] private float startDistanceUnity;
|
||||
|
||||
private Dictionary<PlanetType, float> _realDistances = new Dictionary<PlanetType, float>()
|
||||
{
|
||||
{ PlanetType.Mercury, 57.9f },
|
||||
{ PlanetType.Venus, 108.2f },
|
||||
{ PlanetType.Earth, 149.6f },
|
||||
{ PlanetType.Mars, 227.9f },
|
||||
{ PlanetType.Jupiter, 778.5f },
|
||||
{ PlanetType.Saturn, 1432f },
|
||||
{ PlanetType.Uranus, 2867f },
|
||||
{ PlanetType.Neptune, 4515f },
|
||||
{ PlanetType.Pluto, 5906f }
|
||||
};
|
||||
|
||||
private Dictionary<PlanetType, float> _realRotationSpeeds = new Dictionary<PlanetType, float>()
|
||||
{
|
||||
{ PlanetType.Mercury, 10.83f },
|
||||
{ PlanetType.Venus, 6.52f },
|
||||
{ PlanetType.Earth, 1674f },
|
||||
{ PlanetType.Mars, 868f },
|
||||
{ PlanetType.Jupiter, 45583f },
|
||||
{ PlanetType.Saturn, 36840f },
|
||||
{ PlanetType.Uranus, 14794f },
|
||||
{ PlanetType.Neptune, 9719f },
|
||||
{ PlanetType.Pluto, 813f }
|
||||
};
|
||||
|
||||
private Dictionary<PlanetType, float> _baseRotationSpeeds = new Dictionary<PlanetType, float>()
|
||||
{
|
||||
{ PlanetType.Mercury, 0.26f },
|
||||
{ PlanetType.Venus, -0.025f },
|
||||
{ PlanetType.Earth, 15f },
|
||||
{ PlanetType.Mars, 14.6f },
|
||||
{ PlanetType.Jupiter, 36.4f },
|
||||
{ PlanetType.Saturn, 33.6f },
|
||||
{ PlanetType.Uranus, -20.9f },
|
||||
{ PlanetType.Neptune, 22.4f },
|
||||
{ PlanetType.Pluto, -2.35f }
|
||||
};
|
||||
|
||||
private Dictionary<PlanetType, float> _orbitalSpeeds = new Dictionary<PlanetType, float>()
|
||||
{
|
||||
{ PlanetType.Mercury, 47.4f },
|
||||
{ PlanetType.Venus, 35.0f },
|
||||
{ PlanetType.Earth, 29.8f },
|
||||
{ PlanetType.Mars, 24.1f },
|
||||
{ PlanetType.Jupiter, 13.1f },
|
||||
{ PlanetType.Saturn, 9.7f },
|
||||
{ PlanetType.Uranus, 6.8f },
|
||||
{ PlanetType.Neptune, 5.4f },
|
||||
{ PlanetType.Pluto, 4.7f }
|
||||
};
|
||||
|
||||
private Dictionary<PlanetType, Vector2> _temperatures = new Dictionary<PlanetType, Vector2>()
|
||||
{
|
||||
{ PlanetType.Mercury, new Vector2(-180f, 430f) },
|
||||
{ PlanetType.Venus, new Vector2(437f, 497f) },
|
||||
{ PlanetType.Earth, new Vector2(-88f, 58f) },
|
||||
{ PlanetType.Mars, new Vector2(-125f, 20f) },
|
||||
{ PlanetType.Jupiter, new Vector2(-145f, -108f) },
|
||||
{ PlanetType.Saturn, new Vector2(-178f, -130f) },
|
||||
{ PlanetType.Uranus, new Vector2(-224f, -197f) },
|
||||
{ PlanetType.Neptune, new Vector2(-218f, -200f) },
|
||||
{ PlanetType.Pluto, new Vector2(-240f, -218f) }
|
||||
};
|
||||
|
||||
private Dictionary<PlanetType, string> _planetTypes = new Dictionary<PlanetType, string>()
|
||||
{
|
||||
{ PlanetType.Mercury, "Êàì'ÿíèñòà" },
|
||||
{ PlanetType.Venus, "Êàì'ÿíèñòà" },
|
||||
{ PlanetType.Earth, "Êàì'ÿíèñòà" },
|
||||
{ PlanetType.Mars, "Êàì'ÿíèñòà" },
|
||||
{ PlanetType.Jupiter, "Ãàçîâèé ã³ãàíò" },
|
||||
{ PlanetType.Saturn, "Ãàçîâèé ã³ãàíò" },
|
||||
{ PlanetType.Uranus, "Êðèæàíèé ã³ãàíò" },
|
||||
{ PlanetType.Neptune, "Êðèæàíèé ã³ãàíò" },
|
||||
{ PlanetType.Pluto, "Êàðëèêîâà" }
|
||||
};
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (infoText == null) return;
|
||||
UpdateInfo();
|
||||
}
|
||||
|
||||
void UpdateInfo()
|
||||
{
|
||||
float currentX = Mathf.Abs(transform.position.x);
|
||||
float distanceKm = 0f;
|
||||
if (startDistanceUnity > 0.001f)
|
||||
{
|
||||
float ratio = currentX / startDistanceUnity;
|
||||
distanceKm = ratio * _realDistances[planetType];
|
||||
}
|
||||
|
||||
float currentRotationSpeed = 0f;
|
||||
if (planetSpin != null)
|
||||
{
|
||||
float baseSpeed = Mathf.Abs(_baseRotationSpeeds[planetType]);
|
||||
float currentSpeed = Mathf.Abs(planetSpin.RotationSpeed);
|
||||
if (baseSpeed > 0.0001f)
|
||||
{
|
||||
float speedRatio = currentSpeed / baseSpeed;
|
||||
currentRotationSpeed = _realRotationSpeeds[planetType] * speedRatio;
|
||||
}
|
||||
}
|
||||
|
||||
float orbitalSpeed = _orbitalSpeeds[planetType];
|
||||
Vector2 temp = _temperatures[planetType];
|
||||
string type = _planetTypes[planetType];
|
||||
|
||||
infoText.text =
|
||||
"Òèï ïëàíåòè: " + type + "\n" +
|
||||
"³äñòàíü â³ä Ñîíöÿ: " + distanceKm.ToString("F1") + " ìëí êì\n" +
|
||||
"Øâèäê³ñòü îáåðòàííÿ íàâêîëî ñâ îñ³: " + currentRotationSpeed.ToString("F0") + " êì/ãîä\n" +
|
||||
"Øâèäê³ñòü ðóõó ïî îðá³ò³ íàâêîëî Ñîíöÿ: " + orbitalSpeed.ToString("F1") + " êì/ñ\n" +
|
||||
"Òåìïåðàòóðà ïîâåðõí³: â³ä "+"\n" + temp.x.ToString("F0") + "°C äî " + temp.y.ToString("F0") + "°C";
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/PlanetInfoDisplay.cs.meta
Normal file
11
Assets/Scripts/PlanetInfoDisplay.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a603e4246d4cb1148b467a94f8472250
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
37
Assets/Scripts/PlanetSpin.cs
Normal file
37
Assets/Scripts/PlanetSpin.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class PlanetSpin : MonoBehaviour
|
||||
{
|
||||
[Header("Ïàðàìåòðè îáåðòàííÿ")]
|
||||
[Header("Íàõèë îñ³")]
|
||||
[Range(0f, 100f)]
|
||||
[SerializeField] private float axialTilt = 0.5f;
|
||||
|
||||
[Header("Øâèäê³ñòü îáåðòàííÿ íàâêîëî îñ³")]
|
||||
[Range(0f, 180f)]
|
||||
[SerializeField] private float rotationSpeed = 10f;
|
||||
|
||||
public float RotationSpeed => rotationSpeed;
|
||||
|
||||
|
||||
void Start()
|
||||
{
|
||||
transform.localRotation = Quaternion.Euler(0f, 0f, axialTilt);
|
||||
}
|
||||
|
||||
public void SetRotationSpeed(float value)
|
||||
{
|
||||
rotationSpeed = value;
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
float rotationThisFrame = rotationSpeed * Time.deltaTime;
|
||||
|
||||
transform.Rotate(Vector3.up, rotationThisFrame, Space.Self);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
11
Assets/Scripts/PlanetSpin.cs.meta
Normal file
11
Assets/Scripts/PlanetSpin.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1f369feea756f9f4d9b6e1c778bd9a8e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
36
Assets/Scripts/PlayZone.cs
Normal file
36
Assets/Scripts/PlayZone.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class PlayZone : MonoBehaviour
|
||||
{
|
||||
private BoxCollider _box;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_box = GetComponent<BoxCollider>();
|
||||
}
|
||||
|
||||
public Vector3 ClampToZone(Vector3 position)
|
||||
{
|
||||
Vector3 localPos = transform.InverseTransformPoint(position);
|
||||
Vector3 halfSize = _box.size / 2f;
|
||||
|
||||
localPos.x = Mathf.Clamp(localPos.x, -halfSize.x, halfSize.x);
|
||||
localPos.z = Mathf.Clamp(localPos.z, -halfSize.z, halfSize.z);
|
||||
|
||||
return transform.TransformPoint(localPos);
|
||||
}
|
||||
|
||||
public Vector3 GetRandomPoint()
|
||||
{
|
||||
Vector3 halfSize = _box.size / 2f;
|
||||
|
||||
float randomX = Random.Range(-halfSize.x, halfSize.x);
|
||||
float randomZ = Random.Range(-halfSize.z, halfSize.z);
|
||||
|
||||
Vector3 localPoint = new Vector3(randomX, 0f, randomZ);
|
||||
|
||||
return transform.TransformPoint(localPoint);
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/PlayZone.cs.meta
Normal file
11
Assets/Scripts/PlayZone.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cce531398b0b90c49a22dfd22d08509a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
24
Assets/Scripts/PlayerKick.cs
Normal file
24
Assets/Scripts/PlayerKick.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class PlayerKick : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private float kickForce = 8f;
|
||||
|
||||
private void OnControllerColliderHit(ControllerColliderHit hit)
|
||||
{
|
||||
if (hit.collider.CompareTag("Ball"))
|
||||
{
|
||||
Rigidbody rb = hit.collider.GetComponent<Rigidbody>();
|
||||
|
||||
if (rb != null)
|
||||
{
|
||||
Vector3 direction = hit.moveDirection;
|
||||
direction.y = 0.3f;
|
||||
|
||||
rb.AddForce(direction * kickForce, ForceMode.Impulse);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/PlayerKick.cs.meta
Normal file
11
Assets/Scripts/PlayerKick.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 91e0a7d0d5f450b49bbc4ece8b04efbe
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
18
Assets/Scripts/PoliceIdle.cs
Normal file
18
Assets/Scripts/PoliceIdle.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class PoliceIdle : MonoBehaviour
|
||||
{
|
||||
private Animator animator;
|
||||
|
||||
void Start()
|
||||
{
|
||||
animator = GetComponent<Animator>();
|
||||
|
||||
if (animator != null)
|
||||
{
|
||||
animator.Play("idle_selfcheck_1_300f");
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/PoliceIdle.cs.meta
Normal file
11
Assets/Scripts/PoliceIdle.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ff2fbe1dc3d74224b8e0916d941d5e5c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
14
Assets/Scripts/SolarCursor.cs
Normal file
14
Assets/Scripts/SolarCursor.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class SolarCursor : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Texture2D cursorTexture;
|
||||
|
||||
void Start()
|
||||
{
|
||||
Vector2 hotspot = new Vector2(0, 0);
|
||||
Cursor.SetCursor(cursorTexture, hotspot, CursorMode.Auto);
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/SolarCursor.cs.meta
Normal file
11
Assets/Scripts/SolarCursor.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8f09bdc61ab395549a25cc87eee879e1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
54
Assets/Scripts/SolarSystem.cs
Normal file
54
Assets/Scripts/SolarSystem.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class SolarSystem : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private float G = 100f;
|
||||
private GameObject[] celestials;
|
||||
void Start()
|
||||
{
|
||||
celestials = GameObject.FindGameObjectsWithTag("Celestial");
|
||||
InitialVelocity();
|
||||
}
|
||||
private void FixedUpdate()
|
||||
{
|
||||
Gravity();
|
||||
}
|
||||
void Gravity()
|
||||
{
|
||||
foreach (GameObject a in celestials)
|
||||
{
|
||||
foreach (GameObject b in celestials)
|
||||
{
|
||||
if (!a.Equals(b))
|
||||
{
|
||||
float m1 = a.GetComponent<Rigidbody>().mass;
|
||||
float m2 = b.GetComponent<Rigidbody>().mass;
|
||||
float r = Vector3.Distance(a.transform.position, b.transform.position);
|
||||
a.GetComponent<Rigidbody>().AddForce(
|
||||
(b.transform.position - a.transform.position).normalized *
|
||||
(G * (m1 * m2) / (r * r))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void InitialVelocity()
|
||||
{
|
||||
foreach (GameObject a in celestials)
|
||||
{
|
||||
foreach (GameObject b in celestials)
|
||||
{
|
||||
if (!a.Equals(b))
|
||||
{
|
||||
float m2 = b.GetComponent<Rigidbody>().mass;
|
||||
float r = Vector3.Distance(a.transform.position, b.transform.position);
|
||||
a.transform.LookAt(b.transform);
|
||||
a.GetComponent<Rigidbody>().velocity +=
|
||||
a.transform.right * Mathf.Sqrt((G * m2) / r);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/SolarSystem.cs.meta
Normal file
11
Assets/Scripts/SolarSystem.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5b225d72a40ccca47b90fa93727bf38b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Scripts/Stars.meta
Normal file
8
Assets/Scripts/Stars.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7ac8afc20216cc943999b25eec52bce4
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1224
Assets/Scripts/Stars/ZodiacConstellations.cs
Normal file
1224
Assets/Scripts/Stars/ZodiacConstellations.cs
Normal file
File diff suppressed because it is too large
Load Diff
11
Assets/Scripts/Stars/ZodiacConstellations.cs.meta
Normal file
11
Assets/Scripts/Stars/ZodiacConstellations.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d156cf8c15007d34897098a176a47aa4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
20
Assets/Scripts/Swing.cs
Normal file
20
Assets/Scripts/Swing.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class Swing : MonoBehaviour
|
||||
{
|
||||
private Rigidbody _rb;
|
||||
[SerializeField] private float torque = 30f;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
_rb = GetComponent<Rigidbody>();
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
_rb.WakeUp();
|
||||
_rb.AddTorque(transform.right * torque, ForceMode.Impulse);
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/Swing.cs.meta
Normal file
11
Assets/Scripts/Swing.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b569dd5f1ef04734786caea7a15914b6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
36
Assets/Scripts/SwingRotate.cs
Normal file
36
Assets/Scripts/SwingRotate.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class SwingRotate : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Vector3 rotationAxis = Vector3.up;
|
||||
[SerializeField] private float rotationSpeed = 60f;
|
||||
|
||||
private bool isActive = false;
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (isActive)
|
||||
{
|
||||
transform.Rotate(rotationAxis * rotationSpeed * Time.deltaTime, Space.Self);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTriggerExit(Collider other)
|
||||
{
|
||||
if (other.gameObject.CompareTag("Player"))
|
||||
{
|
||||
isActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTriggerEnter(Collider other)
|
||||
{
|
||||
if (other.gameObject.CompareTag("Player"))
|
||||
{
|
||||
isActive = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
11
Assets/Scripts/SwingRotate.cs.meta
Normal file
11
Assets/Scripts/SwingRotate.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b61a395f59b9a784bb63fb14901dc3ec
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
58
Assets/Scripts/SwingSmoothRotate.cs
Normal file
58
Assets/Scripts/SwingSmoothRotate.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class SwingSmoothRotate : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Transform swing;
|
||||
|
||||
[SerializeField] private float leftAngle = -2.457f;
|
||||
[SerializeField] private float rightAngle = 21f;
|
||||
[SerializeField] private float rotateSpeed = 60f;
|
||||
|
||||
private float targetAngleX;
|
||||
private bool rotate = false;
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (!rotate) return;
|
||||
|
||||
Vector3 current = swing.localEulerAngles;
|
||||
float currentX = NormalizeAngle(current.x);
|
||||
|
||||
float newX = Mathf.MoveTowards(
|
||||
currentX,
|
||||
targetAngleX,
|
||||
rotateSpeed * Time.deltaTime
|
||||
);
|
||||
|
||||
swing.localEulerAngles = new Vector3(newX, current.y, current.z);
|
||||
|
||||
if (Mathf.Abs(newX - targetAngleX) < 0.1f)
|
||||
{
|
||||
rotate = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTriggerEnter(Collider other)
|
||||
{
|
||||
if (!other.CompareTag("Player")) return;
|
||||
|
||||
if (gameObject.name.Contains("Left"))
|
||||
{
|
||||
targetAngleX = leftAngle;
|
||||
rotate = true;
|
||||
}
|
||||
else if (gameObject.name.Contains("Right"))
|
||||
{
|
||||
targetAngleX = rightAngle;
|
||||
rotate = true;
|
||||
}
|
||||
}
|
||||
|
||||
private float NormalizeAngle(float angle)
|
||||
{
|
||||
if (angle > 180f) angle -= 360f;
|
||||
return angle;
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/SwingSmoothRotate.cs.meta
Normal file
11
Assets/Scripts/SwingSmoothRotate.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 091aa36193a940447911510f3069411f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
185
Assets/Scripts/ZodiacCameraController.cs
Normal file
185
Assets/Scripts/ZodiacCameraController.cs
Normal file
@@ -0,0 +1,185 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class ZodiacCameraController : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Transform zodiacRoot;
|
||||
[SerializeField] private Camera zodiacCamera;
|
||||
|
||||
private int _currentIndex = 0;
|
||||
|
||||
private Dictionary<string, CameraPreset> _presets;
|
||||
|
||||
private struct CameraPreset
|
||||
{
|
||||
public Vector3 localPosition;
|
||||
public Vector3 localRotation;
|
||||
|
||||
public CameraPreset(Vector3 pos, Vector3 rot)
|
||||
{
|
||||
localPosition = pos;
|
||||
localRotation = rot;
|
||||
}
|
||||
}
|
||||
|
||||
void Awake()
|
||||
{
|
||||
_presets = new Dictionary<string, CameraPreset>
|
||||
{
|
||||
{ "Zodiac_Aries",
|
||||
new CameraPreset(
|
||||
new Vector3(52670f, 0f, 2644f),
|
||||
new Vector3(0f, 82.342f, 0f))
|
||||
},
|
||||
{ "Zodiac_Taurus",
|
||||
new CameraPreset(
|
||||
new Vector3(29399f, 17419f, 26891f),
|
||||
new Vector3(-1.675f, 69.34f, 0.769f))
|
||||
},
|
||||
{ "Zodiac_Gemini",
|
||||
new CameraPreset(
|
||||
new Vector3(27079f, 23051f, 31496f),
|
||||
new Vector3(-2.952f, 20.843f, 1.051f)
|
||||
)
|
||||
},
|
||||
{ "Zodiac_Cancer",
|
||||
new CameraPreset(
|
||||
new Vector3(5146f, 26343f, 37622f),
|
||||
new Vector3(-18.238f, -25.072f, 15.872f))
|
||||
},
|
||||
{ "Zodiac_Leo",
|
||||
new CameraPreset(
|
||||
new Vector3(-24035f, 18632f, 24187f),
|
||||
new Vector3(-11.603f, -31.992f, 4.569f)
|
||||
)
|
||||
},
|
||||
{ "Zodiac_Virgo",
|
||||
new CameraPreset(
|
||||
new Vector3(-66493f, 26979f, -12167f),
|
||||
new Vector3(-3.051f, -70.52f, 0.831f)
|
||||
)
|
||||
},
|
||||
{ "Zodiac_Libra",
|
||||
new CameraPreset(
|
||||
new Vector3(-47207f, 2331f, -17070f),
|
||||
new Vector3(5.864f, -45.753f, -3.965f))
|
||||
},
|
||||
{ "Zodiac_Scorpius",
|
||||
new CameraPreset(
|
||||
new Vector3(23243f, -3793f, -41775f),
|
||||
new Vector3(-3.387f, -108.118f, -1.408f))
|
||||
},
|
||||
{ "Zodiac_Ophiuchus",
|
||||
new CameraPreset(
|
||||
new Vector3(-5486f, -72738f, -60897f),
|
||||
new Vector3(-19.647f, 0.134f, 15.524f))
|
||||
},
|
||||
{ "Zodiac_Sagittarius",
|
||||
new CameraPreset(
|
||||
new Vector3(-22611f, -22913f, -34762f),
|
||||
new Vector3(-0.858f, -163.7f, 0.486f))
|
||||
},
|
||||
{ "Zodiac_Capricornus",
|
||||
new CameraPreset(
|
||||
new Vector3(-9422f, -33410f, -64497f),
|
||||
new Vector3(20.279f, 160.564f, 2f))
|
||||
},
|
||||
{ "Zodiac_Aquarius",
|
||||
new CameraPreset(
|
||||
new Vector3(23361f, -23299f, -35603f),
|
||||
new Vector3(-2.652f, 146.782f, 0f))
|
||||
},
|
||||
{ "Zodiac_Pisces",
|
||||
new CameraPreset(
|
||||
new Vector3(33456f, -10168f, -23088f),
|
||||
new Vector3(-9.924f, 109.295f, 3.294f))
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
//zodiacCamera.enabled = true;
|
||||
|
||||
if (zodiacRoot.childCount > 0)
|
||||
FocusCurrent();
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (Input.GetKeyDown(KeyCode.RightArrow))
|
||||
Next();
|
||||
|
||||
if (Input.GetKeyDown(KeyCode.LeftArrow))
|
||||
Previous();
|
||||
}
|
||||
|
||||
void Next()
|
||||
{
|
||||
_currentIndex++;
|
||||
if (_currentIndex >= zodiacRoot.childCount)
|
||||
_currentIndex = 0;
|
||||
|
||||
FocusCurrent();
|
||||
}
|
||||
|
||||
void Previous()
|
||||
{
|
||||
_currentIndex--;
|
||||
if (_currentIndex < 0)
|
||||
_currentIndex = zodiacRoot.childCount - 1;
|
||||
|
||||
FocusCurrent();
|
||||
}
|
||||
|
||||
void FocusCurrent()
|
||||
{
|
||||
if (zodiacRoot == null || zodiacRoot.childCount == 0) return;
|
||||
|
||||
if (_currentIndex < 0 || _currentIndex >= zodiacRoot.childCount)
|
||||
_currentIndex = 0;
|
||||
|
||||
Transform constellation = zodiacRoot.GetChild(_currentIndex);
|
||||
|
||||
if (_presets.ContainsKey(constellation.name))
|
||||
{
|
||||
CameraPreset preset = _presets[constellation.name];
|
||||
|
||||
zodiacCamera.transform.SetParent(null);
|
||||
zodiacCamera.transform.position = preset.localPosition;
|
||||
zodiacCamera.transform.rotation = Quaternion.Euler(preset.localRotation);
|
||||
}
|
||||
else
|
||||
{
|
||||
ApplyFallback(constellation);
|
||||
}
|
||||
}
|
||||
|
||||
void ApplyFallback(Transform constellation)
|
||||
{
|
||||
Bounds bounds = CalculateBounds(constellation);
|
||||
Vector3 center = bounds.center;
|
||||
|
||||
Vector3 dir = new Vector3(-1f, 0f, 0f).normalized;
|
||||
float size = Mathf.Max(bounds.size.x, bounds.size.y);
|
||||
float distance = Mathf.Max(size * 1.6f, 1600f);
|
||||
|
||||
zodiacCamera.transform.SetParent(null);
|
||||
zodiacCamera.transform.position = center + dir * distance;
|
||||
zodiacCamera.transform.LookAt(center, Vector3.up);
|
||||
}
|
||||
|
||||
Bounds CalculateBounds(Transform root)
|
||||
{
|
||||
Renderer[] renderers = root.GetComponentsInChildren<Renderer>();
|
||||
|
||||
Bounds bounds = renderers[0].bounds;
|
||||
for (int i = 1; i < renderers.Length; i++)
|
||||
bounds.Encapsulate(renderers[i].bounds);
|
||||
|
||||
return bounds;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
11
Assets/Scripts/ZodiacCameraController.cs.meta
Normal file
11
Assets/Scripts/ZodiacCameraController.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 99b8956777a4ca242a475f8f4d354d12
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user