Periodic enabling of laser

This commit is contained in:
Ali Sharoz 2025-08-19 16:59:43 +05:00
parent 700f11bc94
commit 66462ce70d
14 changed files with 2692 additions and 1073 deletions

105
Assets/ChaseLaserBeam.cs Normal file
View File

@ -0,0 +1,105 @@
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;
private LineRenderer line;
private Vector3 laserStart, laserEnd;
void Awake()
{
line = GetComponent<LineRenderer>();
SetupLaserRenderer();
}
void OnEnable()
{
line.enabled = true;
InvokeRepeating(nameof(UpdateLaser), 0f, updateRate);
}
void OnDisable()
{
CancelInvoke(nameof(UpdateLaser));
if (line != null)
line.enabled = false;
}
void UpdateLaser()
{
laserStart = laserOrigin ? laserOrigin.position : transform.position;
Vector3 direction = transform.forward;
if (Physics.Raycast(laserStart, direction, out RaycastHit hit, maxDistance, collisionMask))
{
laserEnd = hit.point;
if (hit.collider.CompareTag("Player"))
{
Debug.Log("⚠️ Player hit by chase laser!");
ChasePlayerController player = hit.collider.GetComponent<ChasePlayerController>();
if (player != null && !player.waitingForGameOver)
{
player.moveSpeed = 0;
player.waitingForGameOver = true;
player.StartCoroutine(player.PlayStateAndGameOver(player.fallingStateName, player.fallingShortHash));
}
// TODO: Trigger player damage or effects
}
}
else
{
laserEnd = laserStart + direction * maxDistance;
}
line.enabled = true; // Force enabled in case something disables it
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;
// Try using custom emissive shader
Shader laserShader = Shader.Find("Custom/EmissiveLaser");
if (laserShader != null)
{
Material laserMat = new Material(laserShader);
laserMat.SetColor("_Color", laserColor);
laserMat.SetFloat("_Emission", emissionStrength);
laserMat.SetFloat("_ScrollSpeed", scrollSpeed);
line.material = laserMat;
}
else
{
// Fallback shader
Material fallback = new Material(Shader.Find("Sprites/Default"));
fallback.color = laserColor;
line.material = fallback;
}
line.startColor = laserColor;
line.endColor = laserColor;
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0a334db153d189a48b221ea963f66011
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -11,24 +11,28 @@ public class LaserBeam : MonoBehaviour
[Header("Laser Appearance")]
public Color laserColor = Color.red;
public Color warningColor = new Color(1f, 0.5f, 0f); // Orange
public Color warningColor = new Color(1f, 0.5f, 0f);
public float laserWidth = 0.05f;
public float emissionStrength = 5f;
public float scrollSpeed = 1f;
[Header("Player Hit")]
public string playerTag = "Player";
[Tooltip("Approximate beam thickness for hit tests.")]
public float hitRadius = 0.1f;
[Tooltip("Should raycasts consider trigger colliders? (Player often uses triggers)")]
public QueryTriggerInteraction queryTriggerMode = QueryTriggerInteraction.Collide;
[Header("Intro Show")]
public bool showIntro = true;
public float initialShowDuration = 3f;
[Tooltip("If true, the intro beam can kill the player too.")]
public bool introIsDeadly = true;
[Header("Deflection (Box side center)")]
public bool deflectFromBoxSides = true;
public string boxTag = "Box";
public float outDistance = 12f;
public float sideExitPush = 0.02f;
public float entryPush = 0.005f;
[Header("Debug")]
public bool debugDraw = false;
@ -36,6 +40,9 @@ public class LaserBeam : MonoBehaviour
private float timer = 0f;
private enum LaserState { Idle, Charging, Firing }
public enum LaserPhase { Idle, Charging, Firing }
private LaserPhase currentPhase = LaserPhase.Idle;
private LaserState currentState = LaserState.Idle;
private Vector3 laserStart;
@ -44,44 +51,15 @@ public class LaserBeam : MonoBehaviour
private bool introRunning = false;
private bool hasTriggeredDeathThisBurst = false;
// cache root to ignore self-hits
Transform _selfRoot;
[Header("Deflection")]
public bool enableDeflection = true;
public string deflectTag = "Box";
[Tooltip("How far the beam travels after deflection.")]
public float deflectDistance = 10f;
[Tooltip("Push along the deflected direction to avoid re-hitting the same face.")]
public float deflectEdgePush = 0.02f;
// runtime cache so the left/right choice doesn't flicker
Collider _currentDeflectCol;
int _currentDeflectSign = 1; // +1 = right, -1 = left
bool _isDeflecting;
Vector3 _bouncePoint;
Vector3 _bounceEnd;
[Header("Deflection (Box side center)")]
[Tooltip("Tiny push so the second segment isn't inside the face.")]
// runtime
bool _segmented;
[Header("Deflection (Box side center)")]
public bool deflectFromBoxSides = true;
public string boxTag = "Box";
public float outDistance = 12f;
public float sideExitPush = 0.02f; // push outward from side face
public float entryPush = 0.005f; // push outward from front face so it shows
// runtime
bool _routeViaSide;
Vector3 _entryPoint; // front-face hit
Vector3 _midPoint; // side-face center
Collider _lastBox;
int _sideSign = 1; // -1 = left, +1 = right (box local right axis)
// Deflection
private bool _routeViaSide;
private Vector3 _entryPoint;
private Vector3 _midPoint;
private Collider _lastBox;
private int _sideSign = 1;
void Awake()
{
_selfRoot = transform.root;
SetupLaserRenderer();
}
@ -100,7 +78,7 @@ public class LaserBeam : MonoBehaviour
switch (currentState)
{
case LaserState.Idle:
hasTriggeredDeathThisBurst = false; // reset per cycle
hasTriggeredDeathThisBurst = false;
if (timer >= chargeDuration)
{
timer = 0f;
@ -138,20 +116,58 @@ public class LaserBeam : MonoBehaviour
}
if (debugDraw)
Debug.DrawLine(laserStart, laserEnd, Color.cyan);
}
public void SetLaserPhase(LaserPhase phase)
{
currentPhase = phase;
switch (phase)
{
Debug.DrawLine(laserStart, laserEnd, Color.cyan, 0f, false);
case LaserPhase.Idle:
DisableLaser();
break;
case LaserPhase.Charging:
UpdateLaserPath();
line.enabled = true;
SetLineColor(warningColor);
break;
case LaserPhase.Firing:
UpdateLaserPath();
SetLineColor(laserColor);
hasTriggeredDeathThisBurst = false;
CheckHit();
break;
}
}
public void TickLaserDuringFiring()
{
if (currentPhase == LaserPhase.Firing)
{
UpdateLaserPath();
CheckHit();
}
}
public void TickLaserDuringCharging()
{
if (currentPhase == LaserPhase.Charging)
{
BlinkWarning();
UpdateLaserPath();
}
}
// ---------------- Intro show ----------------
System.Collections.IEnumerator IntroShow()
{
introRunning = true;
float t = 0f;
line.enabled = true;
SetLineColor(laserColor);
hasTriggeredDeathThisBurst = false;
while (t < initialShowDuration)
@ -170,7 +186,6 @@ public class LaserBeam : MonoBehaviour
introRunning = false;
}
// ---------------- States ----------------
void StartCharging()
{
UpdateLaserPath();
@ -178,20 +193,12 @@ public class LaserBeam : MonoBehaviour
SetLineColor(warningColor);
}
void BlinkWarning()
{
float blink = Mathf.PingPong(Time.time * 5f, 1f);
Color blinkColor = Color.Lerp(Color.clear, warningColor, blink);
SetLineColor(blinkColor);
}
void FireLaser()
{
UpdateLaserPath();
SetLineColor(laserColor);
hasTriggeredDeathThisBurst = false;
CheckHit(); // initial frame
CheckHit();
}
void DisableLaser()
@ -199,52 +206,6 @@ public class LaserBeam : MonoBehaviour
line.enabled = false;
}
// ---------------- Hit Detection (robust) ----------------
//void CheckHit()
//{
// if (hasTriggeredDeathThisBurst) return;
// Vector3 dir = (laserEnd - laserStart).normalized;
// float distToEnd = Vector3.Distance(laserStart, laserEnd);
// // Cast along visible beam, then pick the nearest valid hit
// RaycastHit[] hits = Physics.SphereCastAll(
// laserStart, hitRadius, dir,
// distToEnd, collisionMask, queryTriggerMode
// );
// if (hits == null || hits.Length == 0) return;
// float bestDist = float.MaxValue;
// Transform best = null;
// foreach (var h in hits)
// {
// // Ignore self (any collider in our own hierarchy)
// if (h.collider && h.collider.GetComponentInParent<LaserBeam>() == this)
// continue;
// // Keep the nearest hit under our visible segment
// if (h.distance < bestDist)
// {
// bestDist = h.distance;
// best = h.collider.transform;
// }
// }
// if (best == null) return;
// // Player detection: check both object and its root
// bool isPlayer =
// best.CompareTag(playerTag) ||
// (best.root != null && best.root.CompareTag(playerTag));
// if (isPlayer)
// {
// Debug.Log("Laser hit player: " + best.name);
// hasTriggeredDeathThisBurst = true;
// CrateEscapeGameManager.Instance?.OnPlayerHitByLaser();
// }
//}
void CheckHit()
{
if (hasTriggeredDeathThisBurst) return;
@ -261,20 +222,32 @@ public class LaserBeam : MonoBehaviour
float best = float.MaxValue;
Transform bestT = null;
Collider bestCol = null;
foreach (var h in hits)
{
if (h.collider && h.collider.GetComponentInParent<LaserBeam>() == this) continue;
if (h.distance < best) { best = h.distance; bestT = h.collider.transform; }
if (h.distance < best) { best = h.distance; bestT = h.collider.transform; bestCol = h.collider; }
}
if (!bestT) return false;
bool isPlayer = bestT.CompareTag(playerTag) || (bestT.root && bestT.root.CompareTag(playerTag));
if (isPlayer)
// Hit player
if (bestT.CompareTag(playerTag) || (bestT.root && bestT.root.CompareTag(playerTag)))
{
hasTriggeredDeathThisBurst = true;
Debug.Log("Laser hit player: " + bestT.name);
CrateEscapeGameManager.Instance?.OnPlayerHitByLaser();
return true;
}
// Hit box
if (bestCol.CompareTag(boxTag))
{
var boxHealth = bestCol.GetComponent<LaserBoxHealth>();
if (boxHealth != null)
boxHealth.TakeLaserDamage();
}
return false;
}
@ -289,17 +262,19 @@ public class LaserBeam : MonoBehaviour
CheckSegment(laserStart, laserEnd);
}
}
void BlinkWarning()
{
float blink = Mathf.PingPong(Time.time * 5f, 1f);
Color blinkColor = Color.Lerp(Color.clear, warningColor, blink);
SetLineColor(blinkColor);
}
void UpdateLaserPath()
{
laserStart = transform.position;
Vector3 dir = transform.forward;
float radius = Mathf.Max(0.0001f, hitRadius);
// first: straight cast to find the first collider
RaycastHit[] hits = Physics.SphereCastAll(laserStart, radius, dir, maxDistance, collisionMask, queryTriggerMode);
Vector3 straightEnd = laserStart + dir * maxDistance;
RaycastHit bestHit = default;
float bestDist = float.MaxValue;
@ -321,21 +296,18 @@ public class LaserBeam : MonoBehaviour
}
}
// default: straight line
_routeViaSide = false;
laserEnd = straightEnd;
line.positionCount = 2;
line.SetPosition(0, laserStart);
line.SetPosition(1, laserEnd);
// route via side center only for tagged Box with a BoxCollider
if (!deflectFromBoxSides || !gotHit || !bestHit.collider.CompareTag(boxTag))
return;
// Side-deflection logic
if (!deflectFromBoxSides || !gotHit || !bestHit.collider.CompareTag(boxTag)) return;
var box = bestHit.collider.GetComponent<BoxCollider>();
if (!box) return;
// choose/stabilize left/right per box
if (_lastBox != bestHit.collider)
{
_lastBox = bestHit.collider;
@ -343,19 +315,14 @@ public class LaserBeam : MonoBehaviour
}
Transform t = box.transform;
// 1) ENTRY POINT on the FRONT face (push a hair outward so it's visible)
_entryPoint = bestHit.point + bestHit.normal * entryPush;
// 2) SIDE-CENTER (left/right in box local space), and outward direction
Vector3 centerW = t.TransformPoint(box.center);
Vector3 half = Vector3.Scale(box.size * 0.5f, t.lossyScale);
Vector3 rightW = t.right.normalized;
Vector3 outDir = rightW * _sideSign;
_midPoint = centerW + rightW * (_sideSign * half.x);
// 3) SECOND LEG: from side-center outward
// remaining distance after traveling to entry + to side-center
float traveled = bestHit.distance + Vector3.Distance(bestHit.point, _midPoint);
float remain = Mathf.Max(0f, maxDistance - traveled);
float leg = Mathf.Min(outDistance, remain);
@ -369,7 +336,6 @@ public class LaserBeam : MonoBehaviour
secondEnd = h2.point;
}
// draw the full polyline: START -> ENTRY -> SIDE-CENTER -> OUT
_routeViaSide = true;
laserEnd = secondEnd;
@ -380,49 +346,22 @@ public class LaserBeam : MonoBehaviour
line.SetPosition(3, laserEnd);
}
//void UpdateLaserPath()
//{
// laserStart = transform.position;
// Vector3 dir = transform.forward;
public void ResetCycle()
{
StopAllCoroutines();
introRunning = false;
timer = 0f;
currentState = LaserState.Idle;
currentPhase = LaserPhase.Idle;
hasTriggeredDeathThisBurst = false;
DisableLaser();
}
// // SphereCast to find the FIRST valid hit along the visible beam,
// // ignoring ONLY this laser's own colliders.
// float radius = Mathf.Max(0.0001f, hitRadius);
// RaycastHit[] hits = Physics.SphereCastAll(
// laserStart, radius, dir, maxDistance, collisionMask, queryTriggerMode
// );
// Vector3 end = laserStart + dir * maxDistance;
// float bestDist = float.MaxValue;
// if (hits != null && hits.Length > 0)
// {
// foreach (var h in hits)
// {
// if (!h.collider) continue;
// // Ignore ONLY this LaserBeam's colliders (not the whole root/level)
// if (h.collider.GetComponentInParent<LaserBeam>() == this)
// continue;
// if (h.distance < bestDist)
// {
// bestDist = h.distance;
// end = h.point;
// }
// }
// }
// laserEnd = end;
// line.SetPosition(0, laserStart);
// line.SetPosition(1, laserEnd);
//}
// ---------------- Utils ----------------
void SetLineColor(Color c)
{
line.material.color = c;
if (line.material.HasProperty("_Color"))
line.material.SetColor("_Color", c);
line.startColor = c;
line.endColor = c;
}
@ -450,18 +389,10 @@ public class LaserBeam : MonoBehaviour
}
else
{
Debug.LogWarning("Custom/EmissiveLaser shader not found. Using fallback.");
line.material = new Material(Shader.Find("Sprites/Default"));
line.material.color = laserColor;
}
line.enabled = false;
}
void OnDrawGizmosSelected()
{
if (!debugDraw) return;
Gizmos.color = Color.magenta;
Gizmos.DrawWireSphere(transform.position, hitRadius);
}
}

