WIP : Props placement and lighting test
This commit is contained in:
@@ -14,6 +14,8 @@ namespace Unheimlich.Features.Dialogue.UI
|
||||
/// so the HallucinationManager can drive baseline behaviour without FindObjectsOfType.
|
||||
/// - Exposes SetShakeParams() and SetGhostTrail() for runtime overrides.
|
||||
/// - ApplyBaseline() / ApplyOverride() drive the two-layer system.
|
||||
/// - One-shot trigger distance is now explicit and independent from the visual near-fade.
|
||||
/// - One-shot fade-out runs independently from the distance-based alpha so it is never overwritten.
|
||||
/// </summary>
|
||||
public class FloatingLabel : MonoBehaviour
|
||||
{
|
||||
@@ -59,8 +61,14 @@ namespace Unheimlich.Features.Dialogue.UI
|
||||
[SerializeField] private float _attractionSmoothness = 4f;
|
||||
|
||||
[Header("One-Shot (Optional)")]
|
||||
[SerializeField] private bool _enableOneShot = false;
|
||||
[SerializeField] [Range(0.01f, 1f)] private float _seenAlphaThreshold = 0.5f;
|
||||
[Tooltip("Enable one-shot behaviour: the label permanently disappears after the player gets close enough.")]
|
||||
[SerializeField] private bool _enableOneShot = false;
|
||||
[Tooltip("If true, the one-shot resets when the player walks far away (outside far-fade zone) without having triggered it.")]
|
||||
[SerializeField] private bool _isRetriggerableFar = false;
|
||||
[Tooltip("Distance at which the one-shot triggers, completely independent from the visual near-fade.")]
|
||||
[SerializeField] private float _oneShotTriggerDistance = 0.5f;
|
||||
[Tooltip("Duration of the fade-out once the one-shot is triggered.")]
|
||||
[SerializeField] private float _fadeOutDuration = 0.5f;
|
||||
|
||||
[Header("Reappear Fade")]
|
||||
[SerializeField] private float _fadeInDuration = 0.5f;
|
||||
@@ -71,7 +79,7 @@ namespace Unheimlich.Features.Dialogue.UI
|
||||
// ─── Runtime state ─────────────────────────────────────────────────────
|
||||
|
||||
private Camera _camera;
|
||||
private Vector3 _localHomePosition;
|
||||
private Vector3 _localHomePosition;
|
||||
private Vector3 _homePosition;
|
||||
private Vector3 _baseScale;
|
||||
|
||||
@@ -90,9 +98,9 @@ namespace Unheimlich.Features.Dialogue.UI
|
||||
private float _liveShakeSmoothness;
|
||||
|
||||
// Ghost trail — live values
|
||||
private bool _liveGhostEnabled;
|
||||
private float _liveGhostAlpha;
|
||||
private TextMeshPro _ghostText;
|
||||
private bool _liveGhostEnabled;
|
||||
private float _liveGhostAlpha;
|
||||
private TextMeshPro _ghostText;
|
||||
private Queue<Vector3> _positionHistory = new();
|
||||
private float _historyTimer;
|
||||
private const float HISTORY_SAMPLE_RATE = 0.016f;
|
||||
@@ -101,8 +109,14 @@ namespace Unheimlich.Features.Dialogue.UI
|
||||
private Vector3 _attractionOffset;
|
||||
|
||||
// One-shot
|
||||
private bool _hasBeenSeen;
|
||||
private bool _permanentlyHidden;
|
||||
private bool _hasBeenSeen;
|
||||
private bool _permanentlyHidden;
|
||||
private float _closestDistanceReached = float.MaxValue;
|
||||
|
||||
// One-shot fade-out — runs independently from the distance alpha
|
||||
private bool _isFadingOut = false;
|
||||
private float _fadeOutTimer = 0f;
|
||||
private float _fadeOutStartAlpha = 1f;
|
||||
|
||||
// Override coroutine
|
||||
private Coroutine _overrideCoroutine;
|
||||
@@ -132,14 +146,12 @@ namespace Unheimlich.Features.Dialogue.UI
|
||||
|
||||
private void Start()
|
||||
{
|
||||
_localHomePosition = transform.localPosition;
|
||||
_baseScale = transform.localScale;
|
||||
_localHomePosition = transform.localPosition;
|
||||
_baseScale = transform.localScale;
|
||||
|
||||
if (_textComponent != null && !string.IsNullOrEmpty(_overrideText))
|
||||
_textComponent.text = _overrideText;
|
||||
|
||||
|
||||
|
||||
SaveBaselineSnapshot();
|
||||
SetupGhostTrail();
|
||||
|
||||
@@ -162,10 +174,10 @@ namespace Unheimlich.Features.Dialogue.UI
|
||||
{
|
||||
_cullTimer = 0f;
|
||||
bool shouldBeActive = Vector3.Distance(_camera.transform.position, transform.position)
|
||||
<= _maxVisibleDistance + _fadeRange;
|
||||
<= _maxVisibleDistance + _fadeRange;
|
||||
if (shouldBeActive != _isActive)
|
||||
{
|
||||
_isActive = shouldBeActive;
|
||||
_isActive = shouldBeActive;
|
||||
_textComponent.enabled = _isActive;
|
||||
if (_ghostText != null) _ghostText.enabled = _isActive && _liveGhostEnabled;
|
||||
if (_isActive) _fadeInAlpha = 0f;
|
||||
@@ -176,22 +188,69 @@ namespace Unheimlich.Features.Dialogue.UI
|
||||
|
||||
UpdatePosition();
|
||||
|
||||
float dist = Vector3.Distance(_camera.transform.position, transform.position);
|
||||
float alpha = ComputeAlpha(dist) * _fadeInAlpha;
|
||||
float dist = Vector3.Distance(_camera.transform.position, transform.position);
|
||||
|
||||
// ── One-shot ───────────────────────────────────────────────────────
|
||||
if (_enableOneShot)
|
||||
{
|
||||
if (!_hasBeenSeen && alpha >= _seenAlphaThreshold) _hasBeenSeen = true;
|
||||
if (_hasBeenSeen && alpha <= 0f)
|
||||
// Track the closest the player has ever been since the label was seen
|
||||
if (_hasBeenSeen && dist < _closestDistanceReached)
|
||||
_closestDistanceReached = dist;
|
||||
|
||||
// Mark as seen as soon as the player enters the visible range
|
||||
if (!_hasBeenSeen && dist <= _maxVisibleDistance)
|
||||
{
|
||||
_permanentlyHidden = true;
|
||||
_textComponent.enabled = false;
|
||||
if (_ghostText != null) _ghostText.enabled = false;
|
||||
_hasBeenSeen = true;
|
||||
_closestDistanceReached = dist;
|
||||
}
|
||||
|
||||
// Fade-out is running — drive alpha independently, skip normal alpha pipeline
|
||||
if (_isFadingOut)
|
||||
{
|
||||
_fadeOutTimer += Time.deltaTime;
|
||||
float t = 1f - Mathf.Clamp01(_fadeOutTimer / _fadeOutDuration);
|
||||
float a = _fadeOutStartAlpha * t;
|
||||
SetTextAlpha(_textComponent, a);
|
||||
if (_ghostText != null) SetTextAlpha(_ghostText, a * _liveGhostAlpha);
|
||||
|
||||
if (_fadeOutTimer >= _fadeOutDuration)
|
||||
{
|
||||
_permanentlyHidden = true;
|
||||
_isFadingOut = false;
|
||||
_textComponent.enabled = false;
|
||||
if (_ghostText != null) _ghostText.enabled = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (_hasBeenSeen)
|
||||
{
|
||||
// Trigger: player reached the explicit trigger distance at some point
|
||||
bool hasTriggered = _closestDistanceReached <= _oneShotTriggerDistance;
|
||||
|
||||
// Reset: player walked far away without ever triggering
|
||||
bool isFarNow = dist > _maxVisibleDistance - _fadeRange;
|
||||
|
||||
if (hasTriggered)
|
||||
{
|
||||
_isFadingOut = true;
|
||||
_fadeOutTimer = 0f;
|
||||
_fadeOutStartAlpha = ComputeAlpha(dist) * _fadeInAlpha;
|
||||
_closestDistanceReached = float.MaxValue;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_isRetriggerableFar && isFarNow)
|
||||
{
|
||||
_hasBeenSeen = false;
|
||||
_closestDistanceReached = float.MaxValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── Normal alpha pipeline ──────────────────────────────────────────
|
||||
float alpha = ComputeAlpha(dist) * _fadeInAlpha;
|
||||
|
||||
UpdateCameraAttraction(alpha);
|
||||
ApplyAlpha(alpha);
|
||||
UpdateAdaptiveScale();
|
||||
@@ -284,10 +343,14 @@ namespace Unheimlich.Features.Dialogue.UI
|
||||
|
||||
public void ResetOneShot()
|
||||
{
|
||||
_hasBeenSeen = false;
|
||||
_permanentlyHidden = false;
|
||||
_hasBeenSeen = false;
|
||||
_permanentlyHidden = false;
|
||||
_isFadingOut = false;
|
||||
_fadeOutTimer = 0f;
|
||||
_fadeOutStartAlpha = 1f;
|
||||
_closestDistanceReached = float.MaxValue;
|
||||
if (_textComponent != null) _textComponent.enabled = true;
|
||||
if (_ghostText != null) _ghostText.enabled = true;
|
||||
if (_ghostText != null) _ghostText.enabled = _liveGhostEnabled;
|
||||
_fadeInAlpha = 0f;
|
||||
}
|
||||
|
||||
@@ -416,13 +479,13 @@ namespace Unheimlich.Features.Dialogue.UI
|
||||
ghostObj.transform.localScale = transform.localScale;
|
||||
ghostObj.layer = gameObject.layer;
|
||||
|
||||
_ghostText = ghostObj.AddComponent<TextMeshPro>();
|
||||
_ghostText.font = _textComponent.font;
|
||||
_ghostText.fontSize = _textComponent.fontSize;
|
||||
_ghostText = ghostObj.AddComponent<TextMeshPro>();
|
||||
_ghostText.font = _textComponent.font;
|
||||
_ghostText.fontSize = _textComponent.fontSize;
|
||||
_ghostText.alignment = _textComponent.alignment;
|
||||
_ghostText.text = _textComponent.text;
|
||||
_ghostText.color = new Color(_textComponent.color.r, _textComponent.color.g,
|
||||
_textComponent.color.b, _liveGhostAlpha);
|
||||
_ghostText.text = _textComponent.text;
|
||||
_ghostText.color = new Color(_textComponent.color.r, _textComponent.color.g,
|
||||
_textComponent.color.b, _liveGhostAlpha);
|
||||
|
||||
MeshRenderer mainRenderer = _textComponent.GetComponent<MeshRenderer>();
|
||||
MeshRenderer ghostRenderer = _ghostText.GetComponent<MeshRenderer>();
|
||||
|
||||
Reference in New Issue
Block a user