162 lines
6.4 KiB
C#
162 lines
6.4 KiB
C#
using System.Collections;
|
|
using UnityEngine;
|
|
using UnityEngine.SceneManagement;
|
|
using Cinemachine;
|
|
using DG.Tweening;
|
|
|
|
namespace CryingSnow.FarmingIsland
|
|
{
|
|
public class ATCTower : MonoBehaviour, IProp
|
|
{
|
|
[Tooltip("The helicopter prefab used in the animation sequence.")]
|
|
[SerializeField] private Helicopter helicopterPrefab;
|
|
|
|
[Tooltip("The position on the helipad where the helicopter spawns.")]
|
|
[SerializeField] private Transform helipadTransform;
|
|
|
|
[Tooltip("Offset for the player's entry position relative to the helipad.")]
|
|
[SerializeField] private Vector3 entryOffset = new Vector3(1.5f, 0f, -0.5f);
|
|
|
|
[Tooltip("Offset for the helicopter's final destination position during takeoff.")]
|
|
[SerializeField] private Vector3 destinationOffset = new Vector3(80f, 20f, 0f);
|
|
|
|
[Tooltip("Reference to the virtual camera that tracks the helicopter.")]
|
|
[SerializeField] private CinemachineVirtualCamera virtualCamera;
|
|
|
|
Location IProp.Location => Location.Tower;
|
|
|
|
// Lazy-loaded reference to the PlayerController
|
|
private PlayerController _player;
|
|
private PlayerController player
|
|
{
|
|
get
|
|
{
|
|
if (_player == null)
|
|
_player = FindFirstObjectByType<PlayerController>();
|
|
return _player;
|
|
}
|
|
}
|
|
|
|
// Flag to ensure the flight sequence only runs once at a time
|
|
private bool isFlying;
|
|
|
|
private void Awake()
|
|
{
|
|
// Start with the tower scaled down to zero for animation purposes
|
|
transform.localScale = Vector3.zero;
|
|
}
|
|
|
|
// Animate the tower appearance and trigger the helicopter sequence
|
|
void IProp.Animate(bool instant, System.Action onFinished)
|
|
{
|
|
if (instant)
|
|
{
|
|
// Instantly set the tower's scale without animation
|
|
transform.localScale = Vector3.one;
|
|
onFinished?.Invoke();
|
|
}
|
|
else
|
|
{
|
|
// Animate the tower's appearance with a bounce effect
|
|
transform.DOScale(Vector3.one, 1f)
|
|
.SetEase(Ease.OutBounce)
|
|
.OnComplete(() =>
|
|
{
|
|
onFinished?.Invoke();
|
|
StartCoroutine(Fly());
|
|
});
|
|
}
|
|
}
|
|
|
|
// Trigger the flight sequence when the player enters the tower's collider
|
|
void OnTriggerEnter(Collider other)
|
|
{
|
|
if (other.CompareTag("Player"))
|
|
{
|
|
_player = other.GetComponent<PlayerController>();
|
|
StartCoroutine(Fly());
|
|
}
|
|
}
|
|
|
|
// Coroutine to handle the helicopter flight sequence and scene transition
|
|
IEnumerator Fly()
|
|
{
|
|
if (isFlying) yield break; // Prevent multiple flight sequences from running concurrently
|
|
|
|
isFlying = true;
|
|
|
|
player.IsControllable = false; // Disable player control during the sequence
|
|
UIManager.Instance.ToggleHUD(false); // Hide HUD elements
|
|
UIManager.Instance.SetActiveJoystick(false); // Hide joystick controls
|
|
|
|
// Calculate the helicopter's spawn point above the helipad
|
|
float flyingHeight = destinationOffset.y;
|
|
var spawnPoint = helipadTransform.position + Vector3.up * flyingHeight;
|
|
var lookRotation = Quaternion.Euler(0f, 180f, 0f);
|
|
var helicopter = Instantiate(helicopterPrefab, spawnPoint, lookRotation).transform;
|
|
|
|
// Set the virtual camera to focus on the helicopter
|
|
virtualCamera.m_LookAt = helicopter;
|
|
virtualCamera.gameObject.SetActive(true);
|
|
|
|
yield return new WaitForSeconds(1f); // Small delay before lowering the helicopter
|
|
|
|
// Lower the helicopter to the helipad
|
|
yield return helicopter.DOMoveY(0f, 5f).WaitForCompletion();
|
|
|
|
// Move the player towards the helipad's entry point
|
|
var entryPoint = helipadTransform.position + entryOffset;
|
|
yield return player.SetDestination(entryPoint);
|
|
|
|
// Hide the player after reaching the destination
|
|
player.SetVisible(false);
|
|
|
|
yield return new WaitForSeconds(1f); // Pause before lifting off
|
|
|
|
// Raise the helicopter to its flying height
|
|
yield return helicopter.DOMoveY(flyingHeight, 5f).WaitForCompletion();
|
|
|
|
// Calculate the direction and rotation for the helicopter's destination
|
|
Vector3 flyingDestination = helipadTransform.position + destinationOffset;
|
|
Vector3 flyingDirection = (flyingDestination.Flatten() - helipadTransform.position).normalized;
|
|
Quaternion flyingLookRotation = Quaternion.LookRotation(flyingDirection);
|
|
|
|
// Rotate the helicopter towards its flying direction
|
|
yield return helicopter.DORotate(flyingLookRotation.eulerAngles, 2f).WaitForCompletion();
|
|
|
|
// Apply a slight tilt to simulate forward acceleration
|
|
Quaternion tiltAngle = helicopter.rotation * Quaternion.Euler(15f, 0f, 0f);
|
|
helicopter.DORotateQuaternion(tiltAngle, 1f);
|
|
|
|
// Move the helicopter towards its destination at a consistent speed
|
|
yield return helicopter.DOMove(flyingDestination, 5f).SetSpeedBased().WaitForCompletion();
|
|
|
|
// Trigger the scene transition
|
|
yield return GoToNextScene();
|
|
}
|
|
|
|
// Coroutine to handle the transition to the next scene
|
|
IEnumerator GoToNextScene()
|
|
{
|
|
// Fade the screen out before loading the new scene
|
|
yield return UIManager.Instance.FadeInScreen();
|
|
|
|
int destinationSceneIndex = SceneManager.GetActiveScene().buildIndex + 1;
|
|
AsyncOperation asyncOperation = SceneManager.LoadSceneAsync(destinationSceneIndex);
|
|
asyncOperation.allowSceneActivation = false;
|
|
|
|
// Wait until the scene is fully loaded but not yet activated
|
|
while (!asyncOperation.isDone)
|
|
{
|
|
if (asyncOperation.progress >= 0.9f)
|
|
{
|
|
yield return new WaitForSeconds(1f); // Delay before activating the scene
|
|
asyncOperation.allowSceneActivation = true; // Activate the new scene
|
|
}
|
|
|
|
yield return null; // Continue waiting until the next frame
|
|
}
|
|
}
|
|
}
|
|
}
|