79 lines
2.8 KiB
C#
79 lines
2.8 KiB
C#
using UnityEngine;
|
|
|
|
/// <summary>
|
|
/// Old film projector feel for the credits projected on the theatre screen: the projector light,
|
|
/// the projected image and the light rays share the same subtle brightness flicker, with rare
|
|
/// short dips like a skipping film.
|
|
/// </summary>
|
|
public class CreditsProjector : MonoBehaviour
|
|
{
|
|
[SerializeField] private Light _light;
|
|
[SerializeField] private CanvasGroup _image;
|
|
[SerializeField] private Renderer[] _rays;
|
|
|
|
[Tooltip("Continuous brightness variation (0 = steady)")]
|
|
[SerializeField, Range(0f, 1f)] private float _flickerAmount = .08f;
|
|
[SerializeField, Min(0f)] private float _flickerSpeed = 7f;
|
|
|
|
[Tooltip("Average number of short brightness dips per second")]
|
|
[SerializeField, Min(0f)] private float _dipsPerSecond = .3f;
|
|
[SerializeField, Range(0f, 1f)] private float _dipAmount = .25f;
|
|
[SerializeField, Min(0f)] private float _dipDuration = .06f;
|
|
|
|
[Tooltip("How much of the flicker reaches the projected image (the light and rays get all of it)")]
|
|
[SerializeField, Range(0f, 1f)] private float _imageFlicker = .5f;
|
|
|
|
private static readonly int ColorId = Shader.PropertyToID("_Color");
|
|
|
|
private float _baseIntensity;
|
|
private float _baseAlpha;
|
|
private Color[] _baseRayColors;
|
|
private MaterialPropertyBlock _block;
|
|
private float _dipTimer;
|
|
private float _seed;
|
|
|
|
private void Awake()
|
|
{
|
|
_seed = Random.Range(0f, 100f);
|
|
_block = new MaterialPropertyBlock();
|
|
|
|
if (_light) _baseIntensity = _light.intensity;
|
|
if (_image) _baseAlpha = _image.alpha;
|
|
|
|
_baseRayColors = new Color[_rays.Length];
|
|
for (int i = 0; i < _rays.Length; i++)
|
|
_baseRayColors[i] = _rays[i] && _rays[i].sharedMaterial ? _rays[i].sharedMaterial.GetColor(ColorId) : Color.white;
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
float noise = Mathf.PerlinNoise(Time.time * _flickerSpeed, _seed);
|
|
float brightness = 1f - _flickerAmount * noise;
|
|
|
|
if (_dipTimer > 0f)
|
|
_dipTimer -= Time.deltaTime;
|
|
else if (Random.value < _dipsPerSecond * Time.deltaTime)
|
|
_dipTimer = _dipDuration;
|
|
|
|
if (_dipTimer > 0f)
|
|
brightness *= 1f - _dipAmount;
|
|
|
|
if (_light)
|
|
_light.intensity = _baseIntensity * brightness;
|
|
|
|
if (_image)
|
|
_image.alpha = _baseAlpha * Mathf.Lerp(1f, brightness, _imageFlicker);
|
|
|
|
for (int i = 0; i < _rays.Length; i++)
|
|
{
|
|
if (!_rays[i])
|
|
continue;
|
|
|
|
_rays[i].GetPropertyBlock(_block);
|
|
Color color = _baseRayColors[i];
|
|
_block.SetColor(ColorId, new Color(color.r * brightness, color.g * brightness, color.b * brightness, color.a));
|
|
_rays[i].SetPropertyBlock(_block);
|
|
}
|
|
}
|
|
}
|