test : opti

This commit is contained in:
Ferlat Thibaud
2026-07-03 11:49:25 +02:00
parent 85ab8ebabd
commit fea082bb6f
399 changed files with 1912806 additions and 1893 deletions
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: af40c02d10e408f40858ac9be2668106
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,57 @@
using UnityEngine;
using UnityEditor;
public static class EnableGPUInstancing
{
private const string MaterialPrefix = "M_";
[MenuItem("Tools/Optimization/Enable GPU Instancing On M_ Materials")]
public static void EnableOnMPrefixMaterials()
{
string[] materialGuids = AssetDatabase.FindAssets("t:Material");
int changed = 0;
int alreadyEnabled = 0;
int skippedWrongPrefix = 0;
int skippedInvalid = 0;
foreach (string guid in materialGuids)
{
string path = AssetDatabase.GUIDToAssetPath(guid);
Material mat = AssetDatabase.LoadAssetAtPath<Material>(path);
if (mat == null || mat.shader == null || !mat.shader.isSupported)
{
skippedInvalid++;
continue;
}
if (!mat.name.StartsWith(MaterialPrefix))
{
skippedWrongPrefix++;
continue;
}
if (mat.enableInstancing)
{
alreadyEnabled++;
continue;
}
mat.enableInstancing = true;
EditorUtility.SetDirty(mat);
changed++;
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
Debug.Log(
$"GPU Instancing terminé sur les matériaux commençant par '{MaterialPrefix}'. " +
$"Activés : {changed}, " +
$"déjà actifs : {alreadyEnabled}, " +
$"ignorés mauvais préfixe : {skippedWrongPrefix}, " +
$"ignorés invalides : {skippedInvalid}."
);
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 8d7b767fc9ca8984ca9685fa864b4250
@@ -1,70 +1,373 @@
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Video;
namespace Unheimlich.Features.Hallucination
{
/// <summary>
/// Plays a full-screen image flash on the HUD canvas.
/// Fades are handled via LeanTween.
/// Call <see cref="Play"/> to trigger the flash.
/// Plays a short hallucination video using an eye blink transition on the HUD canvas.
/// Movement is handled via LeanTween.
/// Call Play() to trigger the hallucination.
/// </summary>
public class HallucinationFlash : MonoBehaviour
{
[Header("Target")]
[SerializeField] private Image _image;
[SerializeField] private VideoPlayer _videoPlayer;
[SerializeField] private RawImage _hallucinationVideo;
[SerializeField] private Image _topEyelid;
[SerializeField] private Image _bottomEyelid;
[Header("Timings")]
[SerializeField, Min(0f)] private float _fadeIn = 0.1f;
[SerializeField, Min(0f)] private float _hold = 0.2f;
[SerializeField, Min(0f)] private float _fadeOut = 0.5f;
[SerializeField, Min(0f)] private float _closeDuration = 0.1f;
[SerializeField, Min(0f)] private float _holdClosed = 0.05f;
[SerializeField, Min(0f)] private float _openDuration = 0.15f;
[SerializeField, Min(0f)] private float _visibleHold = 0.5f;
// ─── State ─────────────────────────────────────────────────────────────
[Header("Video Timing")]
[SerializeField, Range(0f, 1f)] private float _showVideoAtCloseProgress = 0.25f;
private int _tweenId = -1;
[Header("Video Playback")]
[SerializeField, Min(0f)] private float _playbackSpeed = 1f;
[SerializeField] private bool _skipOnDrop = true;
[SerializeField] private bool _logVideoDebug = false;
// ─── Public API ────────────────────────────────────────────────────────
[Header("Positions")]
[SerializeField] private float _openOffset = 600f;
[SerializeField] private float _closedOffset = 0f;
/// <summary>
/// Plays the flash sequence.
/// Interrupts any flash already in progress.
/// Safe to wire to any UnityEvent with no arguments.
/// </summary>
public void Play()
private int _topTweenId = -1;
private int _bottomTweenId = -1;
private int _delayTweenId = -1;
private int _videoTweenId = -1;
private bool _isWarmedUp;
private bool _playWhenReady;
private bool _videoShown;
private void Awake()
{
_image.color = new Color(_image.color.r, _image.color.g, _image.color.b, 0f);
SetHallucinationVisible(false);
SetEyelidsOpen();
CancelCurrent();
_tweenId = LeanTween.value(gameObject, 0f, 1f, _fadeIn)
.setEase(LeanTweenType.easeOutQuad)
.setOnUpdate(SetAlpha)
.setOnComplete(() =>
{
_tweenId = LeanTween.value(gameObject, 1f, 1f, _hold)
.setOnComplete(() =>
{
_tweenId = LeanTween.value(gameObject, 1f, 0f, _fadeOut)
.setEase(LeanTweenType.easeInQuad)
.setOnUpdate(SetAlpha)
.id;
}).id;
}).id;
ConfigureVideoPlayer();
}
// ─── Private ───────────────────────────────────────────────────────────
private void Start()
{
StartCoroutine(WarmUpVideo());
}
public void Play()
{
if (!_isWarmedUp)
{
_playWhenReady = true;
return;
}
PlayPreparedSequence();
}
private void ConfigureVideoPlayer()
{
if (_videoPlayer == null)
return;
_videoPlayer.playOnAwake = false;
_videoPlayer.isLooping = false;
_videoPlayer.waitForFirstFrame = true;
_videoPlayer.skipOnDrop = _skipOnDrop;
_videoPlayer.playbackSpeed = _playbackSpeed;
if (_logVideoDebug)
{
Debug.Log(
"[HallucinationFlash] ConfigureVideoPlayer"
+ " | speed=" + _videoPlayer.playbackSpeed
+ " | canSetSpeed=" + _videoPlayer.canSetPlaybackSpeed
+ " | skipOnDrop=" + _videoPlayer.skipOnDrop
+ " | updateMode=" + _videoPlayer.timeUpdateMode
);
}
}
private IEnumerator WarmUpVideo()
{
if (_videoPlayer == null)
yield break;
SetHallucinationVisible(false);
ConfigureVideoPlayer();
_videoPlayer.Prepare();
while (!_videoPlayer.isPrepared)
yield return null;
ConfigureVideoPlayer();
// Play once while hidden to force Unity to decode the first frames.
_videoPlayer.Play();
while (!_videoPlayer.isPlaying)
yield return null;
// Wait a few frames so the RenderTexture actually receives video data.
yield return null;
yield return null;
yield return null;
_videoPlayer.Pause();
_videoPlayer.time = 0.0;
ConfigureVideoPlayer();
// Wait one frame after seeking back to the beginning.
yield return null;
_isWarmedUp = true;
if (!_playWhenReady)
yield break;
_playWhenReady = false;
PlayPreparedSequence();
}
private void PlayPreparedSequence()
{
CancelCurrent();
ResetVideoToStart();
SetHallucinationVisible(false);
SetEyelidsOpen();
_videoShown = false;
CloseEyes(() =>
{
if (!_videoShown)
ShowVideo();
HoldClosed(() =>
{
OpenEyes(() =>
{
HoldVisible(() =>
{
CloseEyes(() =>
{
HideVideo();
HoldClosed(() =>
{
OpenEyes(() =>
{
ClearTweenIds();
});
});
});
});
});
});
});
ShowVideoDuringClose();
}
private void CloseEyes(System.Action onComplete)
{
RectTransform top = _topEyelid.rectTransform;
RectTransform bottom = _bottomEyelid.rectTransform;
_topTweenId = LeanTween.moveY(top, _closedOffset, _closeDuration)
.setEase(LeanTweenType.easeOutQuad)
.setOnComplete(() =>
{
_topTweenId = -1;
onComplete?.Invoke();
})
.id;
_bottomTweenId = LeanTween.moveY(bottom, -_closedOffset, _closeDuration)
.setEase(LeanTweenType.easeOutQuad)
.setOnComplete(() =>
{
_bottomTweenId = -1;
})
.id;
}
private void OpenEyes(System.Action onComplete)
{
RectTransform top = _topEyelid.rectTransform;
RectTransform bottom = _bottomEyelid.rectTransform;
_topTweenId = LeanTween.moveY(top, _openOffset, _openDuration)
.setEase(LeanTweenType.easeInQuad)
.setOnComplete(() =>
{
_topTweenId = -1;
onComplete?.Invoke();
})
.id;
_bottomTweenId = LeanTween.moveY(bottom, -_openOffset, _openDuration)
.setEase(LeanTweenType.easeInQuad)
.setOnComplete(() =>
{
_bottomTweenId = -1;
})
.id;
}
private void ShowVideoDuringClose()
{
float delay = _closeDuration * _showVideoAtCloseProgress;
_videoTweenId = LeanTween.delayedCall(gameObject, delay, () =>
{
_videoTweenId = -1;
ShowVideo();
}).id;
}
private void ShowVideo()
{
if (_videoShown)
return;
_videoShown = true;
SetHallucinationVisible(true);
PlayVideo();
}
private void HideVideo()
{
PauseVideoAtStart();
SetHallucinationVisible(false);
}
private void HoldClosed(System.Action onComplete)
{
_delayTweenId = LeanTween.delayedCall(gameObject, _holdClosed, () =>
{
_delayTweenId = -1;
onComplete?.Invoke();
}).id;
}
private void HoldVisible(System.Action onComplete)
{
_delayTweenId = LeanTween.delayedCall(gameObject, _visibleHold, () =>
{
_delayTweenId = -1;
onComplete?.Invoke();
}).id;
}
private void PlayVideo()
{
if (_videoPlayer == null)
return;
ConfigureVideoPlayer();
// Do not Stop() here. Stop() can reintroduce decoding latency.
_videoPlayer.Play();
if (_logVideoDebug)
{
Debug.Log(
"[HallucinationFlash] PlayVideo"
+ " | speed=" + _videoPlayer.playbackSpeed
+ " | canSetSpeed=" + _videoPlayer.canSetPlaybackSpeed
+ " | time=" + _videoPlayer.time
+ " | frame=" + _videoPlayer.frame
);
}
}
private void ResetVideoToStart()
{
if (_videoPlayer == null)
return;
_videoPlayer.Pause();
_videoPlayer.time = 0.0;
ConfigureVideoPlayer();
}
private void PauseVideoAtStart()
{
if (_videoPlayer == null)
return;
_videoPlayer.Pause();
_videoPlayer.time = 0.0;
ConfigureVideoPlayer();
}
private void SetHallucinationVisible(bool visible)
{
if (_hallucinationVideo == null)
return;
_hallucinationVideo.enabled = visible;
}
private void SetEyelidsOpen()
{
if (_topEyelid == null || _bottomEyelid == null)
return;
RectTransform top = _topEyelid.rectTransform;
RectTransform bottom = _bottomEyelid.rectTransform;
top.anchoredPosition = new Vector2(top.anchoredPosition.x, _openOffset);
bottom.anchoredPosition = new Vector2(bottom.anchoredPosition.x, -_openOffset);
}
private void CancelCurrent()
{
if (_tweenId == -1) return;
LeanTween.cancel(_tweenId);
_tweenId = -1;
_playWhenReady = false;
_videoShown = false;
if (_topTweenId != -1)
{
LeanTween.cancel(_topTweenId);
_topTweenId = -1;
}
if (_bottomTweenId != -1)
{
LeanTween.cancel(_bottomTweenId);
_bottomTweenId = -1;
}
if (_delayTweenId != -1)
{
LeanTween.cancel(_delayTweenId);
_delayTweenId = -1;
}
if (_videoTweenId != -1)
{
LeanTween.cancel(_videoTweenId);
_videoTweenId = -1;
}
}
private void SetAlpha(float alpha)
private void ClearTweenIds()
{
Color c = _image.color;
c.a = alpha;
_image.color = c;
_topTweenId = -1;
_bottomTweenId = -1;
_delayTweenId = -1;
_videoTweenId = -1;
}
}
}
+10 -1
View File
@@ -103,7 +103,9 @@ public class SpiralStaircase : MonoBehaviour
float wallSegmentHeight = _stairHeight * 2f;
for (int i = 1; i < _settings.HalfTurns / 2 - 2; i++)
int lastIndex = _settings.HalfTurns / 2 - 3;
for (int i = 1; i < _settings.HalfTurns / 2 - 2; i++)
{
GameObject obj = Instantiate(
_references.WallMiddle,
@@ -113,6 +115,13 @@ public class SpiralStaircase : MonoBehaviour
obj.transform.localPosition =
_references.WallMiddle.transform.localPosition +
Vector3.up * wallSegmentHeight * i;
if (i == lastIndex)
{
Vector3 scale = obj.transform.localScale;
scale.y = 3f;
obj.transform.localScale = scale;
}
}
}