From a36dc7c003a4f2055fbab16d724174f095a4072b Mon Sep 17 00:00:00 2001 From: bottlefish <781230111@qq.com> Date: Mon, 29 Jun 2026 16:34:26 +0800 Subject: [PATCH] Fix mobile render texture black screens --- .../Scripts/FixSystem/Memory/MemoryProcess.cs | 114 +++++++++++++++++- .../Scripts/MiniGame/Peipei/Eye/EyeSystem.cs | 97 +++++++++++++++ 2 files changed, 210 insertions(+), 1 deletion(-) diff --git a/Assets/Scripts/FixSystem/Memory/MemoryProcess.cs b/Assets/Scripts/FixSystem/Memory/MemoryProcess.cs index e84970960..44e6f72cf 100644 --- a/Assets/Scripts/FixSystem/Memory/MemoryProcess.cs +++ b/Assets/Scripts/FixSystem/Memory/MemoryProcess.cs @@ -1,10 +1,12 @@ using System.Collections; +using System.Collections.Generic; using UnityEngine; using DG.Tweening; using Yarn.Unity; using AibisDream.Framework; using Cinemachine; using UnityEngine.Rendering; +using UnityEngine.UI; using AibisDream.Kit; using UnityEngine.ResourceManagement.AsyncOperations; @@ -64,12 +66,14 @@ namespace AibisDream.FixSystem [SerializeField] private Material fadeMaterial; private Material runtimeMemoryMaterial; + private readonly List runtimeRenderTextures = new(); public void OpenMemoryView() { memoryGroup.SetActive(true); memoryView.gameObject.SetActive(true); - + EnsureMemoryRenderTargets(); + StartCoroutine(PrimeMemoryRenderTargets()); } public IEnumerator DropMemoryProjector() @@ -176,6 +180,114 @@ namespace AibisDream.FixSystem { if (runtimeMemoryMaterial != null) Destroy(runtimeMemoryMaterial); + + foreach (var renderTexture in runtimeRenderTextures) + { + if (renderTexture == null) + continue; + + renderTexture.Release(); + Destroy(renderTexture); + } + runtimeRenderTextures.Clear(); + } + + private void EnsureMemoryRenderTargets() + { + if (memoryGroup == null || memoryView == null) + return; + + var cameras = memoryGroup.GetComponentsInChildren(true); + foreach (var renderCamera in cameras) + { + if (renderCamera == null || renderCamera.targetTexture == null) + continue; + + renderCamera.allowHDR = false; + renderCamera.allowMSAA = false; + + var originalTexture = renderCamera.targetTexture; + var targetTexture = originalTexture; + if (ShouldReplaceRenderTexture(originalTexture)) + { + targetTexture = CreateCompatibleRenderTexture(originalTexture); + renderCamera.targetTexture = targetTexture; + RebindMemoryRawImages(originalTexture, targetTexture); + } + + if (!targetTexture.IsCreated()) + { + targetTexture.Create(); + } + } + } + + private static bool ShouldReplaceRenderTexture(RenderTexture renderTexture) + { + if (renderTexture == null) + return true; + + if (!SystemInfo.SupportsRenderTextureFormat(renderTexture.format)) + return true; + + var maxSize = Mathf.Min(SystemInfo.maxTextureSize, 2048); + return renderTexture.width > maxSize || renderTexture.height > maxSize; + } + + private RenderTexture CreateCompatibleRenderTexture(RenderTexture source) + { + var maxSize = Mathf.Min(SystemInfo.maxTextureSize, 2048); + var sourceWidth = source != null ? source.width : Screen.width; + var sourceHeight = source != null ? source.height : Screen.height; + var scale = Mathf.Min(1f, maxSize / (float)Mathf.Max(sourceWidth, sourceHeight)); + var width = Mathf.Max(1, Mathf.RoundToInt(sourceWidth * scale)); + var height = Mathf.Max(1, Mathf.RoundToInt(sourceHeight * scale)); + + var renderTexture = new RenderTexture(width, height, 24, RenderTextureFormat.ARGB32) + { + name = source != null ? $"{source.name}_RuntimeCompatible" : "Memory_RuntimeCompatible", + antiAliasing = 1, + useMipMap = false, + autoGenerateMips = false + }; + renderTexture.Create(); + runtimeRenderTextures.Add(renderTexture); + return renderTexture; + } + + private void RebindMemoryRawImages(Texture oldTexture, Texture newTexture) + { + var rawImages = memoryView.GetComponentsInChildren(true); + foreach (var rawImage in rawImages) + { + if (rawImage != null && rawImage.texture == oldTexture) + { + rawImage.texture = newTexture; + } + } + } + + private IEnumerator PrimeMemoryRenderTargets() + { + yield return null; + ForceRenderMemoryTargets(); + yield return new WaitForEndOfFrame(); + ForceRenderMemoryTargets(); + } + + private void ForceRenderMemoryTargets() + { + if (memoryGroup == null || !memoryGroup.activeInHierarchy) + return; + + var cameras = memoryGroup.GetComponentsInChildren(true); + foreach (var renderCamera in cameras) + { + if (renderCamera != null && renderCamera.enabled && renderCamera.targetTexture != null) + { + renderCamera.Render(); + } + } } private void CheckAllFound() diff --git a/Assets/Scripts/MiniGame/Peipei/Eye/EyeSystem.cs b/Assets/Scripts/MiniGame/Peipei/Eye/EyeSystem.cs index abf78d9df..5965f9a41 100644 --- a/Assets/Scripts/MiniGame/Peipei/Eye/EyeSystem.cs +++ b/Assets/Scripts/MiniGame/Peipei/Eye/EyeSystem.cs @@ -32,6 +32,7 @@ namespace AibisDream private EyeData _eyeData = new(); private Tween hsvShiftTween; private MouseFollowAndZoom mouseFollowAndZoom; + private RenderTexture runtimeEyeRenderTexture; /// /// 眼睛 RawImage 的故障/色相/饱和度等效果依赖 AllIn1SpriteShader(或兼容)材质上的属性。 @@ -82,6 +83,88 @@ namespace AibisDream return true; } + private bool EnsureEyeViewRenderTarget() + { + if (eyeImage == null) + { + Debug.LogError("[EyeSystem] eyeImage 未赋值,无法显示视觉模块画面。", this); + return false; + } + + if (cameraManager == null) + { + Debug.LogError("[EyeSystem] cameraManager 未赋值,无法渲染视觉模块画面。", this); + return false; + } + + var viewCamera = cameraManager.GetComponent(); + if (viewCamera == null) + { + Debug.LogError("[EyeSystem] cameraManager 上未找到 Camera 组件,无法渲染视觉模块画面。", cameraManager); + return false; + } + + viewCamera.allowHDR = false; + viewCamera.allowMSAA = false; + + var renderTexture = viewCamera.targetTexture; + if (renderTexture == null) + { + renderTexture = CreateRuntimeEyeRenderTexture(); + viewCamera.targetTexture = renderTexture; + } + + if (!renderTexture.IsCreated()) + { + renderTexture.Create(); + } + + if (eyeImage.texture != renderTexture) + { + eyeImage.texture = renderTexture; + } + + return true; + } + + private RenderTexture CreateRuntimeEyeRenderTexture() + { + var width = Mathf.Clamp(Screen.width, 1, 2048); + var height = Mathf.Clamp(Screen.height, 1, 2048); + + runtimeEyeRenderTexture = new RenderTexture(width, height, 24, RenderTextureFormat.ARGB32) + { + name = "Runtime Eye View RenderTexture", + antiAliasing = 1, + useMipMap = false, + autoGenerateMips = false + }; + runtimeEyeRenderTexture.Create(); + return runtimeEyeRenderTexture; + } + + private IEnumerator PrimeEyeViewRender() + { + yield return null; + ForceRenderEyeView(); + yield return new WaitForEndOfFrame(); + ForceRenderEyeView(); + } + + private void ForceRenderEyeView() + { + if (cameraManager == null || !cameraManager.gameObject.activeInHierarchy) + { + return; + } + + var viewCamera = cameraManager.GetComponent(); + if (viewCamera != null && viewCamera.enabled && viewCamera.targetTexture != null) + { + viewCamera.Render(); + } + } + public void Init() { FixSystemCenter.SystemDic.Register(this); @@ -119,11 +202,15 @@ namespace AibisDream { cameraManager.gameObject.SetActive(true); } + + EnsureEyeViewRenderTarget(); mouseFollowAndZoom.SetIsActive(true); mouseFollowAndZoom.SetIsLock(false); // 激活 ViewCamera 后再打开 EyeView OpenEyeView(); + ForceRenderEyeView(); + StartCoroutine(PrimeEyeViewRender()); // 进入视图时的逻辑 Debug.Log("EyeView entered."); } @@ -168,6 +255,16 @@ namespace AibisDream Debug.Log("EyeView exited."); } + private void OnDestroy() + { + if (runtimeEyeRenderTexture != null) + { + runtimeEyeRenderTexture.Release(); + Destroy(runtimeEyeRenderTexture); + runtimeEyeRenderTexture = null; + } + } + private void Start() { SetEyeColorState(_eyeData.currentState);