Initial Unity project commit
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 87b0237d37823604c954ae75810ace37
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,173 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEditor.SceneManagement;
|
||||
using UnityEngine;
|
||||
using Test_2022.LightsControl;
|
||||
|
||||
[CustomEditor(typeof(LightsControlController))]
|
||||
[CanEditMultipleObjects]
|
||||
public sealed class LightsControlControllerEditor : Editor
|
||||
{
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
DrawDefaultInspector();
|
||||
|
||||
EditorGUILayout.Space(10);
|
||||
|
||||
using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox))
|
||||
{
|
||||
EditorGUILayout.LabelField("Tools", EditorStyles.boldLabel);
|
||||
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
if (GUILayout.Button("Add Selected"))
|
||||
AddSelectedLights(false);
|
||||
|
||||
if (GUILayout.Button("Add Selected (+Children)"))
|
||||
AddSelectedLights(true);
|
||||
}
|
||||
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
if (GUILayout.Button("Find All (Clear)"))
|
||||
FindAll(true);
|
||||
|
||||
if (GUILayout.Button("Find All (Append)"))
|
||||
FindAll(false);
|
||||
}
|
||||
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
if (GUILayout.Button("Remove Nulls"))
|
||||
RemoveNulls();
|
||||
|
||||
if (GUILayout.Button("Clear List"))
|
||||
ClearList();
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.Space(10);
|
||||
|
||||
using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox))
|
||||
{
|
||||
EditorGUILayout.LabelField("Runtime", EditorStyles.boldLabel);
|
||||
|
||||
if (!Application.isPlaying)
|
||||
EditorGUILayout.HelpBox("进入 Play 模式后才会执行闪烁/定时协程。也可以在组件上启用 Auto Start On Enable 自动开始。", MessageType.Info);
|
||||
|
||||
using (new EditorGUI.DisabledScope(!Application.isPlaying))
|
||||
{
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
if (GUILayout.Button("Start"))
|
||||
StartControl();
|
||||
|
||||
if (GUILayout.Button("Stop (Restore)"))
|
||||
StopControl(true);
|
||||
|
||||
if (GUILayout.Button("Stop (No Restore)"))
|
||||
StopControl(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AddSelectedLights(bool includeChildren)
|
||||
{
|
||||
var selected = Selection.gameObjects;
|
||||
if (selected == null || selected.Length == 0)
|
||||
return;
|
||||
|
||||
var toAdd = new List<Light>();
|
||||
for (var i = 0; i < selected.Length; i++)
|
||||
{
|
||||
var go = selected[i];
|
||||
if (go == null)
|
||||
continue;
|
||||
|
||||
if (includeChildren)
|
||||
toAdd.AddRange(go.GetComponentsInChildren<Light>(true));
|
||||
else
|
||||
{
|
||||
var l = go.GetComponent<Light>();
|
||||
if (l != null)
|
||||
toAdd.Add(l);
|
||||
}
|
||||
}
|
||||
|
||||
if (toAdd.Count == 0)
|
||||
return;
|
||||
|
||||
foreach (var t in targets)
|
||||
{
|
||||
var c = (LightsControlController)t;
|
||||
Undo.RecordObject(c, "Add Lights");
|
||||
c.AddLights(toAdd);
|
||||
EditorUtility.SetDirty(c);
|
||||
MarkSceneDirty(c);
|
||||
}
|
||||
}
|
||||
|
||||
void FindAll(bool clearFirst)
|
||||
{
|
||||
foreach (var t in targets)
|
||||
{
|
||||
var c = (LightsControlController)t;
|
||||
Undo.RecordObject(c, "Find Lights In Scene");
|
||||
c.FindAllLightsInScene(clearFirst);
|
||||
EditorUtility.SetDirty(c);
|
||||
MarkSceneDirty(c);
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveNulls()
|
||||
{
|
||||
foreach (var t in targets)
|
||||
{
|
||||
var c = (LightsControlController)t;
|
||||
Undo.RecordObject(c, "Remove Null Lights");
|
||||
c.RemoveNullLights();
|
||||
EditorUtility.SetDirty(c);
|
||||
MarkSceneDirty(c);
|
||||
}
|
||||
}
|
||||
|
||||
void ClearList()
|
||||
{
|
||||
foreach (var t in targets)
|
||||
{
|
||||
var c = (LightsControlController)t;
|
||||
Undo.RecordObject(c, "Clear Lights");
|
||||
c.ClearLights();
|
||||
EditorUtility.SetDirty(c);
|
||||
MarkSceneDirty(c);
|
||||
}
|
||||
}
|
||||
|
||||
void StartControl()
|
||||
{
|
||||
foreach (var t in targets)
|
||||
{
|
||||
var c = (LightsControlController)t;
|
||||
c.StartControl();
|
||||
}
|
||||
}
|
||||
|
||||
void StopControl(bool restoreBaseState)
|
||||
{
|
||||
foreach (var t in targets)
|
||||
{
|
||||
var c = (LightsControlController)t;
|
||||
c.StopControl(restoreBaseState);
|
||||
}
|
||||
}
|
||||
|
||||
static void MarkSceneDirty(LightsControlController c)
|
||||
{
|
||||
if (Application.isPlaying)
|
||||
return;
|
||||
if (!c.gameObject.scene.IsValid())
|
||||
return;
|
||||
EditorSceneManager.MarkSceneDirty(c.gameObject.scene);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1896a40637d32a44f80533164ded9c8c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,576 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Test_2022.LightsControl
|
||||
{
|
||||
[DisallowMultipleComponent]
|
||||
public sealed class LightsControlController : MonoBehaviour
|
||||
{
|
||||
public enum ControlMode
|
||||
{
|
||||
Manual = 0,
|
||||
TimedToggle = 1,
|
||||
HorrorFlicker = 2
|
||||
}
|
||||
|
||||
public enum TimedToggleMode
|
||||
{
|
||||
FixedOnOffDurations = 0,
|
||||
DurationAndToggleCount = 1
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public struct TimedToggleSettings
|
||||
{
|
||||
public TimedToggleMode mode;
|
||||
|
||||
public bool startOn;
|
||||
public bool endOn;
|
||||
public bool loop;
|
||||
|
||||
public float onSeconds;
|
||||
public float offSeconds;
|
||||
public int cycles;
|
||||
|
||||
public float durationSeconds;
|
||||
public int toggleCount;
|
||||
[Range(0f, 1f)] public float jitter;
|
||||
|
||||
public static TimedToggleSettings Default => new TimedToggleSettings
|
||||
{
|
||||
mode = TimedToggleMode.FixedOnOffDurations,
|
||||
startOn = true,
|
||||
endOn = true,
|
||||
loop = false,
|
||||
onSeconds = 0.15f,
|
||||
offSeconds = 0.12f,
|
||||
cycles = 8,
|
||||
durationSeconds = 2f,
|
||||
toggleCount = 10,
|
||||
jitter = 0.1f
|
||||
};
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public struct HorrorFlickerSettings
|
||||
{
|
||||
public bool startOn;
|
||||
public bool endOn;
|
||||
public bool loop;
|
||||
public float durationSeconds;
|
||||
|
||||
public bool affectIntensity;
|
||||
[Min(0f)] public float intensityMinMultiplier;
|
||||
[Min(0f)] public float intensityMaxMultiplier;
|
||||
[Min(0f)] public float subtleNoiseSpeed;
|
||||
[Range(0f, 1f)] public float subtleNoiseStrength;
|
||||
|
||||
[Min(0f)] public float steadyOnMinSeconds;
|
||||
[Min(0f)] public float steadyOnMaxSeconds;
|
||||
|
||||
[Min(0f)] public float offBlipMinSeconds;
|
||||
[Min(0f)] public float offBlipMaxSeconds;
|
||||
|
||||
[Min(0f)] public float blackoutMinSeconds;
|
||||
[Min(0f)] public float blackoutMaxSeconds;
|
||||
[Range(0f, 1f)] public float blackoutChance;
|
||||
|
||||
[Min(0)] public int burstToggleMin;
|
||||
[Min(0)] public int burstToggleMax;
|
||||
[Min(0f)] public float burstIntervalMinSeconds;
|
||||
[Min(0f)] public float burstIntervalMaxSeconds;
|
||||
|
||||
[Range(0f, 1f)] public float steadyWeight;
|
||||
[Range(0f, 1f)] public float offBlipWeight;
|
||||
[Range(0f, 1f)] public float burstWeight;
|
||||
|
||||
public bool useFixedSeed;
|
||||
public int seed;
|
||||
|
||||
public static HorrorFlickerSettings Default => new HorrorFlickerSettings
|
||||
{
|
||||
startOn = true,
|
||||
endOn = true,
|
||||
loop = false,
|
||||
durationSeconds = 6f,
|
||||
affectIntensity = true,
|
||||
intensityMinMultiplier = 0.6f,
|
||||
intensityMaxMultiplier = 1.05f,
|
||||
subtleNoiseSpeed = 1.2f,
|
||||
subtleNoiseStrength = 0.35f,
|
||||
steadyOnMinSeconds = 0.35f,
|
||||
steadyOnMaxSeconds = 1.25f,
|
||||
offBlipMinSeconds = 0.03f,
|
||||
offBlipMaxSeconds = 0.18f,
|
||||
blackoutMinSeconds = 0.25f,
|
||||
blackoutMaxSeconds = 1.2f,
|
||||
blackoutChance = 0.06f,
|
||||
burstToggleMin = 4,
|
||||
burstToggleMax = 14,
|
||||
burstIntervalMinSeconds = 0.02f,
|
||||
burstIntervalMaxSeconds = 0.11f,
|
||||
steadyWeight = 0.55f,
|
||||
offBlipWeight = 0.25f,
|
||||
burstWeight = 0.20f,
|
||||
useFixedSeed = false,
|
||||
seed = 12345
|
||||
};
|
||||
}
|
||||
|
||||
[Header("Lights")]
|
||||
[SerializeField] List<Light> lights = new List<Light>();
|
||||
[SerializeField] bool includeInactiveWhenSearching = true;
|
||||
|
||||
[Header("Control")]
|
||||
[SerializeField] ControlMode mode = ControlMode.Manual;
|
||||
[SerializeField] bool manualOn = true;
|
||||
[SerializeField] bool autoStartOnEnable = true;
|
||||
[SerializeField] bool restoreBaseStateOnDisable = true;
|
||||
[SerializeField] TimedToggleSettings timedToggle = TimedToggleSettings.Default;
|
||||
[SerializeField] HorrorFlickerSettings horrorFlicker = HorrorFlickerSettings.Default;
|
||||
|
||||
Coroutine running;
|
||||
readonly List<Light> cachedLights = new List<Light>();
|
||||
readonly List<bool> cachedEnabled = new List<bool>();
|
||||
readonly List<float> cachedIntensity = new List<float>();
|
||||
|
||||
public ControlMode Mode
|
||||
{
|
||||
get => mode;
|
||||
set => mode = value;
|
||||
}
|
||||
|
||||
public bool ManualOn
|
||||
{
|
||||
get => manualOn;
|
||||
set => manualOn = value;
|
||||
}
|
||||
|
||||
public bool AutoStartOnEnable
|
||||
{
|
||||
get => autoStartOnEnable;
|
||||
set => autoStartOnEnable = value;
|
||||
}
|
||||
|
||||
public IList<Light> Lights => lights;
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
if (!autoStartOnEnable)
|
||||
{
|
||||
if (mode == ControlMode.Manual)
|
||||
ApplyManual();
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode == ControlMode.Manual)
|
||||
ApplyManual();
|
||||
else
|
||||
StartControl();
|
||||
}
|
||||
|
||||
void OnDisable()
|
||||
{
|
||||
StopControl(restoreBaseStateOnDisable);
|
||||
}
|
||||
|
||||
public void ApplyManual()
|
||||
{
|
||||
StopControl(true);
|
||||
SetAllEnabled(manualOn);
|
||||
}
|
||||
|
||||
public void ForceOn()
|
||||
{
|
||||
StopControl(false);
|
||||
SetAllEnabled(true);
|
||||
}
|
||||
|
||||
public void ForceOff()
|
||||
{
|
||||
StopControl(false);
|
||||
SetAllEnabled(false);
|
||||
}
|
||||
|
||||
public void StartControl()
|
||||
{
|
||||
StopControl(false);
|
||||
CacheBaseState();
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case ControlMode.Manual:
|
||||
ApplyManual();
|
||||
return;
|
||||
case ControlMode.TimedToggle:
|
||||
running = StartCoroutine(RunTimedToggle(timedToggle));
|
||||
return;
|
||||
case ControlMode.HorrorFlicker:
|
||||
running = StartCoroutine(RunHorrorFlicker(horrorFlicker));
|
||||
return;
|
||||
default:
|
||||
ApplyManual();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void StopControl(bool restoreBaseState)
|
||||
{
|
||||
if (running != null)
|
||||
{
|
||||
StopCoroutine(running);
|
||||
running = null;
|
||||
}
|
||||
|
||||
if (restoreBaseState)
|
||||
RestoreBaseState();
|
||||
}
|
||||
|
||||
public void SetAllEnabled(bool enabled)
|
||||
{
|
||||
for (var i = 0; i < lights.Count; i++)
|
||||
{
|
||||
var l = lights[i];
|
||||
if (l == null)
|
||||
continue;
|
||||
l.enabled = enabled;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetAllIntensityMultiplier(float multiplier)
|
||||
{
|
||||
if (cachedLights.Count == 0)
|
||||
CacheBaseState();
|
||||
|
||||
for (var i = 0; i < cachedLights.Count; i++)
|
||||
{
|
||||
var l = cachedLights[i];
|
||||
if (l == null)
|
||||
continue;
|
||||
l.intensity = cachedIntensity[i] * multiplier;
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearLights()
|
||||
{
|
||||
lights.Clear();
|
||||
}
|
||||
|
||||
public bool AddLight(Light light)
|
||||
{
|
||||
if (light == null)
|
||||
return false;
|
||||
if (lights.Contains(light))
|
||||
return false;
|
||||
lights.Add(light);
|
||||
return true;
|
||||
}
|
||||
|
||||
public int AddLights(IEnumerable<Light> addLights)
|
||||
{
|
||||
if (addLights == null)
|
||||
return 0;
|
||||
|
||||
var added = 0;
|
||||
foreach (var l in addLights)
|
||||
{
|
||||
if (l == null)
|
||||
continue;
|
||||
if (lights.Contains(l))
|
||||
continue;
|
||||
lights.Add(l);
|
||||
added++;
|
||||
}
|
||||
return added;
|
||||
}
|
||||
|
||||
public int RemoveNullLights()
|
||||
{
|
||||
return lights.RemoveAll(l => l == null);
|
||||
}
|
||||
|
||||
public int FindAllLightsInScene(bool clearFirst, Transform root = null)
|
||||
{
|
||||
Light[] found;
|
||||
#if UNITY_2022_2_OR_NEWER
|
||||
found = UnityEngine.Object.FindObjectsByType<Light>(
|
||||
includeInactiveWhenSearching ? FindObjectsInactive.Include : FindObjectsInactive.Exclude,
|
||||
FindObjectsSortMode.None
|
||||
);
|
||||
#else
|
||||
found = UnityEngine.Object.FindObjectsOfType<Light>(includeInactiveWhenSearching);
|
||||
#endif
|
||||
|
||||
if (clearFirst)
|
||||
lights.Clear();
|
||||
|
||||
var added = 0;
|
||||
for (var i = 0; i < found.Length; i++)
|
||||
{
|
||||
var l = found[i];
|
||||
if (l == null)
|
||||
continue;
|
||||
if (root != null && !l.transform.IsChildOf(root))
|
||||
continue;
|
||||
if (lights.Contains(l))
|
||||
continue;
|
||||
lights.Add(l);
|
||||
added++;
|
||||
}
|
||||
|
||||
return added;
|
||||
}
|
||||
|
||||
void CacheBaseState()
|
||||
{
|
||||
cachedLights.Clear();
|
||||
cachedEnabled.Clear();
|
||||
cachedIntensity.Clear();
|
||||
|
||||
var seen = new HashSet<Light>();
|
||||
for (var i = 0; i < lights.Count; i++)
|
||||
{
|
||||
var l = lights[i];
|
||||
if (l == null)
|
||||
continue;
|
||||
if (!seen.Add(l))
|
||||
continue;
|
||||
cachedLights.Add(l);
|
||||
cachedEnabled.Add(l.enabled);
|
||||
cachedIntensity.Add(l.intensity);
|
||||
}
|
||||
}
|
||||
|
||||
void RestoreBaseState()
|
||||
{
|
||||
for (var i = 0; i < cachedLights.Count; i++)
|
||||
{
|
||||
var l = cachedLights[i];
|
||||
if (l == null)
|
||||
continue;
|
||||
l.enabled = cachedEnabled[i];
|
||||
l.intensity = cachedIntensity[i];
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator RunTimedToggle(TimedToggleSettings s)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (lights.Count == 0)
|
||||
yield break;
|
||||
|
||||
SetAllEnabled(s.startOn);
|
||||
|
||||
if (s.mode == TimedToggleMode.FixedOnOffDurations)
|
||||
{
|
||||
var cycles = Mathf.Max(0, s.cycles);
|
||||
for (var i = 0; i < cycles; i++)
|
||||
{
|
||||
if (s.startOn)
|
||||
yield return WaitOrBreak(Mathf.Max(0f, s.onSeconds));
|
||||
else
|
||||
yield return WaitOrBreak(Mathf.Max(0f, s.offSeconds));
|
||||
|
||||
SetAllEnabled(!s.startOn);
|
||||
|
||||
if (s.startOn)
|
||||
yield return WaitOrBreak(Mathf.Max(0f, s.offSeconds));
|
||||
else
|
||||
yield return WaitOrBreak(Mathf.Max(0f, s.onSeconds));
|
||||
|
||||
SetAllEnabled(s.startOn);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var count = Mathf.Max(0, s.toggleCount);
|
||||
if (count <= 0)
|
||||
yield break;
|
||||
|
||||
var baseInterval = Mathf.Max(0f, s.durationSeconds) / count;
|
||||
var current = s.startOn;
|
||||
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
var interval = baseInterval;
|
||||
if (s.jitter > 0f)
|
||||
{
|
||||
var j = Mathf.Clamp01(s.jitter);
|
||||
interval *= UnityEngine.Random.Range(1f - j, 1f + j);
|
||||
}
|
||||
yield return WaitOrBreak(interval);
|
||||
current = !current;
|
||||
SetAllEnabled(current);
|
||||
}
|
||||
}
|
||||
|
||||
SetAllEnabled(s.endOn);
|
||||
} while (s.loop);
|
||||
}
|
||||
|
||||
IEnumerator WaitOrBreak(float seconds)
|
||||
{
|
||||
if (seconds <= 0f)
|
||||
yield break;
|
||||
yield return new WaitForSeconds(seconds);
|
||||
}
|
||||
|
||||
IEnumerator RunHorrorFlicker(HorrorFlickerSettings s)
|
||||
{
|
||||
var previousRandomState = UnityEngine.Random.state;
|
||||
if (s.useFixedSeed)
|
||||
UnityEngine.Random.InitState(s.seed);
|
||||
|
||||
try
|
||||
{
|
||||
do
|
||||
{
|
||||
if (lights.Count == 0)
|
||||
yield break;
|
||||
|
||||
SetAllEnabled(s.startOn);
|
||||
|
||||
var untilTime = s.durationSeconds > 0f ? Time.unscaledTime + s.durationSeconds : float.PositiveInfinity;
|
||||
var on = s.startOn;
|
||||
|
||||
while (Time.unscaledTime < untilTime)
|
||||
{
|
||||
var wSteady = Mathf.Max(0f, s.steadyWeight);
|
||||
var wOff = Mathf.Max(0f, s.offBlipWeight);
|
||||
var wBurst = Mathf.Max(0f, s.burstWeight);
|
||||
var wTotal = wSteady + wOff + wBurst;
|
||||
if (wTotal <= 0f)
|
||||
wTotal = 1f;
|
||||
|
||||
var pick = UnityEngine.Random.value * wTotal;
|
||||
if (pick < wSteady)
|
||||
{
|
||||
var seg = UnityEngine.Random.Range(
|
||||
Mathf.Max(0f, s.steadyOnMinSeconds),
|
||||
Mathf.Max(0f, s.steadyOnMaxSeconds)
|
||||
);
|
||||
|
||||
if (!on)
|
||||
{
|
||||
on = true;
|
||||
SetAllEnabled(true);
|
||||
}
|
||||
|
||||
var end = Time.unscaledTime + seg;
|
||||
while (Time.unscaledTime < end && Time.unscaledTime < untilTime)
|
||||
{
|
||||
ApplySubtleIntensityNoise(s);
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
else if (pick < wSteady + wOff)
|
||||
{
|
||||
if (UnityEngine.Random.value < Mathf.Clamp01(s.blackoutChance))
|
||||
{
|
||||
if (on)
|
||||
{
|
||||
on = false;
|
||||
SetAllEnabled(false);
|
||||
}
|
||||
|
||||
var blackout = UnityEngine.Random.Range(
|
||||
Mathf.Max(0f, s.blackoutMinSeconds),
|
||||
Mathf.Max(0f, s.blackoutMaxSeconds)
|
||||
);
|
||||
yield return WaitOrBreak(Mathf.Min(blackout, untilTime - Time.unscaledTime));
|
||||
|
||||
if (Time.unscaledTime < untilTime)
|
||||
{
|
||||
on = true;
|
||||
SetAllEnabled(true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (on)
|
||||
{
|
||||
on = false;
|
||||
SetAllEnabled(false);
|
||||
}
|
||||
|
||||
var off = UnityEngine.Random.Range(
|
||||
Mathf.Max(0f, s.offBlipMinSeconds),
|
||||
Mathf.Max(0f, s.offBlipMaxSeconds)
|
||||
);
|
||||
yield return WaitOrBreak(Mathf.Min(off, untilTime - Time.unscaledTime));
|
||||
|
||||
if (Time.unscaledTime < untilTime)
|
||||
{
|
||||
on = true;
|
||||
SetAllEnabled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var minT = Mathf.Max(0, s.burstToggleMin);
|
||||
var maxT = Mathf.Max(minT, s.burstToggleMax);
|
||||
var toggles = UnityEngine.Random.Range(minT, maxT + 1);
|
||||
|
||||
for (var i = 0; i < toggles && Time.unscaledTime < untilTime; i++)
|
||||
{
|
||||
on = !on;
|
||||
SetAllEnabled(on);
|
||||
ApplySubtleIntensityNoise(s);
|
||||
|
||||
var interval = UnityEngine.Random.Range(
|
||||
Mathf.Max(0f, s.burstIntervalMinSeconds),
|
||||
Mathf.Max(0f, s.burstIntervalMaxSeconds)
|
||||
);
|
||||
yield return WaitOrBreak(Mathf.Min(interval, untilTime - Time.unscaledTime));
|
||||
}
|
||||
|
||||
if (Time.unscaledTime < untilTime)
|
||||
{
|
||||
on = true;
|
||||
SetAllEnabled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SetAllEnabled(s.endOn);
|
||||
} while (s.loop);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (s.useFixedSeed)
|
||||
UnityEngine.Random.state = previousRandomState;
|
||||
}
|
||||
}
|
||||
|
||||
void ApplySubtleIntensityNoise(HorrorFlickerSettings s)
|
||||
{
|
||||
if (!s.affectIntensity)
|
||||
return;
|
||||
|
||||
if (cachedLights.Count == 0)
|
||||
CacheBaseState();
|
||||
|
||||
var min = Mathf.Max(0f, s.intensityMinMultiplier);
|
||||
var max = Mathf.Max(min, s.intensityMaxMultiplier);
|
||||
|
||||
var t = Time.unscaledTime * Mathf.Max(0f, s.subtleNoiseSpeed);
|
||||
var strength = Mathf.Clamp01(s.subtleNoiseStrength);
|
||||
|
||||
for (var i = 0; i < cachedLights.Count; i++)
|
||||
{
|
||||
var l = cachedLights[i];
|
||||
if (l == null)
|
||||
continue;
|
||||
|
||||
var n = Mathf.PerlinNoise((s.seed * 0.001f) + i * 13.37f, t);
|
||||
var target = Mathf.Lerp(min, max, n);
|
||||
var blended = Mathf.Lerp(1f, target, strength);
|
||||
l.intensity = cachedIntensity[i] * blended;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 32051ea4816da8d4c8bfab3f72f112b7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user