View File

@ -0,0 +1,117 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using static LaserBeam;
public class LaserBeamController : MonoBehaviour
{
public float interval = 20f;
public float chargeDuration = 3f;
public float fireDuration = 1f;
private List<LaserBeam> allLasers = new List<LaserBeam>();
private List<List<LaserBeam>> batches = new List<List<LaserBeam>>();
private List<LaserBeam> activeLasers = new List<LaserBeam>();
private float timer = 0f;
private LaserPhase currentPhase = LaserPhase.Idle;
void Start()
{
allLasers.AddRange(FindObjectsOfType<LaserBeam>());
// Shuffle
for (int i = 0; i < allLasers.Count; i++)
{
var temp = allLasers[i];
int rand = Random.Range(i, allLasers.Count);
allLasers[i] = allLasers[rand];
allLasers[rand] = temp;
}
// Split into 3 batches
int batchSize = Mathf.CeilToInt(allLasers.Count / 3f);
for (int i = 0; i < allLasers.Count; i += batchSize)
{
batches.Add(allLasers.GetRange(i, Mathf.Min(batchSize, allLasers.Count - i)));
}
foreach (var lb in allLasers)
lb.enabled = false;
StartCoroutine(ActivateBatches());
}
IEnumerator ActivateBatches()
{
for (int i = 0; i < batches.Count; i++)
{
activeLasers.AddRange(batches[i]);
foreach (var laser in activeLasers)
laser.enabled = true;
Debug.Log($"Activated batch {i + 1}, syncing all {activeLasers.Count} lasers.");
ResetAllLasers();
yield return new WaitForSeconds(interval);
}
}
void Update()
{
if (activeLasers.Count == 0) return;
timer += Time.deltaTime;
switch (currentPhase)
{
case LaserPhase.Idle:
if (timer >= chargeDuration)
{
timer = 0f;
currentPhase = LaserPhase.Charging;
foreach (var laser in activeLasers)
laser.SetLaserPhase(LaserPhase.Charging);
}
break;
case LaserPhase.Charging:
foreach (var laser in activeLasers)
laser.TickLaserDuringCharging();
if (timer >= 1f)
{
timer = 0f;
currentPhase = LaserPhase.Firing;
foreach (var laser in activeLasers)
laser.SetLaserPhase(LaserPhase.Firing);
}
break;
case LaserPhase.Firing:
foreach (var laser in activeLasers)
laser.TickLaserDuringFiring();
if (timer >= fireDuration)
{
timer = 0f;
currentPhase = LaserPhase.Idle;
foreach (var laser in activeLasers)
laser.SetLaserPhase(LaserPhase.Idle);
}
break;
}
}
void ResetAllLasers()
{
timer = 0f;
currentPhase = LaserPhase.Idle;
foreach (var laser in activeLasers)
{
laser.SetLaserPhase(LaserPhase.Idle);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9511137add479ac46a49f0f07d801aea
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,283 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &2076035923175665683
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4569536219989199992}
- component: {fileID: 5627322522777133560}
- component: {fileID: 673720149171018749}
- component: {fileID: 89581383608372913}
m_Layer: 10
m_Name: BeamLine
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &4569536219989199992
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2076035923175665683}
serializedVersion: 2
m_LocalRotation: {x: 0, y: -0.7071068, z: 0, w: 0.7071068}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 5.9825163, y: 5.9825163, z: 5.9825163}
m_ConstrainProportionsScale: 1
m_Children: []
m_Father: {fileID: 5791487380880912914}
m_LocalEulerAnglesHint: {x: 0, y: -90, z: 0}
--- !u!114 &5627322522777133560
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2076035923175665683}
m_Enabled: 0
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fb66dc0e33e58d7439c1db6e435dcc9e, type: 3}
m_Name:
m_EditorClassIdentifier:
maxDistance: 6.2
collisionMask:
serializedVersion: 2
m_Bits: 255
chargeDuration: 3
fireDuration: 1
laserColor: {r: 1, g: 0, b: 0, a: 1}
warningColor: {r: 1, g: 0.5, b: 0, a: 1}
laserWidth: 0.01
emissionStrength: 2
scrollSpeed: 1
playerTag: Player
hitRadius: 0.1
queryTriggerMode: 2
showIntro: 1
initialShowDuration: 3
introIsDeadly: 1
deflectFromBoxSides: 1
boxTag: Box
outDistance: 12
sideExitPush: 0.02
entryPush: 0.005
debugDraw: 0
--- !u!120 &673720149171018749
LineRenderer:
serializedVersion: 2
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2076035923175665683}
m_Enabled: 1
m_CastShadows: 0
m_ReceiveShadows: 0
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 0
m_LightProbeUsage: 0
m_ReflectionProbeUsage: 0
m_RayTracingMode: 0
m_RayTraceProcedural: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 0}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_Positions:
- {x: 1.5000002, y: 0.582, z: 56.903}
- {x: 0.12069942, y: 0.5819865, z: 56.902992}
m_Parameters:
serializedVersion: 3
widthMultiplier: 0.01
widthCurve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 1
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
colorGradient:
serializedVersion: 2
key0: {r: 1, g: 0, b: 0, a: 1}
key1: {r: 1, g: 0, b: 0, a: 1}
key2: {r: 0, g: 0, b: 0, a: 0}
key3: {r: 0, g: 0, b: 0, a: 0}
key4: {r: 0, g: 0, b: 0, a: 0}
key5: {r: 0, g: 0, b: 0, a: 0}
key6: {r: 0, g: 0, b: 0, a: 0}
key7: {r: 0, g: 0, b: 0, a: 0}
ctime0: 0
ctime1: 65535
ctime2: 0
ctime3: 0
ctime4: 0
ctime5: 0
ctime6: 0
ctime7: 0
atime0: 0
atime1: 65535
atime2: 0
atime3: 0
atime4: 0
atime5: 0
atime6: 0
atime7: 0
m_Mode: 0
m_ColorSpace: -1
m_NumColorKeys: 2
m_NumAlphaKeys: 2
numCornerVertices: 0
numCapVertices: 0
alignment: 0
textureMode: 0
textureScale: {x: 1, y: 1}
shadowBias: 0.5
generateLightingData: 0
m_MaskInteraction: 0
m_UseWorldSpace: 1
m_Loop: 0
m_ApplyActiveColorSpace: 1
--- !u!114 &89581383608372913
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2076035923175665683}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 0a334db153d189a48b221ea963f66011, type: 3}
m_Name:
m_EditorClassIdentifier:
laserOrigin: {fileID: 4569536219989199992}
maxDistance: 20
collisionMask:
serializedVersion: 2
m_Bits: 4294967295
laserColor: {r: 1, g: 0, b: 0, a: 1}
laserWidth: 0.05
scrollSpeed: 1
emissionStrength: 5
updateRate: 0.02
--- !u!1 &5941778434987404378
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 5791487380880912914}
- component: {fileID: 1558933298697028777}
- component: {fileID: 355708440500072884}
m_Layer: 10
m_Name: ChaseLaser
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &5791487380880912914
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5941778434987404378}
serializedVersion: 2
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0.072500005, y: -0.001000023, z: -0.000029999112}
m_LocalScale: {x: 5, y: 5, z: 5}
m_ConstrainProportionsScale: 1
m_Children:
- {fileID: 4569536219989199992}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: -90, y: 0, z: 0}
--- !u!33 &1558933298697028777
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5941778434987404378}
m_Mesh: {fileID: 938762473992563870, guid: 672aa84817b45ba4aa212666c86e0d4a, type: 3}
--- !u!23 &355708440500072884
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5941778434987404378}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: bd4a01711df9d8d43a627cfa7fd3d2cf, type: 2}
- {fileID: 2100000, guid: c4a4afe7921aa2f4582fccd2bd7f1efa, type: 2}
- {fileID: 2100000, guid: 5fbb0c4334374934abc11d566db804a9, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 464bfa86f2fc8034bb796ca8b991caef
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@ -1500,7 +1500,7 @@ GameObject:
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 0
m_IsActive: 1
--- !u!215 &1117356489
ReflectionProbe:
m_ObjectHideFlags: 0
@ -2512,6 +2512,8 @@ MonoBehaviour:
fallingStateName: Falling
secondHitWindow: 10
stateWaitTimeout: 3
waitingForGameOver: 0
fallingShortHash: 0
validateStatesOnStart: 1
runTag: Run
fallTag: Fall

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,6 @@ public class ChaseCoin : MonoBehaviour
void OnTriggerEnter(Collider other)
{
Debug.Log("ChaseCoin0");
if (other.CompareTag("Player"))
{

View File

@ -36,9 +36,10 @@ public class ChasePlayerController : MonoBehaviour
float minSwipeDistance = 50f;
float lastObstacleHitTime = -999f;
bool waitingForGameOver = false;
public bool waitingForGameOver = false;
int runShortHash, fallShortHash, fallingShortHash;
int runShortHash, fallShortHash;
public int fallingShortHash;
[SerializeField] bool validateStatesOnStart = true;
[SerializeField] string runTag = "Run";
[SerializeField] string fallTag = "Fall";
@ -329,7 +330,7 @@ public class ChasePlayerController : MonoBehaviour
animator.CrossFadeInFixedTime(runStateName, 0.1f, baseLayer, 0f);
}
}
IEnumerator PlayStateAndGameOver(string stateName, int shortHash, float xfade = 0.08f)
public IEnumerator PlayStateAndGameOver(string stateName, int shortHash, float xfade = 0.08f)
{
unableToMove = true;
if (string.IsNullOrEmpty(stateName) || animator == null)

View File

@ -0,0 +1,98 @@
using UnityEngine;
using System.Collections.Generic;
public class LaserBoxHealth : MonoBehaviour
{
[Header("Health Settings")]
public float maxHealth = 100f;
public float currentHealth = 100f;
public float damagePerHit = 10f;
[Header("Visual Feedback")]
public Renderer targetRenderer; // assign your MeshRenderer here if not on same object
private List<Material> runtimeMaterials = new List<Material>();
private List<Color> originalColors = new List<Color>();
[Header("Destruction")]
public float destructionDuration = 1f;
private bool isDestroying = false;
void Start()
{
if (!targetRenderer)
targetRenderer = GetComponent<Renderer>();
if (targetRenderer != null)
{
var sharedMats = targetRenderer.materials;
runtimeMaterials.Clear();
originalColors.Clear();
for (int i = 0; i < sharedMats.Length; i++)
{
Material mat = new Material(sharedMats[i]); // create runtime copy
runtimeMaterials.Add(mat);
originalColors.Add(mat.color);
}
targetRenderer.materials = runtimeMaterials.ToArray(); // assign runtime copies
}
currentHealth = maxHealth;
}
public void TakeLaserDamage()
{
if (isDestroying || currentHealth <= 0f) return;
currentHealth -= damagePerHit;
currentHealth = Mathf.Clamp(currentHealth, 0f, maxHealth);
UpdateColors();
if (currentHealth <= 0f)
{
StartCoroutine(ScaleAndDisable());
}
}
void UpdateColors()
{
float healthPercent = currentHealth / maxHealth;
for (int i = 0; i < runtimeMaterials.Count; i++)
{
if (runtimeMaterials[i] == null) continue;
Color targetColor = originalColors[i];
if (healthPercent <= 0.5f && healthPercent > 0.1f)
{
float t = Mathf.InverseLerp(0.5f, 0.1f, healthPercent);
runtimeMaterials[i].color = Color.Lerp(Color.black, targetColor, t);
}
else if (healthPercent <= 0.1f)
{
runtimeMaterials[i].color = Color.black;
}
}
}
System.Collections.IEnumerator ScaleAndDisable()
{
isDestroying = true;
Vector3 startScale = transform.localScale;
Vector3 endScale = Vector3.zero;
float t = 0f;
while (t < destructionDuration)
{
t += Time.deltaTime;
transform.localScale = Vector3.Lerp(startScale, endScale, t / destructionDuration);
yield return null;
}
gameObject.SetActive(false);
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7425323cb2d4b3d4cb9b8411e82185ec
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: