wip : scarecrow fix & subtitle event implementation
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Unheimlich.VFX;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
@@ -8,7 +10,6 @@ public class ScarecrowFire : MonoBehaviour
|
||||
public class FireElement
|
||||
{
|
||||
public GameObject VFX;
|
||||
/// <summary>Original scale captured at initialization, used as lerp target.</summary>
|
||||
[HideInInspector] public Vector3 OriginalScale;
|
||||
}
|
||||
|
||||
@@ -23,14 +24,9 @@ public class ScarecrowFire : MonoBehaviour
|
||||
[SerializeField] private FireElement _fireBig;
|
||||
|
||||
[Header("Propagation Timings")]
|
||||
[Tooltip("Duration of the scale lerp for each fire element (seconds).")]
|
||||
[SerializeField] private float _growDuration = 3f;
|
||||
|
||||
[Tooltip("How early the next stage starts before the current one finishes (0 = no overlap, 1 = instant).")]
|
||||
[Range(0f, 1f)]
|
||||
[SerializeField] private float _overlapFactor = 0.4f;
|
||||
|
||||
[Tooltip("Curve driving the scale growth — tweak directly in the Inspector.")]
|
||||
[SerializeField] private AnimationCurve _growCurve = new AnimationCurve(
|
||||
new Keyframe(0f, 0f, 0f, 0f),
|
||||
new Keyframe(0.3f, 0.1f, 0f, 2f),
|
||||
@@ -39,10 +35,7 @@ public class ScarecrowFire : MonoBehaviour
|
||||
);
|
||||
|
||||
[Header("Post Process")]
|
||||
[Tooltip("Volume driving the heat haze effect — weight is driven up as fire spreads.")]
|
||||
[SerializeField] private Volume _heatVolume;
|
||||
|
||||
[Tooltip("Curve driving all heat effects over the full sequence duration.")]
|
||||
[SerializeField] private AnimationCurve _heatCurve = new AnimationCurve(
|
||||
new Keyframe(0f, 0f, 0f, 0.5f),
|
||||
new Keyframe(0.5f, 0.4f, 1f, 1f),
|
||||
@@ -50,17 +43,18 @@ public class ScarecrowFire : MonoBehaviour
|
||||
);
|
||||
|
||||
[Header("Heat Shader")]
|
||||
[Tooltip("Material using the HeatHaze shader — _Weight property is driven from 0 to 1.")]
|
||||
[SerializeField] private Material _heatMaterial;
|
||||
|
||||
[Header("Light")]
|
||||
[Tooltip("LightFlicker component to drive — baseIntensity is ramped up with the fire.")]
|
||||
[SerializeField] private MonoLimboStudio.LightFlicker _lightFlicker;
|
||||
[Header("Lights")]
|
||||
[SerializeField] private List<LightEntry> _lights = new List<LightEntry>();
|
||||
|
||||
[Tooltip("Final light intensity reached when the fire is fully ablaze.")]
|
||||
[SerializeField] private float _targetLightIntensity = 3f;
|
||||
[System.Serializable]
|
||||
public class LightEntry
|
||||
{
|
||||
public LightFlicker Flicker;
|
||||
public float TargetIntensity = 3f;
|
||||
}
|
||||
|
||||
// Flag set when the last GrowFire completes — DriveHeatEffects waits on this
|
||||
private bool _fireSequenceComplete = false;
|
||||
private float _totalSequenceDuration = 0f;
|
||||
|
||||
@@ -77,16 +71,13 @@ public class ScarecrowFire : MonoBehaviour
|
||||
InitElement(_fireHead);
|
||||
InitElement(_fireBig);
|
||||
|
||||
// Used as a time reference for _heatCurve mapping — doesn't need to be exact
|
||||
// since DriveHeatEffects now syncs to _fireSequenceComplete rather than this value
|
||||
float overlapDelay = _growDuration * (1f - _overlapFactor);
|
||||
_totalSequenceDuration = _growDuration + (7f * overlapDelay);
|
||||
|
||||
// Ensure everything starts at zero
|
||||
SetHeatShaderWeight(0f);
|
||||
|
||||
if (_lightFlicker)
|
||||
_lightFlicker.SetBaseIntensity(0f);
|
||||
foreach (var entry in _lights)
|
||||
if (entry.Flicker) entry.Flicker.SetBaseIntensity(0f);
|
||||
}
|
||||
|
||||
void Start()
|
||||
@@ -94,10 +85,6 @@ public class ScarecrowFire : MonoBehaviour
|
||||
TriggerFire();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Captures the original Inspector scale, then sets the starting scale to
|
||||
/// (x * 0.2, y * 0.1, z * 0.2) so each element grows from near-nothing.
|
||||
/// </summary>
|
||||
private void InitElement(FireElement el)
|
||||
{
|
||||
if (!el.VFX) return;
|
||||
@@ -113,51 +100,36 @@ public class ScarecrowFire : MonoBehaviour
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/// <summary>Starts the full fire propagation sequence.</summary>
|
||||
public void TriggerFire()
|
||||
{
|
||||
_fireSequenceComplete = false;
|
||||
StartCoroutine(FireSequence());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Propagates fire bottom-up with overlapping stages for an organic feel.
|
||||
/// Sets _fireSequenceComplete when the last element finishes growing.
|
||||
/// </summary>
|
||||
private IEnumerator FireSequence()
|
||||
{
|
||||
float overlapDelay = _growDuration * (1f - _overlapFactor);
|
||||
|
||||
// Drive all heat effects independently — syncs via _fireSequenceComplete
|
||||
StartCoroutine(DriveHeatEffects());
|
||||
|
||||
// Feet
|
||||
StartCoroutine(GrowFire(_fireBase));
|
||||
yield return new WaitForSeconds(overlapDelay);
|
||||
|
||||
// Torso overlaps with feet still growing
|
||||
StartCoroutine(GrowFire(_fireTorso));
|
||||
yield return new WaitForSeconds(overlapDelay);
|
||||
|
||||
// Both arms ignite simultaneously, each propagating from shoulder to tip
|
||||
StartCoroutine(PropagateArm(_fireArmLeft, _fireArmLeftEnd, overlapDelay));
|
||||
StartCoroutine(PropagateArm(_fireArmRight, _fireArmRightEnd, overlapDelay));
|
||||
yield return new WaitForSeconds(overlapDelay * 2f);
|
||||
|
||||
// Head
|
||||
StartCoroutine(GrowFire(_fireHead));
|
||||
yield return new WaitForSeconds(overlapDelay);
|
||||
|
||||
// Full blaze — wait for it to fully complete before flagging done
|
||||
yield return StartCoroutine(GrowFire(_fireBig));
|
||||
|
||||
_fireSequenceComplete = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Propagates fire along one arm: shoulder ignites first,
|
||||
/// then tip starts after overlapDelay rather than waiting for shoulder to finish.
|
||||
/// </summary>
|
||||
private IEnumerator PropagateArm(FireElement shoulder, FireElement tip, float overlapDelay)
|
||||
{
|
||||
StartCoroutine(GrowFire(shoulder));
|
||||
@@ -165,10 +137,6 @@ public class ScarecrowFire : MonoBehaviour
|
||||
yield return StartCoroutine(GrowFire(tip));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Activates a fire element and lerps its scale from near-zero to its original
|
||||
/// Inspector scale, driven by _growCurve for an organic progression.
|
||||
/// </summary>
|
||||
private IEnumerator GrowFire(FireElement el)
|
||||
{
|
||||
if (!el.VFX) yield break;
|
||||
@@ -195,57 +163,54 @@ public class ScarecrowFire : MonoBehaviour
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/// <summary>
|
||||
/// Drives all heat effects (post-process volume, heat shader, light intensity)
|
||||
/// using _heatCurve until _fireSequenceComplete is set, then snaps cleanly to 1.
|
||||
/// Decoupled from individual fire element timing for smoother blending.
|
||||
/// </summary>
|
||||
private IEnumerator DriveHeatEffects()
|
||||
{
|
||||
float elapsed = 0f;
|
||||
float elapsed = 0f;
|
||||
float lastWeight = 0f;
|
||||
|
||||
// Phase 1 : monte avec la heatCurve jusqu'à ce que la séquence feu soit finie.
|
||||
// On snapshote lastWeight à chaque frame pour partir de la vraie valeur courante
|
||||
// en phase 2, évitant tout creux si la courbe redescend après t=1.
|
||||
while (!_fireSequenceComplete)
|
||||
{
|
||||
elapsed += Time.deltaTime;
|
||||
float t = elapsed / _totalSequenceDuration;
|
||||
float weight = _heatCurve.Evaluate(Mathf.Min(t, 0.99f));
|
||||
|
||||
if (_heatVolume)
|
||||
_heatVolume.weight = weight;
|
||||
|
||||
SetHeatShaderWeight(weight);
|
||||
|
||||
if (_lightFlicker)
|
||||
_lightFlicker.SetBaseIntensity(_targetLightIntensity * weight);
|
||||
float t = elapsed / _totalSequenceDuration;
|
||||
lastWeight = _heatCurve.Evaluate(Mathf.Clamp01(t));
|
||||
|
||||
ApplyHeatWeight(lastWeight);
|
||||
yield return null;
|
||||
}
|
||||
|
||||
float lerpElapsed = 0f;
|
||||
// Phase 2 : lerp propre de la valeur courante vers 1, sans jamais redescendre.
|
||||
float lerpElapsed = 0f;
|
||||
float lerpDuration = 8f;
|
||||
float startWeight = _heatCurve.Evaluate(0.99f);
|
||||
float startWeight = lastWeight; // ← valeur réelle au moment du flag, pas heatCurve(0.99)
|
||||
|
||||
while (lerpElapsed < lerpDuration)
|
||||
{
|
||||
lerpElapsed += Time.deltaTime;
|
||||
float weight = Mathf.Lerp(startWeight, 1f, lerpElapsed / lerpDuration);
|
||||
|
||||
if (_heatVolume) _heatVolume.weight = weight;
|
||||
SetHeatShaderWeight(weight);
|
||||
if (_lightFlicker) _lightFlicker.SetBaseIntensity(_targetLightIntensity * weight);
|
||||
|
||||
ApplyHeatWeight(weight);
|
||||
yield return null;
|
||||
}
|
||||
|
||||
if (_heatVolume) _heatVolume.weight = 1f;
|
||||
SetHeatShaderWeight(1f);
|
||||
if (_lightFlicker) _lightFlicker.SetBaseIntensity(_targetLightIntensity);
|
||||
// Phase 3 : maintien à 1 à l'infini.
|
||||
ApplyHeatWeight(1f);
|
||||
}
|
||||
|
||||
/// <summary>Applique un weight normalisé à tous les effets de chaleur + lumière.</summary>
|
||||
private void ApplyHeatWeight(float weight)
|
||||
{
|
||||
if (_heatVolume) _heatVolume.weight = weight;
|
||||
SetHeatShaderWeight(weight);
|
||||
|
||||
// ScarecrowFire pilote la base — LightFlicker applique le flicker par-dessus
|
||||
// sans écrire directement sur targetLight.intensity.
|
||||
foreach (var entry in _lights)
|
||||
if (entry.Flicker) entry.Flicker.SetBaseIntensity(entry.TargetIntensity * weight);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Drives the heat shader via a single normalized weight (0-1).
|
||||
/// All visual parameters are tweaked directly on the material in the Inspector.
|
||||
/// </summary>
|
||||
private void SetHeatShaderWeight(float weight)
|
||||
{
|
||||
if (!_heatMaterial) return;
|
||||
|
||||
Reference in New Issue
Block a user