Refactored trajectory component
This commit is contained in:
@@ -44,12 +44,6 @@ namespace Minigames.Airplane.Core
|
||||
[Tooltip("Gravity multiplier for arc calculation")]
|
||||
[SerializeField] private float gravity = 9.81f;
|
||||
|
||||
[Tooltip("Mass of the airplane")]
|
||||
[SerializeField] private float mass = 1f;
|
||||
|
||||
[Tooltip("Maximum flight time before timeout (seconds)")]
|
||||
[SerializeField] private float maxFlightTime = 10f;
|
||||
|
||||
[Header("Visual")]
|
||||
[Tooltip("Should airplane rotate to face velocity direction?")]
|
||||
[SerializeField] private bool rotateToVelocity = true;
|
||||
@@ -68,6 +62,10 @@ namespace Minigames.Airplane.Core
|
||||
private float flightTimer = 0f;
|
||||
private string lastHitTarget = null;
|
||||
|
||||
// Runtime values loaded from settings
|
||||
private float mass;
|
||||
private float maxFlightTime;
|
||||
|
||||
public bool IsFlying => isFlying;
|
||||
public Vector2 CurrentVelocity => currentVelocity;
|
||||
public string LastHitTarget => lastHitTarget;
|
||||
@@ -80,6 +78,20 @@ namespace Minigames.Airplane.Core
|
||||
{
|
||||
base.OnManagedAwake();
|
||||
|
||||
// Load settings
|
||||
var settings = GameManager.GetSettingsObject<AppleHills.Core.Settings.IAirplaneSettings>();
|
||||
if (settings != null)
|
||||
{
|
||||
mass = settings.AirplaneMass;
|
||||
maxFlightTime = settings.MaxFlightTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Warning("[AirplaneController] AirplaneSettings not found, using defaults!");
|
||||
mass = 1f;
|
||||
maxFlightTime = 10f;
|
||||
}
|
||||
|
||||
// Cache components
|
||||
rb2D = GetComponent<Rigidbody2D>();
|
||||
airplaneCollider = GetComponent<Collider2D>();
|
||||
|
||||
@@ -36,6 +36,20 @@ namespace Minigames.Airplane.Core
|
||||
return airplanePrefab;
|
||||
}
|
||||
|
||||
protected override float GetProjectileMass()
|
||||
{
|
||||
var settings = GameManager.GetSettingsObject<IAirplaneSettings>();
|
||||
if (settings == null)
|
||||
{
|
||||
if (showDebugLogs)
|
||||
Logging.Warning("[AirplaneLaunchController] AirplaneSettings not found!");
|
||||
return 1f; // Default fallback
|
||||
}
|
||||
|
||||
// Read from AirplaneSettings - same mass that AirplaneController uses
|
||||
return settings.AirplaneMass;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Inspector Properties
|
||||
@@ -84,92 +98,8 @@ namespace Minigames.Airplane.Core
|
||||
|
||||
#region Visual Feedback
|
||||
|
||||
protected override void ShowPreview()
|
||||
{
|
||||
// Show anchor visual
|
||||
if (anchorVisual != null)
|
||||
{
|
||||
anchorVisual.SetActive(true);
|
||||
}
|
||||
|
||||
// Show trajectory line (will be updated during drag)
|
||||
if (trajectoryLine != null)
|
||||
{
|
||||
trajectoryLine.enabled = false; // Only show during drag
|
||||
}
|
||||
|
||||
if (showDebugLogs) Logging.Debug("[AirplaneLaunchController] Preview shown");
|
||||
}
|
||||
|
||||
protected override void HidePreview()
|
||||
{
|
||||
// Hide anchor visual
|
||||
if (anchorVisual != null)
|
||||
{
|
||||
anchorVisual.SetActive(false);
|
||||
}
|
||||
|
||||
// Hide trajectory line
|
||||
if (trajectoryLine != null)
|
||||
{
|
||||
trajectoryLine.enabled = false;
|
||||
}
|
||||
|
||||
if (showDebugLogs) Logging.Debug("[AirplaneLaunchController] Preview hidden");
|
||||
}
|
||||
|
||||
protected override void UpdateVisuals(Vector2 currentPosition, Vector2 direction, float force, float dragDistance, float mass)
|
||||
{
|
||||
// Show trajectory line during drag
|
||||
if (trajectoryLine != null && trajectoryLine.enabled == false && dragDistance > 0.1f)
|
||||
{
|
||||
trajectoryLine.enabled = true;
|
||||
}
|
||||
|
||||
// Update trajectory preview
|
||||
if (trajectoryLine != null && trajectoryLine.enabled)
|
||||
{
|
||||
UpdateTrajectoryPreview(direction, force, mass);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the trajectory preview line
|
||||
/// </summary>
|
||||
private void UpdateTrajectoryPreview(Vector2 direction, float force, float mass)
|
||||
{
|
||||
if (trajectoryLine == null) return;
|
||||
|
||||
var config = Config;
|
||||
if (config == null) return;
|
||||
|
||||
if (mass <= 0f)
|
||||
{
|
||||
if (showDebugLogs) Logging.Warning("[AirplaneLaunchController] Cannot calculate trajectory with zero mass!");
|
||||
return;
|
||||
}
|
||||
|
||||
Vector2 startPos = launchAnchor.position;
|
||||
float initialSpeed = force / mass;
|
||||
Vector2 velocity = direction * initialSpeed;
|
||||
|
||||
// Get gravity from prefab's Rigidbody2D (Physics2D.gravity.magnitude * rb.gravityScale)
|
||||
float gravity = GetGravity();
|
||||
|
||||
trajectoryLine.positionCount = config.trajectoryPoints;
|
||||
|
||||
// Calculate trajectory points using config values
|
||||
for (int i = 0; i < config.trajectoryPoints; i++)
|
||||
{
|
||||
float time = i * config.trajectoryTimeStep;
|
||||
|
||||
// Calculate position at this time
|
||||
float x = startPos.x + velocity.x * time;
|
||||
float y = startPos.y + velocity.y * time - 0.5f * gravity * time * time;
|
||||
|
||||
trajectoryLine.SetPosition(i, new Vector3(x, y, 0));
|
||||
}
|
||||
}
|
||||
// Base class handles trajectory preview via TrajectoryPreview component
|
||||
// No custom visual feedback needed for airplane - using default implementation
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -126,21 +126,6 @@ namespace Minigames.FortFight.Core
|
||||
[Tooltip("Downward velocity when dropping (m/s)")]
|
||||
[SerializeField] private float ceilingFanDropSpeed = 20f;
|
||||
|
||||
[Header("Slingshot Settings")]
|
||||
[Tooltip("Base launch force multiplier - higher values = projectiles fly farther")]
|
||||
[SerializeField] private float baseLaunchForce = 20f;
|
||||
|
||||
[Tooltip("Minimum force multiplier (0-1, e.g. 0.1 = 10% of max force required to launch)")]
|
||||
[Range(0f, 1f)]
|
||||
[SerializeField] private float minForceMultiplier = 0.1f;
|
||||
|
||||
[Tooltip("Maximum force multiplier (0-1, e.g. 1.0 = 100% at max drag distance)")]
|
||||
[Range(0f, 2f)]
|
||||
[SerializeField] private float maxForceMultiplier = 1f;
|
||||
|
||||
[Tooltip("How long to keep trajectory visible after launching (seconds)")]
|
||||
[SerializeField] private float trajectoryLockDuration = 2f;
|
||||
|
||||
[Header("Physics Layers")]
|
||||
[Tooltip("Layer for fort blocks - projectiles will collide with these (Default: Layer 8 'FortBlock')")]
|
||||
[AppleHills.Core.Settings.Layer]
|
||||
@@ -180,11 +165,6 @@ namespace Minigames.FortFight.Core
|
||||
|
||||
public Color DamageColorTint => damageColorTint;
|
||||
|
||||
public float BaseLaunchForce => baseLaunchForce;
|
||||
public float MinForceMultiplier => minForceMultiplier;
|
||||
public float MaxForceMultiplier => maxForceMultiplier;
|
||||
public float TrajectoryLockDuration => trajectoryLockDuration;
|
||||
|
||||
public float VacuumSlideSpeed => vacuumSlideSpeed;
|
||||
public int VacuumDestroyBlockCount => vacuumDestroyBlockCount;
|
||||
public float VacuumBlockDamage => vacuumBlockDamage;
|
||||
|
||||
@@ -16,9 +16,7 @@ namespace Minigames.FortFight.Core
|
||||
{
|
||||
#region Inspector Properties
|
||||
|
||||
[Header("FortFight Specific")]
|
||||
[Tooltip("Trajectory preview component")]
|
||||
[SerializeField] private TrajectoryPreview trajectoryPreview;
|
||||
// Note: trajectoryPreview is inherited from DragLaunchController base class
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -86,28 +84,13 @@ namespace Minigames.FortFight.Core
|
||||
{
|
||||
base.OnManagedAwake();
|
||||
|
||||
// Base class handles launchAnchor (previously projectileSpawnPoint)
|
||||
|
||||
if (trajectoryPreview == null)
|
||||
{
|
||||
trajectoryPreview = GetComponent<TrajectoryPreview>();
|
||||
}
|
||||
// Base class handles launchAnchor and trajectoryPreview
|
||||
|
||||
// Set debug logging from developer settings
|
||||
showDebugLogs = CachedDevSettings?.SlingshotShowDebugLogs ?? false;
|
||||
}
|
||||
|
||||
internal override void OnManagedStart()
|
||||
{
|
||||
base.OnManagedStart();
|
||||
|
||||
// Hide trajectory by default
|
||||
if (trajectoryPreview != null)
|
||||
{
|
||||
trajectoryPreview.Hide();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Override Methods
|
||||
@@ -129,6 +112,19 @@ namespace Minigames.FortFight.Core
|
||||
LaunchProjectile(direction, force);
|
||||
}
|
||||
|
||||
protected override float GetProjectileMass()
|
||||
{
|
||||
if (_currentAmmo == null)
|
||||
{
|
||||
if (showDebugLogs)
|
||||
Logging.Warning("[SlingshotController] No ammo selected, cannot get mass!");
|
||||
return 1f; // Default fallback
|
||||
}
|
||||
|
||||
// Read from ProjectileConfig settings - same source as ProjectileBase.Initialize()
|
||||
return _currentAmmo.mass;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Projectile Management
|
||||
@@ -173,7 +169,7 @@ namespace Minigames.FortFight.Core
|
||||
// Lock trajectory to show the shot path
|
||||
if (trajectoryPreview != null)
|
||||
{
|
||||
float lockDuration = CachedSettings?.TrajectoryLockDuration ?? 2f;
|
||||
float lockDuration = Config?.trajectoryLockDuration ?? 2f;
|
||||
trajectoryPreview.LockTrajectory(lockDuration);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,153 +0,0 @@
|
||||
using Core;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Minigames.FortFight.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Displays trajectory prediction line for projectile launches.
|
||||
/// Shows dotted line preview of projectile arc.
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(LineRenderer))]
|
||||
public class TrajectoryPreview : MonoBehaviour
|
||||
{
|
||||
[Header("Trajectory Settings")]
|
||||
[Tooltip("Number of points to simulate (physics steps)")]
|
||||
[SerializeField] private int simulationSteps = 50;
|
||||
|
||||
[Header("Visual")]
|
||||
[Tooltip("Color of trajectory line")]
|
||||
[SerializeField] private Color lineColor = Color.yellow;
|
||||
|
||||
[Tooltip("Width of trajectory line")]
|
||||
[SerializeField] private float lineWidth = 0.1f;
|
||||
|
||||
private LineRenderer lineRenderer;
|
||||
private bool isLocked = false;
|
||||
private float lockTimer = 0f;
|
||||
private float lockDuration = 0f;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
lineRenderer = GetComponent<LineRenderer>();
|
||||
|
||||
// Configure line renderer
|
||||
if (lineRenderer != null)
|
||||
{
|
||||
lineRenderer.startWidth = lineWidth;
|
||||
lineRenderer.endWidth = lineWidth;
|
||||
lineRenderer.startColor = lineColor;
|
||||
lineRenderer.endColor = lineColor;
|
||||
lineRenderer.positionCount = simulationSteps;
|
||||
lineRenderer.enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (isLocked)
|
||||
{
|
||||
lockTimer += Time.deltaTime;
|
||||
if (lockTimer >= lockDuration)
|
||||
{
|
||||
isLocked = false;
|
||||
Hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Show the trajectory preview
|
||||
/// </summary>
|
||||
public void Show()
|
||||
{
|
||||
if (lineRenderer != null)
|
||||
{
|
||||
lineRenderer.enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hide the trajectory preview (unless locked)
|
||||
/// </summary>
|
||||
public void Hide()
|
||||
{
|
||||
// Don't hide if trajectory is locked
|
||||
if (isLocked)
|
||||
return;
|
||||
|
||||
if (lineRenderer != null)
|
||||
{
|
||||
lineRenderer.enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Lock the current trajectory display for a duration
|
||||
/// </summary>
|
||||
public void LockTrajectory(float duration)
|
||||
{
|
||||
isLocked = true;
|
||||
lockTimer = 0f;
|
||||
lockDuration = duration;
|
||||
|
||||
// Ensure line is visible
|
||||
if (lineRenderer != null)
|
||||
{
|
||||
lineRenderer.enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the trajectory preview with new parameters.
|
||||
/// Uses Physics.fixedDeltaTime for accurate simulation matching Unity's physics.
|
||||
/// </summary>
|
||||
/// <param name="startPosition">Starting position of trajectory</param>
|
||||
/// <param name="direction">Launch direction (normalized)</param>
|
||||
/// <param name="force">Launch force (impulse)</param>
|
||||
/// <param name="mass">Projectile mass</param>
|
||||
public void UpdateTrajectory(Vector2 startPosition, Vector2 direction, float force, float mass = 1f)
|
||||
{
|
||||
if (lineRenderer == null) return;
|
||||
|
||||
// Calculate initial velocity: impulse force F gives velocity v = F/m
|
||||
Vector2 startVelocity = (direction * force) / mass;
|
||||
|
||||
// Get gravity with projectile gravity scale from settings
|
||||
var settings = GameManager.GetSettingsObject<AppleHills.Core.Settings.IFortFightSettings>();
|
||||
float gravityScale = settings?.ProjectileGravityScale ?? 1f;
|
||||
Vector2 gravity = new Vector2(Physics2D.gravity.x, Physics2D.gravity.y) * gravityScale;
|
||||
|
||||
// Simulate trajectory using Unity's physics time step
|
||||
Vector3[] points = new Vector3[simulationSteps];
|
||||
Vector2 pos = startPosition;
|
||||
Vector2 vel = startVelocity;
|
||||
|
||||
for (int i = 0; i < simulationSteps; i++)
|
||||
{
|
||||
// Set current position
|
||||
points[i] = new Vector3(pos.x, pos.y, 0);
|
||||
|
||||
// Update velocity (gravity applied over fixedDeltaTime)
|
||||
vel = vel + gravity * Time.fixedDeltaTime;
|
||||
|
||||
// Update position (velocity applied over fixedDeltaTime)
|
||||
pos = pos + vel * Time.fixedDeltaTime;
|
||||
|
||||
// Optional: Stop if hits ground (y < threshold)
|
||||
if (pos.y < -10f)
|
||||
{
|
||||
// Fill remaining points at ground level
|
||||
for (int j = i + 1; j < simulationSteps; j++)
|
||||
{
|
||||
points[j] = new Vector3(pos.x, -10f, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
lineRenderer.positionCount = simulationSteps;
|
||||
lineRenderer.SetPositions(points);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b1e26667c6d4415f8dc51e4a58ba9479
|
||||
timeCreated: 1764682615
|
||||
Reference in New Issue
Block a user