MiniGames/Assets/Scripts/ChaseOn/ChaseLaserBeam.cs
2025-09-22 17:26:19 +05:00

260 lines
7.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Collections;
using UnityEngine;
[RequireComponent(typeof(LineRenderer))]
public class ChaseLaserBeam : MonoBehaviour
{
[Header("Laser Setup")]
public Transform laserOrigin;
public float maxDistance = 20f;
public LayerMask collisionMask;
public Color laserColor = Color.red;
public float laserWidth = 0.05f;
[Header("Visuals")]
public float scrollSpeed = 1f;
public float emissionStrength = 5f;
[Header("Performance")]
public float updateRate = 0.02f;
[Header("Pulse (On/Off)")]
public bool pulsing = true;
public bool startOn = true;
public float onDuration = 1.5f;
public float offDuration = 1.5f;
public float fadeIn = 0.15f;
public float fadeOut = 0.15f;
public float startDelay = 0f;
public float randomStartOffset = 0f;
[Header("Lethality")]
[Range(0f, 1f)] public float lethalThreshold = 0.9f;
private LineRenderer line;
private Vector3 laserStart, laserEnd;
private Material matInstance;
private float currentIntensity = 0f;
private bool isActiveVisual = false;
private bool isEnabled = false;
private Coroutine pulseCo;
void Awake()
{
line = GetComponent<LineRenderer>();
SetupLaserRenderer();
}
void OnEnable()
{
isEnabled = true;
line.enabled = true;
InvokeRepeating(nameof(UpdateLaser), 0f, updateRate);
if (pulsing) pulseCo = StartCoroutine(PulseRoutine());
else
{
currentIntensity = 1f;
isActiveVisual = true;
ApplyIntensity(currentIntensity);
}
}
void OnDisable()
{
isEnabled = false;
CancelInvoke(nameof(UpdateLaser));
if (pulseCo != null) StopCoroutine(pulseCo);
if (line != null) line.enabled = false;
}
void UpdateLaser()
{
if (!isActiveVisual || currentIntensity <= 0.001f)
{
if (line.enabled) line.enabled = false;
return;
}
laserStart = laserOrigin ? laserOrigin.position : transform.position;
Vector3 direction = transform.forward;
if (Physics.Raycast(laserStart, direction, out RaycastHit hit, maxDistance, collisionMask))
{
laserEnd = hit.point;
if (/*currentIntensity >= lethalThreshold && */hit.collider.CompareTag("Player"))
{
// Use Shared_DieZibu for laser kill
var die = hit.collider.GetComponent<Shared_DieZibu>() ?? hit.collider.GetComponentInParent<Shared_DieZibu>();
if (die != null)
{
// optional: stop the runners local movement flags if present
var runner = die.GetComponent<ChasePlayerController>();
if (runner != null)
{
runner.StartCoroutine(runner.PlayStateAndGameOver(runner.fallingStateName, runner.fallingShortHash));
}
die.KillByLaser();
}
else
{
// Fallback: if no Shared_DieZibu found, keep old behavior (optional)
var runner = hit.collider.GetComponent<ChasePlayerController>() ?? hit.collider.GetComponentInParent<ChasePlayerController>();
if (runner != null /*&& !runner.waitingForGameOver*/)
{
runner.moveSpeed = 0;
runner.waitingForGameOver = true;
runner.StartCoroutine(runner.PlayStateAndGameOver(runner.fallingStateName, runner.fallingShortHash));
}
}
}
}
else
{
laserEnd = laserStart + direction * maxDistance;
}
if (!line.enabled) line.enabled = true;
line.SetPosition(0, laserStart);
line.SetPosition(1, laserEnd);
}
void SetupLaserRenderer()
{
line.useWorldSpace = true;
line.positionCount = 2;
line.loop = false;
line.widthMultiplier = laserWidth;
line.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
line.receiveShadows = false;
Shader laserShader = Shader.Find("Custom/EmissiveLaser");
if (laserShader != null)
{
matInstance = new Material(laserShader);
matInstance.SetColor("_Color", laserColor);
matInstance.SetFloat("_Emission", 0f);
matInstance.SetFloat("_ScrollSpeed", scrollSpeed);
line.material = matInstance;
}
else
{
matInstance = new Material(Shader.Find("Sprites/Default"));
matInstance.color = laserColor * 0f;
line.material = matInstance;
}
line.startColor = laserColor;
line.endColor = laserColor;
}
IEnumerator PulseRoutine()
{
float jitter = (randomStartOffset > 0f) ? Random.Range(-randomStartOffset, randomStartOffset) : 0f;
if (startDelay + jitter > 0f) yield return new WaitForSeconds(startDelay + jitter);
bool stateOn = startOn;
while (isEnabled)
{
if (stateOn)
{
if (fadeIn > 0f) yield return FadeIntensity(1f, fadeIn);
else { currentIntensity = 1f; ApplyIntensity(currentIntensity); }
isActiveVisual = true;
if (onDuration > 0f) yield return new WaitForSeconds(onDuration);
}
else
{
if (fadeOut > 0f) yield return FadeIntensity(0f, fadeOut);
else { currentIntensity = 0f; ApplyIntensity(currentIntensity); }
isActiveVisual = false;
if (offDuration > 0f) yield return new WaitForSeconds(offDuration);
}
stateOn = !stateOn;
}
}
IEnumerator FadeIntensity(float target, float time)
{
float start = currentIntensity;
float t = 0f;
isActiveVisual = (target > 0f) || (start > 0f);
while (t < 1f)
{
t += Time.deltaTime / Mathf.Max(0.0001f, time);
currentIntensity = Mathf.Lerp(start, target, t);
ApplyIntensity(currentIntensity);
yield return null;
}
currentIntensity = target;
ApplyIntensity(currentIntensity);
if (currentIntensity <= 0.001f && line.enabled) line.enabled = false;
}
void ApplyIntensity(float normalized)
{
line.widthMultiplier = Mathf.Max(0.0001f, laserWidth * Mathf.Lerp(0.35f, 1f, normalized));
if (matInstance != null)
{
if (matInstance.HasProperty("_Emission"))
{
matInstance.SetFloat("_Emission", emissionStrength * normalized);
}
else
{
Color c = laserColor;
c.a = Mathf.Clamp01(normalized);
matInstance.color = c;
}
}
}
public void SetPulsing(bool enabled)
{
pulsing = enabled;
if (!isEnabled) return;
if (pulseCo != null) { StopCoroutine(pulseCo); pulseCo = null; }
if (pulsing) pulseCo = StartCoroutine(PulseRoutine());
else
{
currentIntensity = 1f;
ApplyIntensity(currentIntensity);
isActiveVisual = true;
}
}
public void ForceOff()
{
if (pulseCo != null) { StopCoroutine(pulseCo); pulseCo = null; }
pulsing = false;
currentIntensity = 0f;
ApplyIntensity(0f);
isActiveVisual = false;
if (line) line.enabled = false;
}
public void ForceOn()
{
if (pulseCo != null) { StopCoroutine(pulseCo); pulseCo = null; }
pulsing = false;
currentIntensity = 1f;
ApplyIntensity(1f);
isActiveVisual = true;
if (line && !line.enabled) line.enabled = true;
}
}