Generic MVP working
This commit is contained in:
committed by
Michal Pikulski
parent
11833ba503
commit
ab579e2d21
@@ -70,6 +70,11 @@ MonoBehaviour:
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: c56b7c4096b59584c93f2cfa79230643
|
||||
m_Address: Settings/AirplaneSettings
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
m_ReadOnly: 0
|
||||
m_Settings: {fileID: 11400000, guid: 11da9bb90d9dd5848b4f7629415a6937, type: 2}
|
||||
m_SchemaSet:
|
||||
|
||||
@@ -3,6 +3,7 @@ using UnityEditor;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Core.Settings;
|
||||
using Minigames.Airplane.Settings;
|
||||
|
||||
namespace AppleHills.Core.Settings.Editor
|
||||
{
|
||||
@@ -10,7 +11,8 @@ namespace AppleHills.Core.Settings.Editor
|
||||
{
|
||||
private Vector2 scrollPosition;
|
||||
private List<BaseSettings> allSettings = new List<BaseSettings>();
|
||||
private string[] tabNames = new string[] { "Player & Follower", "Interaction & Items", "Diving Minigame", "Card System", "Card Sorting", "Bird Pooper", "Statue Dressup", "Fort Fight" };
|
||||
private string[] tabNames = new string[] { "Player & Follower", "Interaction & Items", "Diving Minigame",
|
||||
"Card System", "Card Sorting", "Bird Pooper", "Statue Dressup", "Fort Fight", "Airplane" };
|
||||
private int selectedTab = 0;
|
||||
private Dictionary<string, SerializedObject> serializedSettingsObjects = new Dictionary<string, SerializedObject>();
|
||||
private GUIStyle headerStyle;
|
||||
@@ -53,6 +55,7 @@ namespace AppleHills.Core.Settings.Editor
|
||||
CreateSettingsIfMissing<BirdPooperSettings>("BirdPooperSettings");
|
||||
CreateSettingsIfMissing<StatueDressupSettings>("StatueDressupSettings");
|
||||
CreateSettingsIfMissing<Minigames.FortFight.Core.FortFightSettings>("FortFightSettings");
|
||||
CreateSettingsIfMissing<AirplaneSettings>("AirplaneSettings");
|
||||
}
|
||||
|
||||
private void CreateSettingsIfMissing<T>(string fileName) where T : BaseSettings
|
||||
@@ -134,6 +137,9 @@ namespace AppleHills.Core.Settings.Editor
|
||||
case 7: // Fort Fight
|
||||
DrawSettingsEditor<Minigames.FortFight.Core.FortFightSettings>();
|
||||
break;
|
||||
case 8: // Airplane
|
||||
DrawSettingsEditor<Minigames.Airplane.Settings.AirplaneSettings>();
|
||||
break;
|
||||
}
|
||||
|
||||
EditorGUILayout.EndScrollView();
|
||||
|
||||
@@ -4875,10 +4875,18 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: aa30fcfc16ed44d59edd73fd0224d03c, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: AppleHillsScripts::Minigames.FortFight.Core.CameraController
|
||||
wideViewCamera: {fileID: 858149304}
|
||||
playerOneCamera: {fileID: 846792105}
|
||||
playerTwoCamera: {fileID: 630420675}
|
||||
projectileCamera: {fileID: 1592155790}
|
||||
cameraMappings:
|
||||
- state: 0
|
||||
camera: {fileID: 858149304}
|
||||
- state: 1
|
||||
camera: {fileID: 846792105}
|
||||
- state: 2
|
||||
camera: {fileID: 630420675}
|
||||
- state: 3
|
||||
camera: {fileID: 1592155790}
|
||||
inactivePriority: 10
|
||||
activePriority: 20
|
||||
showDebugLogs: 0
|
||||
--- !u!4 &1674657453
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -5442,7 +5450,7 @@ Transform:
|
||||
m_GameObject: {fileID: 1810521056}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: -10}
|
||||
m_LocalPosition: {x: 14.3, y: -2, z: -10}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Core;
|
||||
using Core.Lifecycle;
|
||||
using Unity.Cinemachine;
|
||||
@@ -7,15 +8,40 @@ using UnityEngine;
|
||||
|
||||
namespace Common.Camera
|
||||
{
|
||||
/// <summary>
|
||||
/// Serializable mapping between a camera state and its Cinemachine camera.
|
||||
/// Used to assign cameras in the Inspector for each enum state.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class CameraStateMapping<TState> where TState : Enum
|
||||
{
|
||||
[Tooltip("The state this camera represents")]
|
||||
public TState state;
|
||||
|
||||
[Tooltip("The Cinemachine camera for this state")]
|
||||
public CinemachineCamera camera;
|
||||
|
||||
public CameraStateMapping(TState state)
|
||||
{
|
||||
this.state = state;
|
||||
this.camera = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generic state-based camera controller using Cinemachine.
|
||||
/// Manages camera transitions by setting priorities on virtual cameras.
|
||||
/// Type parameter TState must be an enum representing camera states.
|
||||
/// </summary>
|
||||
///
|
||||
public abstract class CameraStateManager<TState> : ManagedBehaviour where TState : Enum
|
||||
{
|
||||
#region Configuration
|
||||
|
||||
[Header("Camera Mappings")]
|
||||
[Tooltip("Assign cameras for each state - list auto-populates from enum")]
|
||||
[SerializeField] protected List<CameraStateMapping<TState>> cameraMappings = new List<CameraStateMapping<TState>>();
|
||||
|
||||
[Header("Camera Priority Settings")]
|
||||
[Tooltip("Priority for inactive cameras")]
|
||||
[SerializeField] protected int inactivePriority = 10;
|
||||
@@ -47,11 +73,66 @@ namespace Common.Camera
|
||||
|
||||
#endregion
|
||||
|
||||
#region Lifecycle
|
||||
|
||||
/// <summary>
|
||||
/// Initialize camera mappings and validate them.
|
||||
/// Subclasses should call base.OnManagedAwake() to get automatic initialization.
|
||||
/// If custom initialization is needed, override without calling base.
|
||||
/// </summary>
|
||||
internal override void OnManagedAwake()
|
||||
{
|
||||
base.OnManagedAwake();
|
||||
|
||||
// Initialize cameras from Inspector mappings
|
||||
InitializeCameraMap();
|
||||
|
||||
// Validate all cameras are assigned
|
||||
ValidateCameras();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Initialization
|
||||
|
||||
/// <summary>
|
||||
/// Register a camera for a specific state.
|
||||
/// Call this in subclass OnManagedAwake to set up the camera map.
|
||||
/// Initialize camera mappings from Inspector-assigned list.
|
||||
/// Call this in OnManagedAwake - no need to manually register cameras!
|
||||
/// This is the preferred method for new implementations.
|
||||
/// </summary>
|
||||
protected void InitializeCameraMap()
|
||||
{
|
||||
_cameraMap.Clear();
|
||||
|
||||
// Build dictionary from serialized mappings
|
||||
foreach (var mapping in cameraMappings)
|
||||
{
|
||||
if (mapping.camera == null)
|
||||
{
|
||||
Logging.Warning($"[{GetType().Name}] No camera assigned for state {mapping.state}");
|
||||
continue;
|
||||
}
|
||||
|
||||
_cameraMap[mapping.state] = mapping.camera;
|
||||
mapping.camera.Priority.Value = inactivePriority;
|
||||
|
||||
if (showDebugLogs)
|
||||
Logging.Debug($"[{GetType().Name}] Registered camera '{mapping.camera.gameObject.name}' for state {mapping.state}");
|
||||
}
|
||||
|
||||
_isInitialized = true;
|
||||
|
||||
if (_cameraMap.Count == 0)
|
||||
{
|
||||
Logging.Warning($"[{GetType().Name}] No cameras registered!");
|
||||
}
|
||||
|
||||
if (showDebugLogs) Logging.Debug($"[{GetType().Name}] Initialized with {_cameraMap.Count} cameras");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DEPRECATED: Use InitializeCameraMap() instead for cleaner code.
|
||||
/// Kept for backward compatibility with existing implementations.
|
||||
/// </summary>
|
||||
protected void RegisterCamera(TState state, CinemachineCamera pCamera)
|
||||
{
|
||||
@@ -67,16 +148,14 @@ namespace Common.Camera
|
||||
}
|
||||
|
||||
_cameraMap[state] = pCamera;
|
||||
|
||||
// Set all cameras to inactive priority initially
|
||||
pCamera.Priority.Value = inactivePriority;
|
||||
|
||||
if (showDebugLogs) Logging.Debug($"[{GetType().Name}] Registered camera '{pCamera.gameObject.name}' for state {state}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finalize initialization after all cameras are registered.
|
||||
/// Call this at the end of subclass OnManagedAwake.
|
||||
/// DEPRECATED: Use InitializeCameraMap() instead.
|
||||
/// Kept for backward compatibility with existing implementations.
|
||||
/// </summary>
|
||||
protected void FinalizeInitialization()
|
||||
{
|
||||
@@ -155,15 +234,66 @@ namespace Common.Camera
|
||||
#region Validation
|
||||
|
||||
/// <summary>
|
||||
/// Validate that all required states have cameras registered.
|
||||
/// Subclasses can override to add custom validation.
|
||||
/// Validate that all enum states have cameras registered.
|
||||
/// Override to add custom validation (e.g., check for specific components).
|
||||
/// </summary>
|
||||
protected virtual void ValidateCameras()
|
||||
{
|
||||
// Subclasses should implement specific validation
|
||||
// Check that all enum values have cameras assigned
|
||||
foreach (TState state in Enum.GetValues(typeof(TState)))
|
||||
{
|
||||
if (!_cameraMap.ContainsKey(state))
|
||||
{
|
||||
Logging.Warning($"[{GetType().Name}] No camera assigned for state {state}");
|
||||
}
|
||||
else if (_cameraMap[state] == null)
|
||||
{
|
||||
Logging.Error($"[{GetType().Name}] Camera for state {state} is null!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Editor Support
|
||||
|
||||
#if UNITY_EDITOR
|
||||
/// <summary>
|
||||
/// Auto-populate camera mappings list with all enum values.
|
||||
/// Called automatically in the Editor when the component is added or values change.
|
||||
/// </summary>
|
||||
protected virtual void OnValidate()
|
||||
{
|
||||
// Get all enum values
|
||||
TState[] allStates = (TState[])Enum.GetValues(typeof(TState));
|
||||
|
||||
// Add missing states to the list
|
||||
foreach (TState state in allStates)
|
||||
{
|
||||
bool exists = cameraMappings.Any(m => EqualityComparer<TState>.Default.Equals(m.state, state));
|
||||
if (!exists)
|
||||
{
|
||||
cameraMappings.Add(new CameraStateMapping<TState>(state));
|
||||
}
|
||||
}
|
||||
|
||||
// Remove mappings for states that no longer exist in the enum
|
||||
cameraMappings.RemoveAll(m => !System.Array.Exists(allStates, s => EqualityComparer<TState>.Default.Equals(s, m.state)));
|
||||
|
||||
// Sort by enum order for cleaner Inspector display
|
||||
cameraMappings = cameraMappings.OrderBy(m => (int)(object)m.state).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize list when component is first added
|
||||
/// </summary>
|
||||
protected virtual void Reset()
|
||||
{
|
||||
OnValidate();
|
||||
}
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -68,12 +68,17 @@ namespace Common.Visual
|
||||
#region Public API - Visibility
|
||||
|
||||
/// <summary>
|
||||
/// Show the trajectory preview line
|
||||
/// Show the trajectory preview line.
|
||||
/// Clears any existing trajectory data so nothing displays until UpdateTrajectory is called.
|
||||
/// </summary>
|
||||
public void Show()
|
||||
{
|
||||
if (_lineRenderer != null)
|
||||
{
|
||||
// Clear old trajectory data
|
||||
_lineRenderer.positionCount = 0;
|
||||
|
||||
// Enable the line renderer
|
||||
_lineRenderer.enabled = true;
|
||||
}
|
||||
}
|
||||
@@ -106,6 +111,21 @@ namespace Common.Visual
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Force hide the trajectory immediately, clearing any lock state.
|
||||
/// Use this when transitioning turns or resetting the slingshot.
|
||||
/// </summary>
|
||||
public void ForceHide()
|
||||
{
|
||||
_isLocked = false;
|
||||
_lockTimer = 0f;
|
||||
|
||||
if (_lineRenderer != null)
|
||||
{
|
||||
_lineRenderer.enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public API - Update Trajectory (Multiple Overloads)
|
||||
|
||||
@@ -20,27 +20,12 @@ namespace Minigames.Airplane.Core
|
||||
|
||||
#endregion
|
||||
|
||||
#region Inspector References
|
||||
|
||||
[Header("Cinemachine Cameras")]
|
||||
[Tooltip("Camera for intro sequence")]
|
||||
[SerializeField] private CinemachineCamera introCamera;
|
||||
|
||||
[Tooltip("Camera for showing the next person")]
|
||||
[SerializeField] private CinemachineCamera nextPersonCamera;
|
||||
|
||||
[Tooltip("Camera for aiming view")]
|
||||
[SerializeField] private CinemachineCamera aimingCamera;
|
||||
|
||||
[Tooltip("Camera that follows the airplane (should have CinemachineFollow)")]
|
||||
[SerializeField] private CinemachineCamera flightCamera;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Lifecycle
|
||||
|
||||
internal override void OnManagedAwake()
|
||||
{
|
||||
// Base class handles InitializeCameraMap() and ValidateCameras()
|
||||
base.OnManagedAwake();
|
||||
|
||||
// Set singleton
|
||||
@@ -51,18 +36,6 @@ namespace Minigames.Airplane.Core
|
||||
return;
|
||||
}
|
||||
_instance = this;
|
||||
|
||||
// Register cameras
|
||||
RegisterCamera(AirplaneCameraState.Intro, introCamera);
|
||||
RegisterCamera(AirplaneCameraState.NextPerson, nextPersonCamera);
|
||||
RegisterCamera(AirplaneCameraState.Aiming, aimingCamera);
|
||||
RegisterCamera(AirplaneCameraState.Flight, flightCamera);
|
||||
|
||||
// Finalize initialization
|
||||
FinalizeInitialization();
|
||||
|
||||
// Validate
|
||||
ValidateCameras();
|
||||
}
|
||||
|
||||
internal override void OnManagedDestroy()
|
||||
@@ -81,28 +54,13 @@ namespace Minigames.Airplane.Core
|
||||
|
||||
protected override void ValidateCameras()
|
||||
{
|
||||
if (introCamera == null)
|
||||
{
|
||||
Logging.Error("[AirplaneCameraManager] Intro camera not assigned!");
|
||||
}
|
||||
// Base class validates all enum states have cameras assigned
|
||||
base.ValidateCameras();
|
||||
|
||||
if (nextPersonCamera == null)
|
||||
// Additional validation: Check if flight camera has follow component
|
||||
var flightCamera = GetCamera(AirplaneCameraState.Flight);
|
||||
if (flightCamera != null)
|
||||
{
|
||||
Logging.Error("[AirplaneCameraManager] Next person camera not assigned!");
|
||||
}
|
||||
|
||||
if (aimingCamera == null)
|
||||
{
|
||||
Logging.Error("[AirplaneCameraManager] Aiming camera not assigned!");
|
||||
}
|
||||
|
||||
if (flightCamera == null)
|
||||
{
|
||||
Logging.Error("[AirplaneCameraManager] Flight camera not assigned!");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Verify flight camera has follow component
|
||||
var followComponent = flightCamera.GetComponent<CinemachineFollow>();
|
||||
if (followComponent == null)
|
||||
{
|
||||
@@ -120,6 +78,7 @@ namespace Minigames.Airplane.Core
|
||||
/// </summary>
|
||||
public void StartFollowingAirplane(Transform airplaneTransform)
|
||||
{
|
||||
var flightCamera = GetCamera(AirplaneCameraState.Flight);
|
||||
if (flightCamera == null)
|
||||
{
|
||||
Logging.Warning("[AirplaneCameraManager] Cannot follow airplane - flight camera not assigned!");
|
||||
@@ -146,6 +105,7 @@ namespace Minigames.Airplane.Core
|
||||
/// </summary>
|
||||
public void StopFollowingAirplane()
|
||||
{
|
||||
var flightCamera = GetCamera(AirplaneCameraState.Flight);
|
||||
if (flightCamera == null) return;
|
||||
|
||||
// Clear the follow target
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using Core;
|
||||
using Core.Lifecycle;
|
||||
using Common.Camera;
|
||||
using Core;
|
||||
using Minigames.FortFight.Data;
|
||||
using Unity.Cinemachine;
|
||||
using UnityEngine;
|
||||
@@ -8,11 +8,10 @@ namespace Minigames.FortFight.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Manages camera states and transitions for the Fort Fight minigame.
|
||||
/// Extends CameraStateManager to use the common state-based camera system.
|
||||
/// Subscribes to turn events and switches camera views accordingly.
|
||||
/// Uses Cinemachine for smooth camera blending.
|
||||
/// Singleton pattern for easy access.
|
||||
/// </summary>
|
||||
public class CameraController : ManagedBehaviour
|
||||
public class CameraController : CameraStateManager<FortFightCameraState>
|
||||
{
|
||||
#region Singleton
|
||||
|
||||
@@ -31,41 +30,15 @@ namespace Minigames.FortFight.Core
|
||||
|
||||
#endregion
|
||||
|
||||
#region Inspector References
|
||||
|
||||
[Header("Cinemachine Cameras")]
|
||||
[Tooltip("Virtual camera showing wide battlefield view (both forts)")]
|
||||
[SerializeField] private CinemachineCamera wideViewCamera;
|
||||
|
||||
[Tooltip("Player One's dedicated camera (position this in the scene for Player 1's view)")]
|
||||
[SerializeField] private CinemachineCamera playerOneCamera;
|
||||
|
||||
[Tooltip("Player Two's dedicated camera (position this in the scene for Player 2's view)")]
|
||||
[SerializeField] private CinemachineCamera playerTwoCamera;
|
||||
|
||||
[Tooltip("Camera that follows projectiles in flight (should have CinemachineFollow component)")]
|
||||
[SerializeField] private CinemachineCamera projectileCamera;
|
||||
|
||||
// Note: TurnManager accessed via singleton
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
public CinemachineCamera WideViewCamera => wideViewCamera;
|
||||
public CinemachineCamera PlayerOneCamera => playerOneCamera;
|
||||
public CinemachineCamera PlayerTwoCamera => playerTwoCamera;
|
||||
public CinemachineCamera ProjectileCamera => projectileCamera;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Lifecycle
|
||||
|
||||
internal override void OnManagedAwake()
|
||||
{
|
||||
// Base class handles InitializeCameraMap() and ValidateCameras()
|
||||
base.OnManagedAwake();
|
||||
|
||||
// Register singleton
|
||||
// Set singleton
|
||||
if (_instance != null && _instance != this)
|
||||
{
|
||||
Logging.Warning("[CameraController] Multiple instances detected! Destroying duplicate.");
|
||||
@@ -73,28 +46,6 @@ namespace Minigames.FortFight.Core
|
||||
return;
|
||||
}
|
||||
_instance = this;
|
||||
|
||||
// Validate references
|
||||
if (wideViewCamera == null)
|
||||
{
|
||||
Logging.Error("[CameraController] Wide view camera not assigned!");
|
||||
}
|
||||
|
||||
if (playerOneCamera == null)
|
||||
{
|
||||
Logging.Error("[CameraController] Player One camera not assigned!");
|
||||
}
|
||||
|
||||
if (playerTwoCamera == null)
|
||||
{
|
||||
Logging.Error("[CameraController] Player Two camera not assigned!");
|
||||
}
|
||||
|
||||
if (projectileCamera == null)
|
||||
{
|
||||
Logging.Warning("[CameraController] Projectile camera not assigned - projectiles won't be followed!");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal override void OnManagedStart()
|
||||
@@ -136,75 +87,55 @@ namespace Minigames.FortFight.Core
|
||||
#region Event Handlers
|
||||
|
||||
/// <summary>
|
||||
/// Called when a player's turn starts - activate their dedicated camera
|
||||
/// Called when a player's turn starts - switch to appropriate camera state
|
||||
/// </summary>
|
||||
private void HandleTurnStarted(PlayerData player, TurnState turnState)
|
||||
{
|
||||
Logging.Debug($"[CameraController] Turn started for {player.PlayerName} (Index: {player.PlayerIndex}, State: {turnState})");
|
||||
if (showDebugLogs)
|
||||
Logging.Debug($"[CameraController] Turn started for {player.PlayerName} (Index: {player.PlayerIndex}, State: {turnState})");
|
||||
|
||||
// If transitioning, show wide view
|
||||
if (turnState == TurnState.TransitioningTurn)
|
||||
{
|
||||
ActivateCamera(wideViewCamera);
|
||||
SwitchToState(FortFightCameraState.WideView);
|
||||
return;
|
||||
}
|
||||
|
||||
// Activate the appropriate player camera based on player index
|
||||
// Switch to appropriate player camera based on index
|
||||
if (player.PlayerIndex == 0)
|
||||
{
|
||||
// Player One's turn
|
||||
ActivateCamera(playerOneCamera);
|
||||
SwitchToState(FortFightCameraState.PlayerOne);
|
||||
}
|
||||
else if (player.PlayerIndex == 1)
|
||||
{
|
||||
// Player Two's turn
|
||||
ActivateCamera(playerTwoCamera);
|
||||
SwitchToState(FortFightCameraState.PlayerTwo);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Warning($"[CameraController] Unknown player index: {player.PlayerIndex}, defaulting to wide view");
|
||||
ActivateCamera(wideViewCamera);
|
||||
SwitchToState(FortFightCameraState.WideView);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when a player's turn ends - camera switches handled by turn state changes
|
||||
/// Called when a player's turn ends
|
||||
/// </summary>
|
||||
private void HandleTurnEnded(PlayerData player)
|
||||
{
|
||||
Logging.Debug($"[CameraController] Turn ended for {player.PlayerName}");
|
||||
if (showDebugLogs) Logging.Debug($"[CameraController] Turn ended for {player.PlayerName}");
|
||||
// Camera switching happens via OnTurnStarted when state changes to TransitioningTurn
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Activate a specific camera by setting its priority highest
|
||||
/// </summary>
|
||||
private void ActivateCamera(CinemachineCamera camera)
|
||||
{
|
||||
if (camera == null) return;
|
||||
|
||||
// Set all cameras to low priority
|
||||
if (wideViewCamera != null) wideViewCamera.Priority.Value = 10;
|
||||
if (playerOneCamera != null) playerOneCamera.Priority.Value = 10;
|
||||
if (playerTwoCamera != null) playerTwoCamera.Priority.Value = 10;
|
||||
if (projectileCamera != null) projectileCamera.Priority.Value = 10;
|
||||
|
||||
// Set target camera to high priority
|
||||
camera.Priority.Value = 20;
|
||||
|
||||
Logging.Debug($"[CameraController] Activated camera: {camera.gameObject.name}");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Projectile Tracking
|
||||
|
||||
/// <summary>
|
||||
/// Start following a projectile with the projectile camera.
|
||||
/// Called when a projectile is launched.
|
||||
/// Start following a projectile with the projectile camera
|
||||
/// </summary>
|
||||
public void StartFollowingProjectile(Transform projectileTransform)
|
||||
{
|
||||
var projectileCamera = GetCamera(FortFightCameraState.Projectile);
|
||||
if (projectileCamera == null)
|
||||
{
|
||||
Logging.Warning("[CameraController] Cannot follow projectile - projectile camera not assigned!");
|
||||
@@ -217,38 +148,32 @@ namespace Minigames.FortFight.Core
|
||||
return;
|
||||
}
|
||||
|
||||
// Verify CinemachineFollow component exists (optional check)
|
||||
var followComponent = projectileCamera.GetComponent<CinemachineFollow>();
|
||||
if (followComponent == null)
|
||||
{
|
||||
Logging.Error("[CameraController] Projectile camera missing CinemachineFollow component!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the follow target on the CinemachineCamera's Target property
|
||||
// Set the follow target
|
||||
projectileCamera.Target.TrackingTarget = projectileTransform;
|
||||
|
||||
// Activate the projectile camera
|
||||
ActivateCamera(projectileCamera);
|
||||
// Switch to projectile camera
|
||||
SwitchToState(FortFightCameraState.Projectile);
|
||||
|
||||
Logging.Debug($"[CameraController] Now following projectile: {projectileTransform.gameObject.name}");
|
||||
if (showDebugLogs)
|
||||
Logging.Debug($"[CameraController] Now following projectile: {projectileTransform.gameObject.name}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stop following the projectile and return to wide view.
|
||||
/// Called when projectile has settled.
|
||||
/// Stop following the projectile and return to wide view
|
||||
/// </summary>
|
||||
public void StopFollowingProjectile()
|
||||
{
|
||||
var projectileCamera = GetCamera(FortFightCameraState.Projectile);
|
||||
if (projectileCamera == null) return;
|
||||
|
||||
// Clear the follow target on the CinemachineCamera's Target property
|
||||
// Clear the follow target
|
||||
projectileCamera.Target.TrackingTarget = null;
|
||||
|
||||
// Return to wide view
|
||||
ActivateCamera(wideViewCamera);
|
||||
SwitchToState(FortFightCameraState.WideView);
|
||||
|
||||
Logging.Debug("[CameraController] Stopped following projectile, returned to wide view");
|
||||
if (showDebugLogs)
|
||||
Logging.Debug("[CameraController] Stopped following projectile, returned to wide view");
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -256,11 +181,11 @@ namespace Minigames.FortFight.Core
|
||||
#region Public API
|
||||
|
||||
/// <summary>
|
||||
/// Manually switch to wide view (useful for game start/end)
|
||||
/// Manually switch to wide view
|
||||
/// </summary>
|
||||
public void ShowWideView()
|
||||
{
|
||||
ActivateCamera(wideViewCamera);
|
||||
SwitchToState(FortFightCameraState.WideView);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -270,23 +195,35 @@ namespace Minigames.FortFight.Core
|
||||
{
|
||||
if (playerIndex == 0)
|
||||
{
|
||||
ActivateCamera(playerOneCamera);
|
||||
SwitchToState(FortFightCameraState.PlayerOne);
|
||||
}
|
||||
else if (playerIndex == 1)
|
||||
{
|
||||
ActivateCamera(playerTwoCamera);
|
||||
SwitchToState(FortFightCameraState.PlayerTwo);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Editor Helpers
|
||||
#region Validation
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnValidate()
|
||||
protected override void ValidateCameras()
|
||||
{
|
||||
// Base class validates all enum states have cameras assigned
|
||||
base.ValidateCameras();
|
||||
|
||||
// Additional validation: Check if projectile camera has follow component
|
||||
var projectileCamera = GetCamera(FortFightCameraState.Projectile);
|
||||
if (projectileCamera != null)
|
||||
{
|
||||
var followComponent = projectileCamera.GetComponent<CinemachineFollow>();
|
||||
if (followComponent == null)
|
||||
{
|
||||
Logging.Warning("[CameraController] Projectile camera missing CinemachineFollow component!");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -95,6 +95,17 @@ namespace Minigames.FortFight.Core
|
||||
|
||||
#region Override Methods
|
||||
|
||||
public override void Enable()
|
||||
{
|
||||
// Clear any locked trajectory from previous turn
|
||||
if (trajectoryPreview != null)
|
||||
{
|
||||
trajectoryPreview.ForceHide();
|
||||
}
|
||||
|
||||
base.Enable();
|
||||
}
|
||||
|
||||
protected override void StartDrag(Vector2 worldPosition)
|
||||
{
|
||||
// Check ammo before starting drag
|
||||
|
||||
@@ -61,5 +61,15 @@
|
||||
Medium, // Moderate deviations, moderate thinking
|
||||
Hard // Minimal deviations, faster thinking
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Camera states for Fort Fight minigame
|
||||
/// </summary>
|
||||
public enum FortFightCameraState
|
||||
{
|
||||
WideView, // Shows entire battlefield
|
||||
PlayerOne, // Player 1's view
|
||||
PlayerTwo, // Player 2's view
|
||||
Projectile // Follows projectile in flight
|
||||
}
|
||||
}
|
||||
|
||||
31
Assets/Settings/AirplaneSettings.asset
Normal file
31
Assets/Settings/AirplaneSettings.asset
Normal file
@@ -0,0 +1,31 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 1c277e2fec3d42e2b3b0bed1b8a33beb, type: 3}
|
||||
m_Name: AirplaneSettings
|
||||
m_EditorClassIdentifier: AppleHillsScripts::Minigames.Airplane.Settings.AirplaneSettings
|
||||
slingshotSettings:
|
||||
maxDragDistance: 5
|
||||
baseLaunchForce: 20
|
||||
minForceMultiplier: 0.1
|
||||
maxForceMultiplier: 1
|
||||
trajectoryPoints: 20
|
||||
trajectoryTimeStep: 0.1
|
||||
trajectoryLockDuration: 0
|
||||
autoRegisterInput: 1
|
||||
airplaneMass: 1
|
||||
maxFlightTime: 10
|
||||
cameraFollowSmoothing: 5
|
||||
flightCameraZoom: 5
|
||||
introDuration: 1
|
||||
personIntroDuration: 1
|
||||
evaluationDuration: 1
|
||||
showDebugLogs: 0
|
||||
8
Assets/Settings/AirplaneSettings.asset.meta
Normal file
8
Assets/Settings/AirplaneSettings.asset.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c56b7c4096b59584c93f2cfa79230643
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user