feat: 使用 ResourceSystem 异步加载精灵与关卡配置

Made-with: Cursor
This commit is contained in:
2026-03-27 15:42:46 +08:00
parent 28418edd44
commit 9a9645dfec
5 changed files with 107 additions and 42 deletions
@@ -1,4 +1,4 @@
using System.Collections;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
@@ -11,9 +11,12 @@ using Cinemachine;
using UnityEngine.Rendering;
using AibisDream.Kit;
using UnityEngine.EventSystems;
using UnityEngine.ResourceManagement.AsyncOperations;
public class MemoryProcess : MonoBehaviour
{
private const string MemorySpritePath = "Sprite/Memory/{0}.png";
public BubbleSlotGroup bubbleSlotGroup;
public GameObject memoryView;
public GameObject projector;
@@ -327,12 +330,15 @@ public class MemoryProcess : MonoBehaviour
{
fadeMaterial.SetFloat("_DirectionalDistortionFade", -15);
FavoritesManager.Instance.CloseFavorites();
Sprite memSprite = Resources.Load<Sprite>("Art/Memory/" + memName);
var memoryKey = string.Format(MemorySpritePath, memName);
var memoryHandle = ResourceSystem.LoadAsync<Sprite>(memoryKey);
yield return memoryHandle;
Sprite memSprite = memoryHandle.Status == AsyncOperationStatus.Succeeded ? memoryHandle.Result : null;
memoryFinishedspRender.sprite = memSprite;
memoryFinishedImageNoColor.sprite = memSprite;
if (memSprite == null)
{
Debug.LogError("Memory not found: " + memName);
Debug.LogError("Memory not found: " + memoryKey);
}
// AudioManager.PlayMemoryAudio("mem_" + memName);
@@ -390,12 +396,17 @@ public class MemoryProcess : MonoBehaviour
yield break;
}
Sprite memorySprite = Resources.Load<Sprite>("Art/Memory/" + PunchTape.MemoryIndex);
var searchMemoryKey = string.Format(MemorySpritePath, PunchTape.MemoryIndex);
var searchMemoryHandle = ResourceSystem.LoadAsync<Sprite>(searchMemoryKey);
yield return searchMemoryHandle;
Sprite memorySprite = searchMemoryHandle.Status == AsyncOperationStatus.Succeeded
? searchMemoryHandle.Result
: null;
memoryFinishedspRender.sprite = memorySprite;
memoryFinishedImageNoColor.sprite = memorySprite;
if (memorySprite == null)
{
Debug.LogError("Memory not found: " + PunchTape.MemoryIndex);
Debug.LogError("Memory not found: " + searchMemoryKey);
}
MemoryProcessVloume.weight = 1;
@@ -1,5 +1,7 @@
using System.Collections;
using System.Collections;
using AibisDream.FixSystem;
using AibisDream.Framework;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine;
using Yarn.Unity;
@@ -21,25 +23,27 @@ namespace AibisDream.MiniGame.Language
/// <param name="levelName">关卡配置名称(Resources/AnalysisLevels/ 下的文件名)</param>
/// <param name="completionNode">完成时触发的对话节点(可选,会覆盖配置中的节点)</param>
[YarnCommand("start_analysis")]
public static void StartAnalysis(string levelName, string completionNode = "")
public static IEnumerator StartAnalysis(string levelName, string completionNode = "")
{
if (AnalysisModeManager == null)
{
Debug.LogError("AnalysisModeManager 未找到!请确保场景中有 AnalysisModeManager 组件。");
return;
yield break;
}
// 从 Resources 加载关卡配置
AnalysisModeData levelData = Resources.Load<AnalysisModeData>($"AnalysisLevels/{levelName}");
if (levelData == null)
var handler = ResourceSystem.LoadAsync<AnalysisModeData>($"AnalysisLevels/{levelName}");
yield return handler;
if (handler.Status == AsyncOperationStatus.Succeeded && handler.Result != null)
{
Debug.LogError($"找不到关卡配置: Resources/AnalysisLevels/{levelName}.asset");
return;
AnalysisModeData levelData = handler.Result;
AnalysisModeManager.OpenView(levelData, completionNode);
}
else
{
Debug.LogError($"找不到关卡配置: {levelName}.asset");
yield break;
}
// 启动分析模式
AnalysisModeManager.OpenView(levelData, completionNode);
}
/// <summary>
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
@@ -10,12 +10,15 @@ using AibisDream.FixSystem;
using Cinemachine;
using AibisDream.Framework;
using AibisDream.Kit;
using UnityEngine.ResourceManagement.AsyncOperations;
using Sequence = DG.Tweening.Sequence;
namespace AibisDream
{
public class EyeSystem : MonoBehaviour
{
private const string MemorySpritePath = "Sprite/Memory/{0}.png";
public BubbleSlotGroup bubbleSlotGroup;
[SerializeField] private List<EyeTarget> targets = new(); // 保存目标列表
public List<EyeTarget> Targets => targets; // 提供目标列表的公共访问
@@ -307,10 +310,6 @@ namespace AibisDream
Debug.LogError("No eyeImage");
yield break;
}
// AudioManager.RandomPlayInteraction("colorcorrect_in");
// AudioManager.PlayLoopAudio("colorcorrect_loop");
//AudioManager.Instance.PlaySfx("event:/ActionFB/visualturn");
// _HsvShift 从 0 ~ 360 来回变化
hsvShiftTween = DOTween
.To(() => material.GetFloat("_HsvShift"), x => material.SetFloat("_HsvShift", x), 360, 1f)
@@ -367,14 +366,16 @@ namespace AibisDream
if (memoryName != null)
{
Sprite memorySprite = Resources.Load<Sprite>("Art/Memory/" + memoryName);
if (memorySprite == null)
var memoryKey = string.Format(MemorySpritePath, memoryName);
var memoryHandle = ResourceSystem.LoadAsync<Sprite>(memoryKey);
yield return memoryHandle;
if (memoryHandle.Status != AsyncOperationStatus.Succeeded || memoryHandle.Result == null)
{
Debug.LogWarning("Memory not found: " + memoryName);
Debug.LogWarning("Memory not found: " + memoryKey);
yield break;
}
memoryRender.sprite = memorySprite;
memoryRender.sprite = memoryHandle.Result;
// 使 memoryRender 可见
memoryRender.gameObject.SetActive(true);
@@ -1,13 +1,19 @@
using System.Collections;
using System;
using System.Collections;
using AibisDream.Framework;
using AibisDream.Kit;
using AibisDream.Utility;
using DG.Tweening;
using UnityEngine;
using UnityEngine.ResourceManagement.AsyncOperations;
namespace AibisDream
{
public class SpriteShowcase : Singleton<SpriteShowcase>
{
/// <summary>Addressable Key 模板,与 Scene_Dream 中梦境图 Address 一致。</summary>
private const string DreamSpritePath = "Dream/梦境/{0}.png";
[SerializeField] private SpriteRenderer _spriteRenderer;
[SerializeField] private SpriteRenderer _backgroundSpriteRenderer;
[SerializeField] private SpriteRenderer _largeSpriteRenderer;
@@ -30,10 +36,29 @@ namespace AibisDream
}
}
private static string NormalizeDreamPicName(string picName)
{
if (string.IsNullOrEmpty(picName)) return picName;
return picName.EndsWith(".png", StringComparison.OrdinalIgnoreCase)
? picName.Substring(0, picName.Length - 4)
: picName;
}
private IEnumerator LoadDreamSpriteInto(SpriteRenderer target, string picName)
{
var key = string.Format(DreamSpritePath, NormalizeDreamPicName(picName));
var handle = ResourceSystem.LoadAsync<Sprite>(key);
yield return handle;
if (handle.Status == AsyncOperationStatus.Succeeded && handle.Result != null)
target.sprite = handle.Result;
else
Debug.LogError($"[SpriteShowcase] Failed to load sprite: {key}");
}
/// <summary>
/// 显示物体(小图)
/// </summary>
/// <param name="picName">图片名称(相对于 Resources/Art/Obj/ 的路径</param>
/// <param name="picName">图片名(无扩展名,与 Yarn 中一致;Addressable Key 由 <see cref="DreamSpritePath"/> 拼接</param>
/// <param name="duration">淡入时长</param>
/// <returns>协程</returns>
public IEnumerator ShowObj(string picName, float duration = 1)
@@ -46,18 +71,15 @@ namespace AibisDream
_spriteRenderer.gameObject.SetActive(true);
// 切换图片
var newSprite = Resources.Load<Sprite>($"Art/Obj/{picName}");
_spriteRenderer.sprite = newSprite;
yield return LoadDreamSpriteInto(_spriteRenderer, picName);
// 然后淡入
yield return _spriteRenderer.DOFade(1, duration).WaitForCompletion();
}
/// <summary>
/// 显示大图
/// </summary>
/// <param name="picName">图片名称(相对于 Resources/Art/Obj/ 的路径</param>
/// <param name="picName">图片名(无扩展名,与 Yarn 中一致;Addressable Key 由 <see cref="DreamSpritePath"/> 拼接</param>
/// <param name="duration">淡入时长</param>
/// <returns>协程</returns>
public IEnumerator ShowLargeObj(string picName, float duration = 1)
@@ -72,11 +94,8 @@ namespace AibisDream
_largeSpriteRenderer.gameObject.SetActive(true);
// 切换图片
var newSprite = Resources.Load<Sprite>($"Art/Obj/{picName}");
_largeSpriteRenderer.sprite = newSprite;
yield return LoadDreamSpriteInto(_largeSpriteRenderer, picName);
// 然后淡入
yield return _largeSpriteRenderer.DOFade(1, duration).WaitForCompletion();
}
@@ -178,4 +197,4 @@ namespace AibisDream
StartCoroutine(FadeOutAsync(duration));
}
}
}
}
+34 -4
View File
@@ -1,9 +1,11 @@
using System.Collections;
using System;
using System.Collections;
using AibisDream.Framework;
using AibisDream.Kit;
using DG.Tweening;
using RainbowArt.CleanFlatUI;
using UnityEngine;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.UI;
namespace AibisDream.UI
@@ -19,6 +21,9 @@ namespace AibisDream.UI
[Header("Obj尺寸参数")] public float objWidth;
public float objHeight;
/// <summary>Addressable Key 模板,与 Obj 精灵 Address 一致。</summary>
private const string ObjSpritePath = "Sprite/Obj/{0}.png";
#region
private Image _fadeImage;
@@ -52,6 +57,14 @@ namespace AibisDream.UI
_timeTurner = transform.GetComponentInChildren<TimeTurner>();
}
private static string NormalizeObjPicName(string picName)
{
if (string.IsNullOrEmpty(picName)) return picName;
return picName.EndsWith(".png", StringComparison.OrdinalIgnoreCase)
? picName.Substring(0, picName.Length - 4)
: picName;
}
public IEnumerator FadeInAsync(float duration = 1)
{
return _fadeImage.FadeInAsync(duration);
@@ -80,8 +93,16 @@ namespace AibisDream.UI
{
_showObjPanel.gameObject.SetActive(true);
// 切换图片
var newSprite = Resources.Load<Sprite>($"Art/Obj/{picName}");
var key = string.Format(ObjSpritePath, NormalizeObjPicName(picName));
var handle = ResourceSystem.LoadAsync<Sprite>(key);
yield return handle;
if (handle.Status != AsyncOperationStatus.Succeeded || handle.Result == null)
{
Debug.LogError($"[PlayToolPanel] Failed to load sprite: {key}");
yield break;
}
var newSprite = handle.Result;
// 获取图片的长宽比
var imageAspect = (float)newSprite.texture.width / newSprite.texture.height;
@@ -110,7 +131,16 @@ namespace AibisDream.UI
public IEnumerator ShowFullScreen(string picName)
{
_fullScreenImage.sprite = Resources.Load<Sprite>($"Art/Obj/{picName}");
var key = string.Format(ObjSpritePath, NormalizeObjPicName(picName));
var handle = ResourceSystem.LoadAsync<Sprite>(key);
yield return handle;
if (handle.Status != AsyncOperationStatus.Succeeded || handle.Result == null)
{
Debug.LogError($"[PlayToolPanel] Failed to load sprite: {key}");
yield break;
}
_fullScreenImage.sprite = handle.Result;
// 淡入
yield return _fullScreenImage.FadeInAsync(1);