UI换了很多,spine主视觉停用
This commit is contained in:
@@ -1,28 +1,24 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.UI;
|
||||
using Spine.Unity;
|
||||
using UnityEngine.Video;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
using UnityEditor.SceneManagement;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Throttled preload: uses queues and concurrency limits to load scenes and Resources in small time slices
|
||||
/// Throttled preload: uses queues and concurrency limits to load Resources in small time slices
|
||||
/// to avoid long frames on low-end devices.
|
||||
/// - scenesToPreload: names of scenes included in Build Settings to preload additively (allowSceneActivation=false)
|
||||
/// - resourcesToPreload: paths under Resources/ to load via Resources.LoadAsync
|
||||
/// The opening presentation now uses two videos: vj01 plays once, then vj02 loops.
|
||||
/// </summary>
|
||||
public class preload_allScene : MonoBehaviour
|
||||
{
|
||||
[Header("Preload settings")]
|
||||
public string[] resourcesToPreload = new string[0];
|
||||
|
||||
[Header("UI")]
|
||||
public GameObject spineObject1;
|
||||
public GameObject spineObject2;
|
||||
public CanvasGroup spineObject1CanvasGroup;
|
||||
public float spineObject1DestroyDelay = 6.7f;
|
||||
public float spineObject1FadeDelay = 5.7f;
|
||||
public float spineObject2PlayDelay = 0f;
|
||||
[Header("UI references")]
|
||||
public Text progressText;
|
||||
[Tooltip("Optional Image whose fillAmount will be driven by the overall progress (0..1)")]
|
||||
public Image progressFillImage;
|
||||
@@ -31,6 +27,11 @@ public class preload_allScene : MonoBehaviour
|
||||
[Tooltip("Documentation text normalized.")]
|
||||
public Text loadingInfoText;
|
||||
|
||||
[Header("Opening Video")]
|
||||
public RawImage openingVideoRawImage;
|
||||
public VideoClip vj01Clip;
|
||||
public VideoClip vj02Clip;
|
||||
|
||||
[Header("Behavior")]
|
||||
public bool startOnAwake = true;
|
||||
|
||||
@@ -39,27 +40,30 @@ public class preload_allScene : MonoBehaviour
|
||||
[Tooltip("Max milliseconds spent per frame on driver work (approx)")]
|
||||
public int maxMilliSecondsPerFrame = 4;
|
||||
|
||||
// internal queues and trackers
|
||||
private Queue<string> resourceQueue = new Queue<string>();
|
||||
|
||||
private List<(string path, ResourceRequest rr)> activeResourceReqs = new List<(string, ResourceRequest)>();
|
||||
|
||||
private List<Object> loadedResources = new List<Object>();
|
||||
private readonly Queue<string> resourceQueue = new Queue<string>();
|
||||
private readonly List<(string path, ResourceRequest rr)> activeResourceReqs = new List<(string, ResourceRequest)>();
|
||||
private readonly List<Object> loadedResources = new List<Object>();
|
||||
|
||||
private Coroutine preloadCoroutine;
|
||||
private VideoPlayer videoPlayer1;
|
||||
private VideoPlayer videoPlayer2A;
|
||||
private VideoPlayer videoPlayer2B;
|
||||
private RenderTexture videoTexture1;
|
||||
private RenderTexture videoTexture2A;
|
||||
private RenderTexture videoTexture2B;
|
||||
private VideoPlayer activeLoopPlayer;
|
||||
private VideoPlayer standbyLoopPlayer;
|
||||
private bool waitingForLoopStartup;
|
||||
private Coroutine openingVideoStartupCoroutine;
|
||||
|
||||
void Awake()
|
||||
private void Awake()
|
||||
{
|
||||
Debug.Log("[preload_allScene] Awake called. Forcing Time.timeScale = 1.");
|
||||
Time.timeScale = 1f; // Ensure time is running so fades and DOTween work
|
||||
Time.timeScale = 1f;
|
||||
|
||||
// 确保物体 1 初始处于关闭状态,以便 1 秒后延迟开启
|
||||
if (spineObject1 != null)
|
||||
{
|
||||
spineObject1.SetActive(false);
|
||||
}
|
||||
EnsureOpeningVideoSetup();
|
||||
SetVideoDisplayVisible(openingVideoRawImage, false);
|
||||
|
||||
// if UI not assigned, try to auto-find Text components
|
||||
if (progressText == null)
|
||||
{
|
||||
progressText = GetComponentInChildren<Text>(true);
|
||||
@@ -67,7 +71,6 @@ public class preload_allScene : MonoBehaviour
|
||||
|
||||
if (loadingInfoText == null)
|
||||
{
|
||||
// try to find a different Text child (avoid using same as progressText)
|
||||
var texts = GetComponentsInChildren<Text>(true);
|
||||
foreach (var t in texts)
|
||||
{
|
||||
@@ -80,28 +83,12 @@ public class preload_allScene : MonoBehaviour
|
||||
}
|
||||
}
|
||||
|
||||
void Start()
|
||||
private void Start()
|
||||
{
|
||||
Debug.Log("[preload_allScene] Start called. resourcesToPreload count: " + (resourcesToPreload?.Length ?? 0));
|
||||
|
||||
// 同时启用并初始化两个 Spine 物体
|
||||
if (spineObject1 != null)
|
||||
{
|
||||
// Start 时显式禁用物体 1,确保初始状态正确
|
||||
spineObject1.SetActive(false);
|
||||
// 等待 1 秒后再播放 Spine 1
|
||||
StartCoroutine(DelayedPlaySpine1());
|
||||
}
|
||||
StartOpeningVideoSequence();
|
||||
|
||||
if (spineObject2 != null)
|
||||
{
|
||||
// Start 时显式禁用物体 2,确保初始状态正确
|
||||
spineObject2.SetActive(false);
|
||||
// 延迟播放物体 2 的动画
|
||||
StartCoroutine(DelayedPlaySpine2Logic());
|
||||
}
|
||||
|
||||
// 1 秒后禁用指定的 Image
|
||||
if (startDisableImage != null)
|
||||
{
|
||||
StartCoroutine(DelayedDisableImage());
|
||||
@@ -110,6 +97,113 @@ public class preload_allScene : MonoBehaviour
|
||||
StartPreload();
|
||||
}
|
||||
|
||||
private void EnsureOpeningVideoSetup()
|
||||
{
|
||||
TryAutoAssignVideoClips();
|
||||
|
||||
if (videoPlayer1 == null && openingVideoRawImage != null)
|
||||
{
|
||||
videoPlayer1 = CreateVideoPlayer("OpeningVideoPlayer_VJ01", vj01Clip, false, ref videoTexture1);
|
||||
if (videoPlayer1 != null)
|
||||
{
|
||||
videoPlayer1.loopPointReached += OnVj01Finished;
|
||||
}
|
||||
}
|
||||
|
||||
if (videoPlayer2A == null && openingVideoRawImage != null)
|
||||
{
|
||||
videoPlayer2A = CreateVideoPlayer("OpeningVideoPlayer_VJ02_A", vj02Clip, false, ref videoTexture2A);
|
||||
if (videoPlayer2A != null)
|
||||
{
|
||||
videoPlayer2A.prepareCompleted += OnLoopPlayerPrepared;
|
||||
videoPlayer2A.loopPointReached += OnLoopVideoReachedEnd;
|
||||
}
|
||||
}
|
||||
|
||||
if (videoPlayer2B == null && openingVideoRawImage != null)
|
||||
{
|
||||
videoPlayer2B = CreateVideoPlayer("OpeningVideoPlayer_VJ02_B", vj02Clip, false, ref videoTexture2B);
|
||||
if (videoPlayer2B != null)
|
||||
{
|
||||
videoPlayer2B.prepareCompleted += OnLoopPlayerPrepared;
|
||||
videoPlayer2B.loopPointReached += OnLoopVideoReachedEnd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void StartOpeningVideoSequence()
|
||||
{
|
||||
EnsureOpeningVideoSetup();
|
||||
if (openingVideoStartupCoroutine != null)
|
||||
{
|
||||
StopCoroutine(openingVideoStartupCoroutine);
|
||||
}
|
||||
|
||||
openingVideoStartupCoroutine = StartCoroutine(PrepareOpeningVideosAndStart());
|
||||
}
|
||||
|
||||
private IEnumerator PrepareOpeningVideosAndStart()
|
||||
{
|
||||
SetVideoDisplayVisible(openingVideoRawImage, false);
|
||||
|
||||
if (videoPlayer1 != null && !videoPlayer1.isPrepared)
|
||||
{
|
||||
videoPlayer1.Prepare();
|
||||
}
|
||||
|
||||
if (videoPlayer2A != null && !videoPlayer2A.isPrepared)
|
||||
{
|
||||
videoPlayer2A.Prepare();
|
||||
}
|
||||
|
||||
if (videoPlayer2B != null && !videoPlayer2B.isPrepared)
|
||||
{
|
||||
videoPlayer2B.Prepare();
|
||||
}
|
||||
|
||||
while (!AreOpeningVideosPrepared())
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
|
||||
openingVideoStartupCoroutine = null;
|
||||
|
||||
if (videoPlayer1 != null)
|
||||
{
|
||||
if (openingVideoRawImage != null)
|
||||
{
|
||||
openingVideoRawImage.texture = videoTexture1;
|
||||
}
|
||||
|
||||
SetVideoDisplayVisible(openingVideoRawImage, true);
|
||||
ResetPlayerToStart(videoPlayer1);
|
||||
videoPlayer1.Play();
|
||||
yield break;
|
||||
}
|
||||
|
||||
StartLoopVideo2();
|
||||
}
|
||||
|
||||
private bool AreOpeningVideosPrepared()
|
||||
{
|
||||
if (videoPlayer1 != null && !videoPlayer1.isPrepared)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (videoPlayer2A != null && !videoPlayer2A.isPrepared)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (videoPlayer2B != null && !videoPlayer2B.isPrepared)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private IEnumerator DelayedDisableImage()
|
||||
{
|
||||
yield return new WaitForSeconds(1f);
|
||||
@@ -120,117 +214,292 @@ public class preload_allScene : MonoBehaviour
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator DelayedPlaySpine1()
|
||||
private VideoPlayer CreateVideoPlayer(string objectName, VideoClip clip, bool loop, ref RenderTexture renderTexture)
|
||||
{
|
||||
// 等待 1 秒
|
||||
yield return new WaitForSeconds(1f);
|
||||
|
||||
if (spineObject1 != null)
|
||||
if (clip == null || openingVideoRawImage == null)
|
||||
{
|
||||
spineObject1.SetActive(true);
|
||||
var sg1 = spineObject1.GetComponentInChildren<SkeletonGraphic>(true);
|
||||
if (sg1 != null)
|
||||
return null;
|
||||
}
|
||||
|
||||
Transform existing = transform.Find(objectName);
|
||||
GameObject playerObject = existing != null ? existing.gameObject : new GameObject(objectName);
|
||||
playerObject.transform.SetParent(transform, false);
|
||||
|
||||
var player = playerObject.GetComponent<VideoPlayer>();
|
||||
if (player == null)
|
||||
{
|
||||
player = playerObject.AddComponent<VideoPlayer>();
|
||||
}
|
||||
|
||||
bool mustStartFromFirstFrame = clip == vj01Clip;
|
||||
|
||||
player.playOnAwake = false;
|
||||
player.isLooping = loop;
|
||||
player.waitForFirstFrame = false;
|
||||
player.skipOnDrop = !mustStartFromFirstFrame;
|
||||
player.timeUpdateMode = VideoTimeUpdateMode.UnscaledGameTime;
|
||||
player.playbackSpeed = 1f;
|
||||
player.audioOutputMode = VideoAudioOutputMode.None;
|
||||
player.source = VideoSource.VideoClip;
|
||||
player.clip = clip;
|
||||
player.renderMode = VideoRenderMode.RenderTexture;
|
||||
|
||||
int width = clip.width > 0 ? (int)clip.width : 1920;
|
||||
int height = clip.height > 0 ? (int)clip.height : 1080;
|
||||
EnsureRenderTexture(ref renderTexture, width, height, objectName + "_RT");
|
||||
player.targetTexture = renderTexture;
|
||||
|
||||
return player;
|
||||
}
|
||||
|
||||
private static void SetVideoDisplayVisible(RawImage image, bool visible)
|
||||
{
|
||||
if (image == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
image.gameObject.SetActive(visible);
|
||||
}
|
||||
|
||||
private static void ResetPlayerToStart(VideoPlayer player)
|
||||
{
|
||||
if (player == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try { player.playbackSpeed = 1f; } catch { }
|
||||
try { player.Stop(); } catch { }
|
||||
try { player.frame = 0; } catch { }
|
||||
try { player.time = 0d; } catch { }
|
||||
}
|
||||
|
||||
private void EnsureRenderTexture(ref RenderTexture renderTexture, int width, int height, string textureName)
|
||||
{
|
||||
if (renderTexture != null && renderTexture.width == width && renderTexture.height == height)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ReleaseRenderTexture(ref renderTexture);
|
||||
|
||||
renderTexture = new RenderTexture(width, height, 0, RenderTextureFormat.ARGB32);
|
||||
renderTexture.name = textureName;
|
||||
renderTexture.Create();
|
||||
}
|
||||
|
||||
private void ReleaseRenderTexture(ref RenderTexture renderTexture)
|
||||
{
|
||||
if (renderTexture == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (renderTexture.IsCreated())
|
||||
{
|
||||
renderTexture.Release();
|
||||
}
|
||||
|
||||
Destroy(renderTexture);
|
||||
renderTexture = null;
|
||||
}
|
||||
|
||||
private void OnVj01Finished(VideoPlayer source)
|
||||
{
|
||||
if (videoPlayer1 != null)
|
||||
{
|
||||
videoPlayer1.Stop();
|
||||
}
|
||||
|
||||
StartLoopVideo2();
|
||||
}
|
||||
|
||||
private void StartLoopVideo2()
|
||||
{
|
||||
if (videoPlayer2A == null && videoPlayer2B == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SetVideoDisplayVisible(openingVideoRawImage, true);
|
||||
|
||||
VideoPlayer firstPrepared = GetPreparedLoopPlayer();
|
||||
if (firstPrepared != null)
|
||||
{
|
||||
StartPreparedLoopPlayer(firstPrepared);
|
||||
return;
|
||||
}
|
||||
|
||||
waitingForLoopStartup = true;
|
||||
|
||||
if (videoPlayer2A != null && !videoPlayer2A.isPrepared)
|
||||
{
|
||||
videoPlayer2A.Prepare();
|
||||
}
|
||||
|
||||
if (videoPlayer2B != null && !videoPlayer2B.isPrepared)
|
||||
{
|
||||
videoPlayer2B.Prepare();
|
||||
}
|
||||
}
|
||||
|
||||
private VideoPlayer GetPreparedLoopPlayer()
|
||||
{
|
||||
if (videoPlayer2A != null && videoPlayer2A.isPrepared)
|
||||
{
|
||||
return videoPlayer2A;
|
||||
}
|
||||
|
||||
if (videoPlayer2B != null && videoPlayer2B.isPrepared)
|
||||
{
|
||||
return videoPlayer2B;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void StartPreparedLoopPlayer(VideoPlayer player)
|
||||
{
|
||||
if (player == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
activeLoopPlayer = player;
|
||||
standbyLoopPlayer = player == videoPlayer2A ? videoPlayer2B : videoPlayer2A;
|
||||
waitingForLoopStartup = false;
|
||||
|
||||
if (openingVideoRawImage != null)
|
||||
{
|
||||
openingVideoRawImage.texture = player.targetTexture;
|
||||
}
|
||||
|
||||
SetVideoDisplayVisible(openingVideoRawImage, true);
|
||||
|
||||
if (!activeLoopPlayer.isPlaying)
|
||||
{
|
||||
activeLoopPlayer.Play();
|
||||
}
|
||||
|
||||
if (standbyLoopPlayer != null && !standbyLoopPlayer.isPrepared)
|
||||
{
|
||||
standbyLoopPlayer.Prepare();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLoopPlayerPrepared(VideoPlayer source)
|
||||
{
|
||||
if (waitingForLoopStartup)
|
||||
{
|
||||
StartPreparedLoopPlayer(source);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnApplicationPause(bool pauseStatus)
|
||||
{
|
||||
if (!pauseStatus)
|
||||
{
|
||||
ResumeOpeningVideosIfNeeded();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnApplicationFocus(bool hasFocus)
|
||||
{
|
||||
if (hasFocus)
|
||||
{
|
||||
ResumeOpeningVideosIfNeeded();
|
||||
}
|
||||
}
|
||||
|
||||
private void ResumeOpeningVideosIfNeeded()
|
||||
{
|
||||
if (openingVideoRawImage == null || !openingVideoRawImage.gameObject.activeInHierarchy)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (videoPlayer1 != null && openingVideoRawImage.texture == videoTexture1 && !videoPlayer1.isPlaying)
|
||||
{
|
||||
videoPlayer1.Play();
|
||||
return;
|
||||
}
|
||||
|
||||
if (activeLoopPlayer != null && openingVideoRawImage.texture == activeLoopPlayer.targetTexture && !activeLoopPlayer.isPlaying)
|
||||
{
|
||||
activeLoopPlayer.Play();
|
||||
return;
|
||||
}
|
||||
|
||||
VideoPlayer prepared = GetPreparedLoopPlayer();
|
||||
if (prepared != null && !prepared.isPlaying)
|
||||
{
|
||||
StartPreparedLoopPlayer(prepared);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLoopVideoReachedEnd(VideoPlayer source)
|
||||
{
|
||||
if (source != activeLoopPlayer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (standbyLoopPlayer != null && standbyLoopPlayer.isPrepared)
|
||||
{
|
||||
VideoPlayer finishedPlayer = activeLoopPlayer;
|
||||
VideoPlayer nextPlayer = standbyLoopPlayer;
|
||||
|
||||
if (openingVideoRawImage != null)
|
||||
{
|
||||
sg1.allowMultipleCanvasRenderers = true;
|
||||
sg1.Initialize(true);
|
||||
var state1 = (sg1.Animation as IAnimationStateComponent)?.AnimationState;
|
||||
if (state1 != null)
|
||||
{
|
||||
state1.SetAnimation(0, "intro", false);
|
||||
}
|
||||
|
||||
// 改为延迟切换到 loop 动画
|
||||
StartCoroutine(DelayedPlaySpine1Loop(sg1));
|
||||
|
||||
// 新增渐隐逻辑
|
||||
StartCoroutine(FadeOutSpine1());
|
||||
openingVideoRawImage.texture = nextPlayer.targetTexture;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator DelayedPlaySpine1Loop(SkeletonGraphic sg)
|
||||
{
|
||||
if (spineObject1DestroyDelay > 0)
|
||||
yield return new WaitForSeconds(spineObject1DestroyDelay);
|
||||
|
||||
var state1 = (sg.Animation as IAnimationStateComponent)?.AnimationState;
|
||||
if (state1 != null)
|
||||
{
|
||||
state1.SetAnimation(0, "loop", true);
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator FadeOutSpine1()
|
||||
{
|
||||
if (spineObject1CanvasGroup == null) yield break;
|
||||
|
||||
if (spineObject1FadeDelay > 0)
|
||||
yield return new WaitForSeconds(spineObject1FadeDelay);
|
||||
|
||||
float duration = 1f;
|
||||
float elapsed = 0f;
|
||||
float startAlpha = spineObject1CanvasGroup.alpha;
|
||||
|
||||
while (elapsed < duration)
|
||||
{
|
||||
elapsed += Time.deltaTime;
|
||||
spineObject1CanvasGroup.alpha = Mathf.Lerp(startAlpha, 0f, elapsed / duration);
|
||||
yield return null;
|
||||
}
|
||||
|
||||
spineObject1CanvasGroup.alpha = 0f;
|
||||
|
||||
// 渐隐结束后销毁物体 1
|
||||
if (spineObject1 != null)
|
||||
{
|
||||
Debug.Log("SpineObject1 fade out completed. Destroying object.");
|
||||
Destroy(spineObject1);
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator DelayedPlaySpine2Logic()
|
||||
{
|
||||
if (spineObject2 == null) yield break;
|
||||
|
||||
// 等待指定的播放延迟
|
||||
if (spineObject2PlayDelay > 0)
|
||||
yield return new WaitForSeconds(spineObject2PlayDelay);
|
||||
|
||||
// 启用物体并初始化动画
|
||||
spineObject2.SetActive(true);
|
||||
var sg2 = spineObject2.GetComponentInChildren<SkeletonGraphic>(true);
|
||||
if (sg2 != null)
|
||||
{
|
||||
sg2.allowMultipleCanvasRenderers = true;
|
||||
sg2.Initialize(true);
|
||||
var state2 = (sg2.Animation as IAnimationStateComponent)?.AnimationState;
|
||||
if (state2 != null)
|
||||
if (!nextPlayer.isPlaying)
|
||||
{
|
||||
state2.SetAnimation(0, "loop", true);
|
||||
nextPlayer.Play();
|
||||
}
|
||||
|
||||
activeLoopPlayer = nextPlayer;
|
||||
standbyLoopPlayer = finishedPlayer;
|
||||
|
||||
if (standbyLoopPlayer.isPlaying)
|
||||
{
|
||||
standbyLoopPlayer.Stop();
|
||||
}
|
||||
|
||||
standbyLoopPlayer.Prepare();
|
||||
return;
|
||||
}
|
||||
|
||||
source.Play();
|
||||
}
|
||||
|
||||
public void StartPreload()
|
||||
{
|
||||
if (preloadCoroutine != null) return;
|
||||
if (preloadCoroutine != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// fill queues
|
||||
resourceQueue.Clear();
|
||||
|
||||
if (resourcesToPreload != null)
|
||||
{
|
||||
foreach (var r in resourcesToPreload)
|
||||
if (!string.IsNullOrWhiteSpace(r)) resourceQueue.Enqueue(r);
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(r))
|
||||
{
|
||||
resourceQueue.Enqueue(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Log($"Preload starting. Resources queued: {resourceQueue.Count}");
|
||||
|
||||
// ensure UI shows 0%
|
||||
UpdateProgressText(0f);
|
||||
UpdateLoadingInfo("");
|
||||
UpdateLoadingInfo(string.Empty);
|
||||
|
||||
// If nothing to preload, just show 100% and fade out immediately
|
||||
if (resourceQueue.Count == 0)
|
||||
{
|
||||
UpdateProgressText(1f);
|
||||
@@ -252,12 +521,10 @@ public class preload_allScene : MonoBehaviour
|
||||
|
||||
private IEnumerator PreloadRoutine()
|
||||
{
|
||||
// Start initial batch
|
||||
while (resourceQueue.Count > 0 || activeResourceReqs.Count > 0)
|
||||
{
|
||||
float frameStart = Time.realtimeSinceStartup;
|
||||
|
||||
// start resource reqs up to concurrency
|
||||
while (activeResourceReqs.Count < maxConcurrentResourceLoads && resourceQueue.Count > 0)
|
||||
{
|
||||
string path = resourceQueue.Dequeue();
|
||||
@@ -278,10 +545,12 @@ public class preload_allScene : MonoBehaviour
|
||||
Debug.Log($"Preload: started resource load '{path}'");
|
||||
}
|
||||
|
||||
if ((Time.realtimeSinceStartup - frameStart) * 1000f > maxMilliSecondsPerFrame) break;
|
||||
if ((Time.realtimeSinceStartup - frameStart) * 1000f > maxMilliSecondsPerFrame)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Poll progress and collect finished resources
|
||||
for (int i = activeResourceReqs.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var tuple = activeResourceReqs[i];
|
||||
@@ -289,36 +558,36 @@ public class preload_allScene : MonoBehaviour
|
||||
if (rr.isDone)
|
||||
{
|
||||
if (rr.asset != null)
|
||||
{
|
||||
loadedResources.Add(rr.asset);
|
||||
}
|
||||
|
||||
Debug.Log($"Preload: resource loaded '{tuple.path}'");
|
||||
activeResourceReqs.RemoveAt(i);
|
||||
}
|
||||
|
||||
if ((Time.realtimeSinceStartup - frameStart) * 1000f > maxMilliSecondsPerFrame) break;
|
||||
if ((Time.realtimeSinceStartup - frameStart) * 1000f > maxMilliSecondsPerFrame)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Update progress calculation
|
||||
float overall = CalculateOverallProgress();
|
||||
UpdateProgressText(overall);
|
||||
|
||||
// If there are no active resource requests and no queued resources, we're done
|
||||
bool anyActiveResources = activeResourceReqs.Count > 0 || resourceQueue.Count > 0;
|
||||
|
||||
if (!anyActiveResources)
|
||||
{
|
||||
UpdateProgressText(1f);
|
||||
UpdateLoadingInfo("Loading Complete");
|
||||
preloadCoroutine = null;
|
||||
Debug.Log("Preload complete (throttled). Resources cached: " + loadedResources.Count);
|
||||
|
||||
yield break;
|
||||
}
|
||||
|
||||
// yield one frame to respect budget
|
||||
yield return null;
|
||||
}
|
||||
|
||||
// if we exit loop, also mark complete
|
||||
UpdateProgressText(1f);
|
||||
UpdateLoadingInfo("Loading Complete");
|
||||
preloadCoroutine = null;
|
||||
@@ -330,25 +599,25 @@ public class preload_allScene : MonoBehaviour
|
||||
int items = 0;
|
||||
|
||||
items += resourceQueue.Count + activeResourceReqs.Count;
|
||||
|
||||
if (items == 0) return 1f;
|
||||
|
||||
foreach (var (path, rr) in activeResourceReqs)
|
||||
if (items == 0)
|
||||
{
|
||||
sum += rr.progress; // 0..1
|
||||
return 1f;
|
||||
}
|
||||
|
||||
return Mathf.Clamp01(sum / (float)items);
|
||||
foreach (var (_, rr) in activeResourceReqs)
|
||||
{
|
||||
sum += rr.progress;
|
||||
}
|
||||
|
||||
return Mathf.Clamp01(sum / items);
|
||||
}
|
||||
|
||||
private void UpdateProgressText(float t)
|
||||
{
|
||||
int percent = Mathf.RoundToInt(t * 100f);
|
||||
|
||||
// update fill image if present
|
||||
if (progressFillImage != null)
|
||||
{
|
||||
// clamp to 0..1
|
||||
progressFillImage.fillAmount = Mathf.Clamp01(t);
|
||||
}
|
||||
|
||||
@@ -358,16 +627,14 @@ public class preload_allScene : MonoBehaviour
|
||||
return;
|
||||
}
|
||||
|
||||
// If no UI assigned, try to find any in children and cache it
|
||||
var tcomp = GetComponentInChildren<Text>(true);
|
||||
if (tcomp != null)
|
||||
var textComponent = GetComponentInChildren<Text>(true);
|
||||
if (textComponent != null)
|
||||
{
|
||||
progressText = tcomp;
|
||||
progressText = textComponent;
|
||||
progressText.text = percent + "%";
|
||||
}
|
||||
}
|
||||
|
||||
// helper to update loading info text
|
||||
private void UpdateLoadingInfo(string message)
|
||||
{
|
||||
if (loadingInfoText != null)
|
||||
@@ -376,7 +643,6 @@ public class preload_allScene : MonoBehaviour
|
||||
return;
|
||||
}
|
||||
|
||||
// try to find and cache a Text child that is not the progress text
|
||||
var texts = GetComponentsInChildren<Text>(true);
|
||||
foreach (var t in texts)
|
||||
{
|
||||
@@ -388,4 +654,71 @@ public class preload_allScene : MonoBehaviour
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (openingVideoStartupCoroutine != null)
|
||||
{
|
||||
StopCoroutine(openingVideoStartupCoroutine);
|
||||
openingVideoStartupCoroutine = null;
|
||||
}
|
||||
|
||||
if (videoPlayer1 != null)
|
||||
{
|
||||
videoPlayer1.loopPointReached -= OnVj01Finished;
|
||||
}
|
||||
|
||||
if (videoPlayer2A != null)
|
||||
{
|
||||
videoPlayer2A.prepareCompleted -= OnLoopPlayerPrepared;
|
||||
videoPlayer2A.loopPointReached -= OnLoopVideoReachedEnd;
|
||||
}
|
||||
|
||||
if (videoPlayer2B != null)
|
||||
{
|
||||
videoPlayer2B.prepareCompleted -= OnLoopPlayerPrepared;
|
||||
videoPlayer2B.loopPointReached -= OnLoopVideoReachedEnd;
|
||||
}
|
||||
|
||||
ReleaseRenderTexture(ref videoTexture1);
|
||||
ReleaseRenderTexture(ref videoTexture2A);
|
||||
ReleaseRenderTexture(ref videoTexture2B);
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnValidate()
|
||||
{
|
||||
TryAutoAssignVideoClips();
|
||||
}
|
||||
|
||||
private void TryAutoAssignVideoClips()
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
if (vj01Clip == null)
|
||||
{
|
||||
vj01Clip = AssetDatabase.LoadAssetAtPath<VideoClip>("Assets/op/opVideo/vj01.mp4");
|
||||
changed |= vj01Clip != null;
|
||||
}
|
||||
|
||||
if (vj02Clip == null)
|
||||
{
|
||||
vj02Clip = AssetDatabase.LoadAssetAtPath<VideoClip>("Assets/op/opVideo/vj02.mp4");
|
||||
changed |= vj02Clip != null;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
{
|
||||
EditorUtility.SetDirty(this);
|
||||
if (gameObject.scene.IsValid())
|
||||
{
|
||||
EditorSceneManager.MarkSceneDirty(gameObject.scene);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
private void TryAutoAssignVideoClips()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,23 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 26613b5040884aa4486eff889fdf0eea
|
||||
AudioImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 8
|
||||
defaultSettings:
|
||||
serializedVersion: 2
|
||||
loadType: 2
|
||||
sampleRateSetting: 0
|
||||
sampleRateOverride: 44100
|
||||
compressionFormat: 1
|
||||
quality: 1
|
||||
conversionMode: 0
|
||||
preloadAudioData: 0
|
||||
platformSettingOverrides: {}
|
||||
forceToMono: 0
|
||||
normalize: 1
|
||||
loadInBackground: 1
|
||||
ambisonic: 0
|
||||
3D: 1
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a88f50e3064ffd54ba9d1ddf36f5d729
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
@@ -0,0 +1,27 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1c27fc5c2d1c39347874aad933096b27
|
||||
VideoClipImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 3
|
||||
frameRange: 0
|
||||
startFrame: -1
|
||||
endFrame: -1
|
||||
colorSpace: 0
|
||||
deinterlace: 0
|
||||
encodeAlpha: 0
|
||||
flipVertical: 0
|
||||
flipHorizontal: 0
|
||||
importAudio: 1
|
||||
targetSettings:
|
||||
:
|
||||
enableTranscoding: 1
|
||||
codec: 1
|
||||
resizeFormat: 0
|
||||
aspectRatio: 0
|
||||
customWidth: 1920
|
||||
customHeight: 1080
|
||||
bitrateMode: 2
|
||||
spatialQuality: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
@@ -0,0 +1,27 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e2fac5aa18afc054bb4d5d526ee66c5c
|
||||
VideoClipImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 3
|
||||
frameRange: 0
|
||||
startFrame: -1
|
||||
endFrame: -1
|
||||
colorSpace: 0
|
||||
deinterlace: 0
|
||||
encodeAlpha: 0
|
||||
flipVertical: 0
|
||||
flipHorizontal: 0
|
||||
importAudio: 1
|
||||
targetSettings:
|
||||
:
|
||||
enableTranscoding: 1
|
||||
codec: 1
|
||||
resizeFormat: 0
|
||||
aspectRatio: 0
|
||||
customWidth: 1920
|
||||
customHeight: 1080
|
||||
bitrateMode: 2
|
||||
spatialQuality: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user