Update LaserBeam.cs
This commit is contained in:
parent
f3d30841e3
commit
a681beec0e
@ -4,15 +4,11 @@ using System.Collections;
|
|||||||
[RequireComponent(typeof(LineRenderer))]
|
[RequireComponent(typeof(LineRenderer))]
|
||||||
public class LaserBeam : MonoBehaviour
|
public class LaserBeam : MonoBehaviour
|
||||||
{
|
{
|
||||||
[Header("Control")]
|
|
||||||
[Tooltip("If true, this beam will NOT run its own timers or intro; it only responds to the controller.")]
|
|
||||||
public bool externalControl = true;
|
|
||||||
|
|
||||||
[Header("Laser Settings")]
|
[Header("Laser Settings")]
|
||||||
public float maxDistance = 20f;
|
public float maxDistance = 20f;
|
||||||
public LayerMask collisionMask = ~0;
|
public LayerMask collisionMask = ~0;
|
||||||
public float chargeDuration = 3f; // used only if externalControl == false
|
public float chargeDuration = 3f;
|
||||||
public float fireDuration = 1f; // used only if externalControl == false
|
public float fireDuration = 1f;
|
||||||
|
|
||||||
[Header("Laser Appearance")]
|
[Header("Laser Appearance")]
|
||||||
public Color laserColor = Color.red;
|
public Color laserColor = Color.red;
|
||||||
@ -26,7 +22,7 @@ public class LaserBeam : MonoBehaviour
|
|||||||
public float hitRadius = 0.1f;
|
public float hitRadius = 0.1f;
|
||||||
public QueryTriggerInteraction queryTriggerMode = QueryTriggerInteraction.Collide;
|
public QueryTriggerInteraction queryTriggerMode = QueryTriggerInteraction.Collide;
|
||||||
|
|
||||||
[Header("Intro Show (ignored if externalControl)")]
|
[Header("Intro Show")]
|
||||||
public bool showIntro = true;
|
public bool showIntro = true;
|
||||||
public float initialShowDuration = 3f;
|
public float initialShowDuration = 3f;
|
||||||
public bool introIsDeadly = true;
|
public bool introIsDeadly = true;
|
||||||
@ -35,8 +31,8 @@ public class LaserBeam : MonoBehaviour
|
|||||||
public bool deflectFromBoxSides = true;
|
public bool deflectFromBoxSides = true;
|
||||||
public string boxTag = "Box";
|
public string boxTag = "Box";
|
||||||
public float outDistance = 12f;
|
public float outDistance = 12f;
|
||||||
public float sideExitPush = 0.02f;
|
public float sideExitPush = 0.02f; // will be lifted to >= hitRadius + epsilon at runtime
|
||||||
public float entryPush = 0.005f;
|
public float entryPush = 0.005f; // will be lifted to >= 0.25*hitRadius at runtime
|
||||||
|
|
||||||
[Header("Debug")]
|
[Header("Debug")]
|
||||||
public bool debugDraw = false;
|
public bool debugDraw = false;
|
||||||
@ -60,33 +56,22 @@ public class LaserBeam : MonoBehaviour
|
|||||||
private Collider _lastBox;
|
private Collider _lastBox;
|
||||||
private int _sideSign = 1;
|
private int _sideSign = 1;
|
||||||
|
|
||||||
|
// External control hook (set by controller if used)
|
||||||
|
public bool externalControl = true;
|
||||||
|
|
||||||
void Awake()
|
void Awake()
|
||||||
{
|
{
|
||||||
SetupLaserRenderer();
|
SetupLaserRenderer();
|
||||||
// Always start safe
|
|
||||||
currentPhase = LaserPhase.Idle;
|
|
||||||
hasTriggeredDeathThisBurst = false;
|
|
||||||
DisableLaser();
|
|
||||||
StopAllCoroutines();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Start()
|
void Start()
|
||||||
{
|
{
|
||||||
// Only self-run if not externally controlled
|
if (showIntro)
|
||||||
if (!externalControl && showIntro)
|
|
||||||
StartCoroutine(IntroShow());
|
StartCoroutine(IntroShow());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Update()
|
void Update()
|
||||||
{
|
{
|
||||||
if (externalControl)
|
|
||||||
{
|
|
||||||
// Passive: only draw debug line if visible
|
|
||||||
if (debugDraw) Debug.DrawLine(laserStart, laserEnd, Color.cyan);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Legacy self-FSM (optional use)
|
|
||||||
if (introRunning) return;
|
if (introRunning) return;
|
||||||
|
|
||||||
timer += Time.deltaTime;
|
timer += Time.deltaTime;
|
||||||
@ -131,18 +116,19 @@ public class LaserBeam : MonoBehaviour
|
|||||||
Debug.DrawLine(laserStart, laserEnd, Color.cyan);
|
Debug.DrawLine(laserStart, laserEnd, Color.cyan);
|
||||||
}
|
}
|
||||||
|
|
||||||
// LaserBeam.cs — replace SetLaserPhase with this version
|
|
||||||
public void SetLaserPhase(LaserPhase phase)
|
public void SetLaserPhase(LaserPhase phase)
|
||||||
{
|
{
|
||||||
|
// When controller is driving, cancel any self-cycling
|
||||||
if (externalControl)
|
if (externalControl)
|
||||||
{
|
{
|
||||||
StopAllCoroutines();
|
StopAllCoroutines();
|
||||||
introRunning = false;
|
introRunning = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!line) SetupLaserRenderer();
|
if (!line) SetupLaserRenderer();
|
||||||
|
|
||||||
// Always clear when entering lethal/lead-in phases
|
// Clear 1-kill gate whenever we enter lead-in or lethal phases
|
||||||
if (phase == LaserPhase.Firing || phase == LaserPhase.Charging)
|
if (phase == LaserPhase.Charging || phase == LaserPhase.Firing)
|
||||||
hasTriggeredDeathThisBurst = false;
|
hasTriggeredDeathThisBurst = false;
|
||||||
|
|
||||||
currentPhase = phase;
|
currentPhase = phase;
|
||||||
@ -163,7 +149,7 @@ public class LaserBeam : MonoBehaviour
|
|||||||
UpdateLaserPath();
|
UpdateLaserPath();
|
||||||
line.enabled = true;
|
line.enabled = true;
|
||||||
SetLineColor(laserColor);
|
SetLineColor(laserColor);
|
||||||
CheckHit();
|
CheckHit(); // immediate check on enter
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -209,7 +195,7 @@ public class LaserBeam : MonoBehaviour
|
|||||||
void DisableLaser()
|
void DisableLaser()
|
||||||
{
|
{
|
||||||
line.enabled = false;
|
line.enabled = false;
|
||||||
// Also clear endpoint for safety/debug
|
// Optional: zero endpoints for clarity in debug
|
||||||
laserStart = transform.position;
|
laserStart = transform.position;
|
||||||
laserEnd = laserStart;
|
laserEnd = laserStart;
|
||||||
}
|
}
|
||||||
@ -223,16 +209,12 @@ public class LaserBeam : MonoBehaviour
|
|||||||
|
|
||||||
void CheckHit()
|
void CheckHit()
|
||||||
{
|
{
|
||||||
// HARD GATES: never kill unless we’re allowed to
|
// only lethal during Firing, or during Intro if flagged as deadly
|
||||||
if (!isActiveAndEnabled) return;
|
|
||||||
if (!gameObject.activeInHierarchy) return;
|
|
||||||
|
|
||||||
bool lethalNow = (currentPhase == LaserPhase.Firing) || (introRunning && introIsDeadly);
|
bool lethalNow = (currentPhase == LaserPhase.Firing) || (introRunning && introIsDeadly);
|
||||||
if (!lethalNow) return;
|
if (!lethalNow || hasTriggeredDeathThisBurst) return;
|
||||||
|
|
||||||
if (hasTriggeredDeathThisBurst) return;
|
// local helper that can ignore a specific collider (e.g., the deflection box)
|
||||||
|
bool CheckSegment(Vector3 a, Vector3 b, Collider ignoreCol = null)
|
||||||
bool CheckSegment(Vector3 a, Vector3 b)
|
|
||||||
{
|
{
|
||||||
Vector3 d = b - a;
|
Vector3 d = b - a;
|
||||||
float len = d.magnitude;
|
float len = d.magnitude;
|
||||||
@ -247,12 +229,15 @@ public class LaserBeam : MonoBehaviour
|
|||||||
Collider bestCol = null;
|
Collider bestCol = null;
|
||||||
foreach (var h in hits)
|
foreach (var h in hits)
|
||||||
{
|
{
|
||||||
if (h.collider && h.collider.GetComponentInParent<LaserBeam>() == this) continue;
|
if (!h.collider) continue;
|
||||||
|
if (ignoreCol && h.collider == ignoreCol) continue; // NEW: ignore the deflection box
|
||||||
|
if (h.collider.GetComponentInParent<LaserBeam>() == this) continue;
|
||||||
if (h.distance < best) { best = h.distance; bestT = h.collider.transform; bestCol = h.collider; }
|
if (h.distance < best) { best = h.distance; bestT = h.collider.transform; bestCol = h.collider; }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bestT) return false;
|
if (!bestT) return false;
|
||||||
|
|
||||||
|
// Player?
|
||||||
if (bestT.CompareTag(playerTag) || (bestT.root && bestT.root.CompareTag(playerTag)))
|
if (bestT.CompareTag(playerTag) || (bestT.root && bestT.root.CompareTag(playerTag)))
|
||||||
{
|
{
|
||||||
hasTriggeredDeathThisBurst = true;
|
hasTriggeredDeathThisBurst = true;
|
||||||
@ -260,6 +245,7 @@ public class LaserBeam : MonoBehaviour
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Box? (still allow box damage feedback)
|
||||||
if (bestCol && bestCol.CompareTag(boxTag))
|
if (bestCol && bestCol.CompareTag(boxTag))
|
||||||
{
|
{
|
||||||
var boxHealth = bestCol.GetComponent<LaserBoxHealth>();
|
var boxHealth = bestCol.GetComponent<LaserBoxHealth>();
|
||||||
@ -270,11 +256,12 @@ public class LaserBeam : MonoBehaviour
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// segmented checks if we’re deflecting
|
||||||
if (_routeViaSide)
|
if (_routeViaSide)
|
||||||
{
|
{
|
||||||
if (CheckSegment(laserStart, _entryPoint)) return;
|
if (CheckSegment(laserStart, _entryPoint)) return;
|
||||||
if (CheckSegment(_entryPoint, _midPoint)) return;
|
if (CheckSegment(_entryPoint, _midPoint, _lastBox)) return; // ignore the box while exiting
|
||||||
CheckSegment(_midPoint, laserEnd);
|
CheckSegment(_midPoint, laserEnd, _lastBox); // ignore it on the last leg too
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -316,6 +303,7 @@ public class LaserBeam : MonoBehaviour
|
|||||||
line.SetPosition(0, laserStart);
|
line.SetPosition(0, laserStart);
|
||||||
line.SetPosition(1, laserEnd);
|
line.SetPosition(1, laserEnd);
|
||||||
|
|
||||||
|
// No deflect?
|
||||||
if (!deflectFromBoxSides || !gotHit || !bestHit.collider.CompareTag(boxTag)) return;
|
if (!deflectFromBoxSides || !gotHit || !bestHit.collider.CompareTag(boxTag)) return;
|
||||||
|
|
||||||
var box = bestHit.collider.GetComponent<BoxCollider>();
|
var box = bestHit.collider.GetComponent<BoxCollider>();
|
||||||
@ -328,21 +316,40 @@ public class LaserBeam : MonoBehaviour
|
|||||||
}
|
}
|
||||||
|
|
||||||
Transform t = box.transform;
|
Transform t = box.transform;
|
||||||
_entryPoint = bestHit.point + bestHit.normal * entryPush;
|
|
||||||
|
|
||||||
|
// ensure we don’t start the entry segment inside the box
|
||||||
|
float safeEntry = Mathf.Max(entryPush, hitRadius * 0.25f);
|
||||||
|
_entryPoint = bestHit.point + bestHit.normal * safeEntry;
|
||||||
|
|
||||||
|
// compute the midpoint on the box side we’re exiting from
|
||||||
Vector3 centerW = t.TransformPoint(box.center);
|
Vector3 centerW = t.TransformPoint(box.center);
|
||||||
Vector3 half = Vector3.Scale(box.size * 0.5f, t.lossyScale);
|
Vector3 half = Vector3.Scale(box.size * 0.5f, t.lossyScale);
|
||||||
Vector3 rightW = t.right.normalized;
|
Vector3 rightW = t.right.normalized;
|
||||||
Vector3 outDir = rightW * _sideSign;
|
Vector3 outDir = rightW * _sideSign;
|
||||||
_midPoint = centerW + rightW * (_sideSign * half.x);
|
_midPoint = centerW + rightW * (_sideSign * half.x);
|
||||||
|
|
||||||
|
// how much distance remains for leg 2
|
||||||
float traveled = bestHit.distance + Vector3.Distance(bestHit.point, _midPoint);
|
float traveled = bestHit.distance + Vector3.Distance(bestHit.point, _midPoint);
|
||||||
float remain = Mathf.Max(0f, maxDistance - traveled);
|
float remain = Mathf.Max(0f, maxDistance - traveled);
|
||||||
float leg = Mathf.Min(outDistance, remain);
|
float leg = Mathf.Min(outDistance, remain);
|
||||||
|
|
||||||
Vector3 secondStart = _midPoint + outDir * sideExitPush;
|
// Choose a second start that is definitely OUTSIDE the box surface
|
||||||
|
float minExit = Mathf.Max(sideExitPush, radius + 0.02f);
|
||||||
|
Vector3 secondStart = _midPoint + outDir * minExit;
|
||||||
|
|
||||||
|
// If somehow still overlapping the box bounds, nudge out a bit more (guarded)
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
// AABBs are conservative; this is cheap and “good enough”
|
||||||
|
if (box.bounds.Contains(secondStart))
|
||||||
|
secondStart += outDir * (radius + 0.02f);
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
Vector3 secondEnd = secondStart + outDir * leg;
|
Vector3 secondEnd = secondStart + outDir * leg;
|
||||||
|
|
||||||
|
// Trim second leg if it hits something early
|
||||||
if (Physics.SphereCast(secondStart, radius, outDir, out var h2, leg, collisionMask, queryTriggerMode))
|
if (Physics.SphereCast(secondStart, radius, outDir, out var h2, leg, collisionMask, queryTriggerMode))
|
||||||
{
|
{
|
||||||
if (!(h2.collider && h2.collider.GetComponentInParent<LaserBeam>() == this))
|
if (!(h2.collider && h2.collider.GetComponentInParent<LaserBeam>() == this))
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user