Pulver trash maze sequence
This commit is contained in:
92
Assets/Scripts/Minigames/TrashMaze/Objects/MazeExit.cs
Normal file
92
Assets/Scripts/Minigames/TrashMaze/Objects/MazeExit.cs
Normal file
@@ -0,0 +1,92 @@
|
||||
using System.Collections;
|
||||
using Core;
|
||||
using Interactions;
|
||||
using Minigames.TrashMaze.Core;
|
||||
using Minigames.TrashMaze.Data;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Minigames.TrashMaze.Objects
|
||||
{
|
||||
/// <summary>
|
||||
/// Maze exit interactable that teleports Pulver out of the maze.
|
||||
/// Uses camera blend with midway teleportation to create seamless transition.
|
||||
/// Does NOT switch controllers - Pulver remains player-controlled.
|
||||
/// </summary>
|
||||
public class MazeExit : SaveableInteractable
|
||||
{
|
||||
[Header("Maze Exit Settings")]
|
||||
[Tooltip("Transform where Pulver should be teleported to (maze exit position)")]
|
||||
[SerializeField] private Transform teleportTarget;
|
||||
|
||||
[Tooltip("Camera state to blend to (typically PulverGameplay)")]
|
||||
[SerializeField] private TrashMazeCameraState targetCameraState = TrashMazeCameraState.PulverGameplay;
|
||||
|
||||
public override string SaveId => $"{gameObject.scene.name}/MazeExit/{gameObject.name}";
|
||||
|
||||
protected override object GetSerializableState()
|
||||
{
|
||||
// MazeExit doesn't need to save state - it's a simple trigger
|
||||
return null;
|
||||
}
|
||||
|
||||
protected override void ApplySerializableState(string state)
|
||||
{
|
||||
// MazeExit doesn't need to restore state
|
||||
}
|
||||
|
||||
protected override bool DoInteraction()
|
||||
{
|
||||
Logging.Debug("[MazeExit] Starting maze exit sequence");
|
||||
|
||||
StartCoroutine(ExitMazeSequence());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private IEnumerator ExitMazeSequence()
|
||||
{
|
||||
// Step 1: Find Pulver (should be the active player-controlled character)
|
||||
var pulverController = FindFirstObjectByType<PulverController>();
|
||||
if (pulverController == null)
|
||||
{
|
||||
Debug.LogError("[MazeExit] PulverController not found in scene!");
|
||||
yield break;
|
||||
}
|
||||
|
||||
GameObject pulverGameObject = pulverController.gameObject;
|
||||
Logging.Debug($"[MazeExit] Found Pulver at {pulverGameObject.transform.position}");
|
||||
|
||||
// Step 2: Start camera blend to target state (PulverGameplay)
|
||||
TeleportationHelper.StartCameraBlend(targetCameraState);
|
||||
|
||||
// Step 3: Wait for halfway through blend, teleport Pulver, and set tracking target
|
||||
yield return TeleportationHelper.TeleportMidBlendAndSetTracking(pulverGameObject, teleportTarget, targetCameraState);
|
||||
|
||||
// Step 4: Wait for camera blend to complete
|
||||
yield return TeleportationHelper.WaitForCameraBlend();
|
||||
|
||||
// Step 5: Stop Pulver movement to prevent it from continuing with cached input
|
||||
if (pulverController != null)
|
||||
{
|
||||
pulverController.InterruptMoveTo();
|
||||
Logging.Debug("[MazeExit] Stopped Pulver movement after teleportation");
|
||||
}
|
||||
|
||||
Logging.Debug("[MazeExit] Maze exit sequence completed");
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnValidate()
|
||||
{
|
||||
name = "MazeExit";
|
||||
|
||||
// Default to PulverGameplay camera
|
||||
if (targetCameraState == TrashMazeCameraState.Gameplay)
|
||||
{
|
||||
targetCameraState = TrashMazeCameraState.PulverGameplay;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4543937f547b49ce8e506aac52442f73
|
||||
timeCreated: 1766151078
|
||||
@@ -0,0 +1,158 @@
|
||||
using System.Collections;
|
||||
using Core;
|
||||
using Minigames.TrashMaze.Core;
|
||||
using Minigames.TrashMaze.Data;
|
||||
using Unity.Cinemachine;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Minigames.TrashMaze.Objects
|
||||
{
|
||||
/// <summary>
|
||||
/// Static helper class for trash maze teleportation logic.
|
||||
/// Provides reusable methods for:
|
||||
/// - Starting camera blend to a target state
|
||||
/// - Teleporting a character midway through blend
|
||||
/// - Repositioning camera to teleported character
|
||||
/// - Setting up camera tracking after blend completes
|
||||
/// </summary>
|
||||
public static class TeleportationHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Get the camera for the target camera state
|
||||
/// </summary>
|
||||
private static CinemachineCamera GetTargetCamera(TrashMazeCameraState cameraState)
|
||||
{
|
||||
if (TrashMazeCameraController.Instance == null)
|
||||
return null;
|
||||
|
||||
return cameraState switch
|
||||
{
|
||||
TrashMazeCameraState.Gameplay => TrashMazeCameraController.Instance.GetGameplayCamera(),
|
||||
TrashMazeCameraState.Maze => TrashMazeCameraController.Instance.GetMazeCamera(),
|
||||
TrashMazeCameraState.PulverGameplay => TrashMazeCameraController.Instance.GetPulverGameplayCamera(),
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start the camera blend to the target state
|
||||
/// </summary>
|
||||
public static void StartCameraBlend(TrashMazeCameraState targetState)
|
||||
{
|
||||
if (TrashMazeCameraController.Instance != null)
|
||||
{
|
||||
Logging.Debug($"[TeleportationHelper] Starting camera blend to {targetState}");
|
||||
|
||||
switch (targetState)
|
||||
{
|
||||
case TrashMazeCameraState.Gameplay:
|
||||
TrashMazeCameraController.Instance.SwitchToGameplay();
|
||||
break;
|
||||
case TrashMazeCameraState.Maze:
|
||||
TrashMazeCameraController.Instance.SwitchToMaze();
|
||||
break;
|
||||
case TrashMazeCameraState.PulverGameplay:
|
||||
TrashMazeCameraController.Instance.SwitchToPulverGameplay();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError($"[TeleportationHelper] TrashMazeCameraController instance not found!");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Coroutine that waits for halfway through camera blend, then teleports the character
|
||||
/// and immediately sets it as the tracking target for the camera
|
||||
/// </summary>
|
||||
public static IEnumerator TeleportMidBlendAndSetTracking(GameObject character, Transform teleportTarget, TrashMazeCameraState targetCameraState)
|
||||
{
|
||||
CinemachineBrain brain = Camera.main?.GetComponent<CinemachineBrain>();
|
||||
|
||||
if (brain != null && brain.IsBlending)
|
||||
{
|
||||
// Get blend duration from brain
|
||||
float blendDuration = brain.ActiveBlend != null ? brain.ActiveBlend.Duration : 1f;
|
||||
float halfBlendTime = blendDuration / 2f;
|
||||
|
||||
Logging.Debug($"[TeleportationHelper] Waiting {halfBlendTime:F2}s (half of {blendDuration:F2}s blend) before teleport");
|
||||
|
||||
// Wait for halfway through the blend
|
||||
yield return new WaitForSeconds(halfBlendTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fallback: wait a short moment if no blend is detected
|
||||
yield return new WaitForSeconds(0.25f);
|
||||
}
|
||||
|
||||
// Teleport character
|
||||
if (character != null && teleportTarget != null)
|
||||
{
|
||||
character.transform.position = teleportTarget.position;
|
||||
character.transform.rotation = teleportTarget.rotation;
|
||||
Logging.Debug($"[TeleportationHelper] Teleported {character.name} to {teleportTarget.position}");
|
||||
|
||||
// Immediately set as tracking target - let the blend finish naturally
|
||||
SetCameraTrackingTarget(character, targetCameraState);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (character == null)
|
||||
Debug.LogError($"[TeleportationHelper] Character GameObject is null!");
|
||||
if (teleportTarget == null)
|
||||
Debug.LogError($"[TeleportationHelper] Teleport target not assigned!");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wait for camera blend to complete
|
||||
/// </summary>
|
||||
public static IEnumerator WaitForCameraBlend()
|
||||
{
|
||||
CinemachineBrain brain = Camera.main?.GetComponent<CinemachineBrain>();
|
||||
|
||||
if (brain != null)
|
||||
{
|
||||
// Wait until blend is complete
|
||||
while (brain.IsBlending)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
|
||||
Logging.Debug($"[TeleportationHelper] Camera blend completed");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fallback: wait a brief moment
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a character as the tracking target for the target camera
|
||||
/// </summary>
|
||||
public static void SetCameraTrackingTarget(GameObject character, TrashMazeCameraState targetCameraState)
|
||||
{
|
||||
if (character == null)
|
||||
{
|
||||
Debug.LogError($"[TeleportationHelper] Cannot set tracking target - character is null");
|
||||
return;
|
||||
}
|
||||
|
||||
var targetCamera = GetTargetCamera(targetCameraState);
|
||||
if (targetCamera != null)
|
||||
{
|
||||
targetCamera.Follow = character.transform;
|
||||
targetCamera.LookAt = character.transform;
|
||||
Logging.Debug($"[TeleportationHelper] Set {character.name} as tracking target for {targetCameraState} camera");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError($"[TeleportationHelper] Target camera for state {targetCameraState} not found!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1cf42e4c3a1e3c345aaef352bf84c762
|
||||
@@ -0,0 +1,109 @@
|
||||
using System.Collections;
|
||||
using Core;
|
||||
using Input;
|
||||
using Items;
|
||||
using Minigames.TrashMaze.Core;
|
||||
using Minigames.TrashMaze.Data;
|
||||
using Unity.Cinemachine;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Minigames.TrashMaze.Objects
|
||||
{
|
||||
/// <summary>
|
||||
/// Trash Maze specific controller switch that transitions TO Pulver (maze entrance).
|
||||
/// Handles camera blend with midway teleportation to create the illusion of entering the maze.
|
||||
/// </summary>
|
||||
public class TrashMazeSwitchToPulver : ControllerSwitchItem
|
||||
{
|
||||
[Header("Trash Maze - To Pulver Settings")]
|
||||
[Tooltip("Transform where Pulver should be teleported to (maze entrance)")]
|
||||
[SerializeField] private Transform teleportTarget;
|
||||
|
||||
[Tooltip("Camera state to blend to (Maze camera)")]
|
||||
[SerializeField] private TrashMazeCameraState targetCameraState = TrashMazeCameraState.Maze;
|
||||
|
||||
protected override IEnumerator SwitchControllerSequence()
|
||||
{
|
||||
_isSwitching = true;
|
||||
|
||||
// Step 1: Get controllers
|
||||
var currentController = InputManager.Instance.GetActiveController();
|
||||
var targetController = InputManager.Instance.GetController("pulver");
|
||||
|
||||
if (currentController == null || targetController == null)
|
||||
{
|
||||
Debug.LogError($"[TrashMazeSwitchToPulver] Failed to get controllers!");
|
||||
_isSwitching = false;
|
||||
yield break;
|
||||
}
|
||||
|
||||
GameObject currentGameObject = (currentController as MonoBehaviour)?.gameObject;
|
||||
GameObject targetGameObject = (targetController as MonoBehaviour)?.gameObject;
|
||||
|
||||
Logging.Debug($"[TrashMazeSwitchToPulver] Switching from {currentGameObject?.name} to Pulver");
|
||||
|
||||
// Step 2: Deactivate current controller (Trafalgar)
|
||||
DeactivateCurrentController(currentController, currentGameObject);
|
||||
|
||||
// Step 3: Deactivate Pulver's follower controller (will be teleported)
|
||||
if (targetGameObject != null)
|
||||
{
|
||||
var pulverFollower = targetGameObject.GetComponent<FollowerController>();
|
||||
if (pulverFollower != null)
|
||||
{
|
||||
pulverFollower.DeactivateFollower();
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4: Start camera blend to maze
|
||||
TeleportationHelper.StartCameraBlend(targetCameraState);
|
||||
|
||||
// Step 5: Wait for halfway through the blend, teleport Pulver, and set tracking target
|
||||
yield return TeleportationHelper.TeleportMidBlendAndSetTracking(targetGameObject, teleportTarget, targetCameraState);
|
||||
|
||||
// Step 6: Wait for camera blend to complete
|
||||
yield return TeleportationHelper.WaitForCameraBlend();
|
||||
|
||||
// Step 7: Activate Pulver controller
|
||||
if (targetController is BasePlayerMovementController targetPlayerController)
|
||||
{
|
||||
targetPlayerController.ActivateController();
|
||||
}
|
||||
|
||||
// Step 8: Switch InputManager to Pulver controller
|
||||
bool switchSuccess = InputManager.Instance.SwitchToController("pulver");
|
||||
|
||||
if (switchSuccess)
|
||||
{
|
||||
Logging.Debug($"[TrashMazeSwitchToPulver] Successfully switched to Pulver controller");
|
||||
OnCharacterSwitch.Invoke();
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError($"[TrashMazeSwitchToPulver] Failed to switch to Pulver controller");
|
||||
}
|
||||
|
||||
// Step 9: Mark as used if one-time use
|
||||
if (isOneTime)
|
||||
{
|
||||
DisableVisual();
|
||||
}
|
||||
|
||||
_isSwitching = false;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnValidate()
|
||||
{
|
||||
name = "TrashMazeSwitch_ToPulver";
|
||||
|
||||
// Default to Maze camera
|
||||
if (targetCameraState != TrashMazeCameraState.Maze)
|
||||
{
|
||||
targetCameraState = TrashMazeCameraState.Maze;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fe2d6200d0d54638adb61befd932228f
|
||||
timeCreated: 1766149622
|
||||
@@ -0,0 +1,180 @@
|
||||
using System.Collections;
|
||||
using Core;
|
||||
using Input;
|
||||
using Items;
|
||||
using Minigames.TrashMaze.Core;
|
||||
using Minigames.TrashMaze.Data;
|
||||
using Unity.Cinemachine;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Minigames.TrashMaze.Objects
|
||||
{
|
||||
/// <summary>
|
||||
/// Trash Maze specific controller switch that transitions FROM Pulver back TO Trafalgar (maze exit).
|
||||
/// Handles camera blend back to gameplay view and re-enables follower mode.
|
||||
/// </summary>
|
||||
public class TrashMazeSwitchToTrafalgar : ControllerSwitchItem
|
||||
{
|
||||
[Header("Trash Maze - To Trafalgar Settings")]
|
||||
[Tooltip("Camera state to blend to (Gameplay camera)")]
|
||||
[SerializeField] private TrashMazeCameraState targetCameraState = TrashMazeCameraState.Gameplay;
|
||||
|
||||
protected override IEnumerator SwitchControllerSequence()
|
||||
{
|
||||
_isSwitching = true;
|
||||
|
||||
// Step 1: Get controllers
|
||||
var currentController = InputManager.Instance.GetActiveController();
|
||||
var targetController = InputManager.Instance.GetController("trafalgar");
|
||||
|
||||
if (currentController == null || targetController == null)
|
||||
{
|
||||
Debug.LogError($"[TrashMazeSwitchToTrafalgar] Failed to get controllers!");
|
||||
_isSwitching = false;
|
||||
yield break;
|
||||
}
|
||||
|
||||
GameObject currentGameObject = (currentController as MonoBehaviour)?.gameObject;
|
||||
GameObject targetGameObject = (targetController as MonoBehaviour)?.gameObject;
|
||||
|
||||
Logging.Debug($"[TrashMazeSwitchToTrafalgar] Switching from Pulver to {targetGameObject?.name}");
|
||||
|
||||
// Step 2: Deactivate current controller (Pulver)
|
||||
DeactivateCurrentController(currentController, currentGameObject);
|
||||
|
||||
// Explicitly deactivate PulverController to ensure it stops receiving input
|
||||
if (currentGameObject != null)
|
||||
{
|
||||
var pulverController = currentGameObject.GetComponent<PulverController>();
|
||||
if (pulverController != null)
|
||||
{
|
||||
pulverController.DeactivateController();
|
||||
Logging.Debug("[TrashMazeSwitchToTrafalgar] Explicitly deactivated PulverController");
|
||||
}
|
||||
}
|
||||
|
||||
// Step 3: Start camera blend back to gameplay
|
||||
StartCameraBlend();
|
||||
|
||||
// Step 4: Wait for camera blend to complete
|
||||
yield return WaitForCameraBlend();
|
||||
|
||||
// Step 5: Unset Pulver as tracking target and set Trafalgar for gameplay camera
|
||||
SetTrafalgarAsTrackingTarget(targetGameObject);
|
||||
|
||||
// Step 6: Activate Pulver's follower mode (so it follows Trafalgar)
|
||||
if (currentGameObject != null)
|
||||
{
|
||||
var pulverFollower = currentGameObject.GetComponent<FollowerController>();
|
||||
if (pulverFollower != null)
|
||||
{
|
||||
pulverFollower.ActivateFollower();
|
||||
}
|
||||
}
|
||||
|
||||
// Step 7: Activate Trafalgar controller
|
||||
if (targetController is BasePlayerMovementController targetPlayerController)
|
||||
{
|
||||
targetPlayerController.ActivateController();
|
||||
}
|
||||
|
||||
// Step 8: Switch InputManager to Trafalgar controller
|
||||
bool switchSuccess = InputManager.Instance.SwitchToController("trafalgar");
|
||||
|
||||
if (switchSuccess)
|
||||
{
|
||||
Logging.Debug($"[TrashMazeSwitchToTrafalgar] Successfully switched to Trafalgar controller");
|
||||
OnCharacterSwitch.Invoke();
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError($"[TrashMazeSwitchToTrafalgar] Failed to switch to Trafalgar controller");
|
||||
}
|
||||
|
||||
// Step 8: Mark as used if one-time use
|
||||
if (isOneTime)
|
||||
{
|
||||
DisableVisual();
|
||||
}
|
||||
|
||||
_isSwitching = false;
|
||||
}
|
||||
|
||||
private void StartCameraBlend()
|
||||
{
|
||||
if (TrashMazeCameraController.Instance != null)
|
||||
{
|
||||
Logging.Debug($"[TrashMazeSwitchToTrafalgar] Starting camera blend to {targetCameraState}");
|
||||
|
||||
if (targetCameraState == TrashMazeCameraState.Gameplay)
|
||||
{
|
||||
TrashMazeCameraController.Instance.SwitchToGameplay();
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Warning($"[TrashMazeSwitchToTrafalgar] Unexpected camera state: {targetCameraState}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("[TrashMazeSwitchToTrafalgar] TrashMazeCameraController instance not found!");
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator WaitForCameraBlend()
|
||||
{
|
||||
CinemachineBrain brain = Camera.main?.GetComponent<CinemachineBrain>();
|
||||
|
||||
if (brain != null)
|
||||
{
|
||||
// Wait until blend is complete
|
||||
while (brain.IsBlending)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
|
||||
Logging.Debug("[TrashMazeSwitchToTrafalgar] Camera blend completed");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fallback: wait a brief moment
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetTrafalgarAsTrackingTarget(GameObject trafalgarGameObject)
|
||||
{
|
||||
if (TrashMazeCameraController.Instance != null)
|
||||
{
|
||||
// Clear maze camera tracking target
|
||||
var mazeCamera = TrashMazeCameraController.Instance.GetMazeCamera();
|
||||
if (mazeCamera != null)
|
||||
{
|
||||
mazeCamera.Follow = null;
|
||||
mazeCamera.LookAt = null;
|
||||
Logging.Debug($"[TrashMazeSwitchToTrafalgar] Cleared Pulver as tracking target from maze camera");
|
||||
}
|
||||
|
||||
// Set Trafalgar as tracking target for gameplay camera
|
||||
if (trafalgarGameObject != null)
|
||||
{
|
||||
var gameplayCamera = TrashMazeCameraController.Instance.GetGameplayCamera();
|
||||
if (gameplayCamera != null)
|
||||
{
|
||||
gameplayCamera.Follow = trafalgarGameObject.transform;
|
||||
gameplayCamera.LookAt = trafalgarGameObject.transform;
|
||||
Logging.Debug($"[TrashMazeSwitchToTrafalgar] Set Trafalgar as tracking target for gameplay camera");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnValidate()
|
||||
{
|
||||
name = "TrashMazeSwitch_ToTrafalgar";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 60a323cce5144fe9bae5dd3b313315a1
|
||||
timeCreated: 1766149639
|
||||
Reference in New Issue
Block a user