Merge branch '7.2春优化' into 'develop'
fix(ui): 主界面加载前黑屏遮罩,就绪后再淡出 See merge request aibis-dream/aibis-dream!725
This commit is contained in:
@@ -516,6 +516,6 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
defaultValue: 0
|
||||
sliderMaxValue: 6
|
||||
lockThreshold: 0.06
|
||||
lockThreshold: 0.08
|
||||
openAsset: {fileID: 11400000, guid: f3a3a8f61c646e54ea285290f46c6812, type: 2}
|
||||
closeAsset: {fileID: 11400000, guid: f5cbafa33288ca949bbde2b8955f4b7b, type: 2}
|
||||
|
||||
@@ -40,7 +40,7 @@ ScriptedImporter:
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spritePixelsToUnits: 21.5
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 0
|
||||
generateCubemap: 6
|
||||
@@ -100,7 +100,7 @@ ScriptedImporter:
|
||||
addSortingGroup: 1
|
||||
addShadowCasters: 0
|
||||
importFileNodeState: 1
|
||||
platformSettingsDirtyTick: 639183460123309200
|
||||
platformSettingsDirtyTick: 639186120455284200
|
||||
textureAssetName:
|
||||
singleSpriteImportData:
|
||||
- name:
|
||||
|
||||
@@ -133,27 +133,33 @@ Shader "AIBIS/EyeUnifiedSprite"
|
||||
return saturate(mul(mat, color));
|
||||
}
|
||||
|
||||
fixed4 sampleMainTex(float2 uv)
|
||||
half4 sampleMainTex(float2 uv)
|
||||
{
|
||||
return tex2D(_MainTex, uv);
|
||||
return tex2D(_MainTex, saturate(uv));
|
||||
}
|
||||
|
||||
fixed4 gaussianBlurSample(float2 uv, float stepSize)
|
||||
half3 GaussianBlurRgb(float2 uv, float stepSize)
|
||||
{
|
||||
float angle = 1.937315; // ~111 deg, matches MemoryTuningSprite
|
||||
float2 stepDir = float2(sin(angle), cos(angle));
|
||||
float2 stepUv = stepDir * stepSize;
|
||||
|
||||
fixed4 col = sampleMainTex(uv) * 0.18;
|
||||
col += sampleMainTex(uv + stepUv * 1.0) * 0.15;
|
||||
col += sampleMainTex(uv - stepUv * 1.0) * 0.15;
|
||||
col += sampleMainTex(uv + stepUv * 2.0) * 0.12;
|
||||
col += sampleMainTex(uv - stepUv * 2.0) * 0.12;
|
||||
col += sampleMainTex(uv + stepUv * 3.0) * 0.09;
|
||||
col += sampleMainTex(uv - stepUv * 3.0) * 0.09;
|
||||
col += sampleMainTex(uv + stepUv * 4.0) * 0.05;
|
||||
col += sampleMainTex(uv - stepUv * 4.0) * 0.05;
|
||||
return col;
|
||||
#if defined(SHADER_API_MOBILE)
|
||||
half3 rgb = sampleMainTex(uv).rgb * 0.34;
|
||||
rgb += sampleMainTex(uv + stepUv).rgb * 0.33;
|
||||
rgb += sampleMainTex(uv - stepUv).rgb * 0.33;
|
||||
#else
|
||||
half3 rgb = sampleMainTex(uv).rgb * 0.18;
|
||||
rgb += sampleMainTex(uv + stepUv * 1.0).rgb * 0.15;
|
||||
rgb += sampleMainTex(uv - stepUv * 1.0).rgb * 0.15;
|
||||
rgb += sampleMainTex(uv + stepUv * 2.0).rgb * 0.12;
|
||||
rgb += sampleMainTex(uv - stepUv * 2.0).rgb * 0.12;
|
||||
rgb += sampleMainTex(uv + stepUv * 3.0).rgb * 0.09;
|
||||
rgb += sampleMainTex(uv - stepUv * 3.0).rgb * 0.09;
|
||||
rgb += sampleMainTex(uv + stepUv * 4.0).rgb * 0.05;
|
||||
rgb += sampleMainTex(uv - stepUv * 4.0).rgb * 0.05;
|
||||
#endif
|
||||
return rgb;
|
||||
}
|
||||
|
||||
fixed4 sampleSprite(float2 uv, float2 screenUv)
|
||||
@@ -171,14 +177,14 @@ Shader "AIBIS/EyeUnifiedSprite"
|
||||
float noise = hash21(floor(uv * 42.0) + floor(_Time.y * 16.0));
|
||||
distortedUv += (noise - 0.5) * _DistortAmount;
|
||||
|
||||
// Match legacy AllIn1 scale (~offset * fade * 0.005); avoid MemoryTuning's 0.014 base.
|
||||
float2 texel = _MainTex_TexelSize.xy;
|
||||
float2 texel = max(abs(_MainTex_TexelSize.xy), float2(1e-5, 1e-5));
|
||||
float stepSize = length(texel) + _BlurSize;
|
||||
fixed4 col = sampleMainTex(distortedUv);
|
||||
fixed4 blurCol = gaussianBlurSample(distortedUv, stepSize);
|
||||
fixed3 blurredRgb = GaussianBlurRgb(distortedUv, stepSize);
|
||||
|
||||
float blurStrength = pow(saturate(_BlurAmount), 0.75);
|
||||
return lerp(col, blurCol, blurStrength);
|
||||
col.rgb = lerp(col.rgb, blurredRgb, blurStrength);
|
||||
return col;
|
||||
}
|
||||
|
||||
fixed4 frag(v2f i) : SV_Target
|
||||
|
||||
@@ -68,6 +68,7 @@ Shader "UI/EyeViewportOverlay"
|
||||
fixed4 color : COLOR;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 worldPosition : TEXCOORD1;
|
||||
float4 screenPosition : TEXCOORD2;
|
||||
};
|
||||
|
||||
sampler2D _MainTex;
|
||||
@@ -85,6 +86,7 @@ Shader "UI/EyeViewportOverlay"
|
||||
o.worldPosition = v.vertex;
|
||||
o.vertex = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.uv;
|
||||
o.screenPosition = ComputeScreenPos(o.vertex);
|
||||
o.color = v.color * _Color;
|
||||
return o;
|
||||
}
|
||||
@@ -118,7 +120,8 @@ Shader "UI/EyeViewportOverlay"
|
||||
|
||||
fixed4 frag(v2f i) : SV_Target
|
||||
{
|
||||
float alpha = ComputeViewportAlpha(i.uv);
|
||||
float2 screenUv = i.screenPosition.xy / max(i.screenPosition.w, 0.0001);
|
||||
float alpha = ComputeViewportAlpha(saturate(screenUv));
|
||||
fixed4 col = fixed4(i.color.rgb, i.color.a * alpha);
|
||||
col.a *= UnityGet2DClipping(i.worldPosition.xy, _ClipRect);
|
||||
return col;
|
||||
|
||||
+802
-802
File diff suppressed because it is too large
Load Diff
+803
-801
File diff suppressed because it is too large
Load Diff
@@ -3172,7 +3172,7 @@ GameObject:
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &960307108
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -3188,9 +3188,9 @@ RectTransform:
|
||||
- {fileID: 231219352}
|
||||
m_Father: {fileID: 367483172}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 1}
|
||||
m_AnchorMax: {x: 0, y: 1}
|
||||
m_AnchoredPosition: {x: 94, y: -25}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 64, y: 100}
|
||||
m_Pivot: {x: 1, y: 1}
|
||||
--- !u!222 &960307110
|
||||
|
||||
@@ -20,20 +20,19 @@ namespace AibisDream.FixSystem
|
||||
private const float ProjectorMoveDuration = 2f;
|
||||
private const float MaxClarityDistortion = 1f;
|
||||
private const float MaxFrequencyBlur = 0.6f;
|
||||
private const float MobileMaxFrequencyBlur = 0.45f;
|
||||
private const float MinPixelDensity = 18f;
|
||||
private const float MobileMinPixelDensity = 24f;
|
||||
private const float MaxPixelDensity = 96f;
|
||||
private const string DirectionalDistortionFadeProperty = "_DirectionalDistortionFade";
|
||||
|
||||
private static readonly int EnablePixelateId = Shader.PropertyToID("_EnablePixelate");
|
||||
private static readonly int FrequencyTuningId = Shader.PropertyToID("_FrequencyTuning");
|
||||
private static readonly int ClarityTuningId = Shader.PropertyToID("_ClarityTuning");
|
||||
private static readonly int DirectionalDistortionFadeId = Shader.PropertyToID(DirectionalDistortionFadeProperty);
|
||||
private static readonly int PixelateFadeId = Shader.PropertyToID("_PixelateFade");
|
||||
private static readonly int PixelatePixelDensityId = Shader.PropertyToID("_PixelatePixelDensity");
|
||||
private static readonly int EnableGaussianBlurId = Shader.PropertyToID("_EnableGaussianBlur");
|
||||
private static readonly int GaussianBlurFadeId = Shader.PropertyToID("_GaussianBlurFade");
|
||||
private static readonly int GaussianBlurOffsetId = Shader.PropertyToID("_GaussianBlurOffset");
|
||||
private static readonly int EnableUvDistortId = Shader.PropertyToID("_EnableUVDistort");
|
||||
private static readonly int UvDistortFadeId = Shader.PropertyToID("_UVDistortFade");
|
||||
private static readonly int MemoryGrayscaleId = Shader.PropertyToID("_MemoryGrayscale");
|
||||
private static readonly int MemoryContrastId = Shader.PropertyToID("_MemoryContrast");
|
||||
@@ -76,8 +75,10 @@ namespace AibisDream.FixSystem
|
||||
[SerializeField] private MemoryPunchTapeSlot punchTapeSlot;
|
||||
|
||||
[SerializeField] private Material fadeMaterial;
|
||||
[SerializeField] private Shader memoryTuningShader;
|
||||
private Material runtimeMemoryMaterial;
|
||||
private Material runtimeNoColorMemoryMaterial;
|
||||
private bool spriteShaderTuningAvailable;
|
||||
private Tween overlayTween;
|
||||
|
||||
public void OpenMemoryView()
|
||||
@@ -276,14 +277,14 @@ namespace AibisDream.FixSystem
|
||||
{
|
||||
frequencySlider.OnTuningChanged -= ApplyFrequencyTuning;
|
||||
frequencySlider.Init(memoryFrequencyVolume);
|
||||
frequencySlider.SetVolumeOutputEnabled(!useSpriteShaderTuning);
|
||||
frequencySlider.SetVolumeOutputEnabled(!spriteShaderTuningAvailable);
|
||||
frequencySlider.OnTuningChanged += ApplyFrequencyTuning;
|
||||
}
|
||||
if (claritySlider != null)
|
||||
{
|
||||
claritySlider.OnTuningChanged -= ApplyClarityTuning;
|
||||
claritySlider.Init(memoryClarityVolume);
|
||||
claritySlider.SetVolumeOutputEnabled(!useSpriteShaderTuning);
|
||||
claritySlider.SetVolumeOutputEnabled(!spriteShaderTuningAvailable);
|
||||
claritySlider.OnTuningChanged += ApplyClarityTuning;
|
||||
}
|
||||
|
||||
@@ -463,33 +464,31 @@ namespace AibisDream.FixSystem
|
||||
|
||||
private void ApplyFrequencyTuning(float strength)
|
||||
{
|
||||
if (!useSpriteShaderTuning || fadeMaterial == null)
|
||||
if (!spriteShaderTuningAvailable || fadeMaterial == null)
|
||||
return;
|
||||
|
||||
bool active = strength > 0.001f;
|
||||
float blurCap = Application.isMobilePlatform ? MobileMaxFrequencyBlur : MaxFrequencyBlur;
|
||||
float minPixelDensity = Application.isMobilePlatform ? MobileMinPixelDensity : MinPixelDensity;
|
||||
|
||||
SetFloatIfExists(FrequencyTuningId, strength);
|
||||
SetFloatIfExists(EnablePixelateId, active ? 1f : 0f);
|
||||
SetFloatIfExists(PixelateFadeId, strength);
|
||||
SetFloatIfExists(PixelatePixelDensityId, Mathf.Lerp(MaxPixelDensity, MinPixelDensity, strength));
|
||||
SetFloatIfExists(EnableGaussianBlurId, active ? 1f : 0f);
|
||||
SetFloatIfExists(GaussianBlurFadeId, strength * MaxFrequencyBlur);
|
||||
SetFloatIfExists(PixelatePixelDensityId, Mathf.Lerp(MaxPixelDensity, minPixelDensity, strength));
|
||||
SetFloatIfExists(GaussianBlurFadeId, strength * blurCap);
|
||||
SetFloatIfExists(GaussianBlurOffsetId, Mathf.Lerp(0.05f, 0.35f, strength));
|
||||
}
|
||||
|
||||
private void ApplyClarityTuning(float strength)
|
||||
{
|
||||
if (!useSpriteShaderTuning || fadeMaterial == null)
|
||||
if (!spriteShaderTuningAvailable || fadeMaterial == null)
|
||||
return;
|
||||
|
||||
bool active = strength > 0.001f;
|
||||
SetFloatIfExists(ClarityTuningId, strength);
|
||||
SetFloatIfExists(EnableUvDistortId, active ? 1f : 0f);
|
||||
SetFloatIfExists(UvDistortFadeId, strength * MaxClarityDistortion);
|
||||
}
|
||||
|
||||
private void ResetSpriteTuning()
|
||||
{
|
||||
if (!useSpriteShaderTuning || fadeMaterial == null)
|
||||
if (!spriteShaderTuningAvailable || fadeMaterial == null)
|
||||
return;
|
||||
|
||||
ApplyFrequencyTuning(0f);
|
||||
@@ -528,6 +527,7 @@ namespace AibisDream.FixSystem
|
||||
|
||||
private void PrepareRuntimeMemoryMaterial()
|
||||
{
|
||||
spriteShaderTuningAvailable = false;
|
||||
if (!useSpriteShaderTuning || !HasMemoryGraphic())
|
||||
return;
|
||||
|
||||
@@ -535,12 +535,20 @@ namespace AibisDream.FixSystem
|
||||
if (baseMaterial == null)
|
||||
baseMaterial = fadeMaterial;
|
||||
|
||||
var shader = baseMaterial != null ? baseMaterial.shader : null;
|
||||
var shader = memoryTuningShader;
|
||||
if (shader == null && baseMaterial != null)
|
||||
shader = baseMaterial.shader;
|
||||
if (shader == null || shader.name != "AibisDream/MemoryTuningSprite")
|
||||
shader = Shader.Find("AibisDream/MemoryTuningSprite");
|
||||
if (shader == null)
|
||||
{
|
||||
Debug.LogWarning("[MemoryProcess] 未找到 AibisDream/MemoryTuningSprite,调频将回退到当前材质表现。", this);
|
||||
Debug.LogWarning("[MemoryProcess] 未找到 AibisDream/MemoryTuningSprite,调频将回退到 Volume 后处理。", this);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!shader.isSupported)
|
||||
{
|
||||
Debug.LogWarning("[MemoryProcess] MemoryTuningSprite 在当前平台不受支持,调频将回退到 Volume 后处理。", this);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -560,6 +568,7 @@ namespace AibisDream.FixSystem
|
||||
SetNoColorMemoryMaterial(runtimeNoColorMemoryMaterial);
|
||||
}
|
||||
|
||||
spriteShaderTuningAvailable = true;
|
||||
ResetSpriteTuning();
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace AibisDream.FixSystem
|
||||
{
|
||||
[SerializeField] private float defaultValue = 0f;
|
||||
[SerializeField] private float sliderMaxValue = 6f;
|
||||
[SerializeField] private float lockThreshold = 0.06f;
|
||||
[SerializeField] private float lockThreshold = 0.08f;
|
||||
[SerializeField] private TimelineAsset openAsset;
|
||||
[SerializeField] private TimelineAsset closeAsset;
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using AibisDream.Kit;
|
||||
using System.Collections;
|
||||
using AibisDream.Kit;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Localization;
|
||||
using UnityEngine.Localization.Settings;
|
||||
@@ -137,5 +138,23 @@ namespace AibisDream.Framework
|
||||
{
|
||||
await LocalizationSettings.InitializationOperation.Task;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 等待本地化系统初始化完成(含 SettingLoader 触发的语言切换)。
|
||||
/// </summary>
|
||||
public static IEnumerator WaitUntilReady()
|
||||
{
|
||||
yield return LocalizationSettings.InitializationOperation;
|
||||
yield return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 等待 LocalizeStringEvent 等 UI 组件刷新文案。
|
||||
/// </summary>
|
||||
public static IEnumerator WaitForUIRefresh()
|
||||
{
|
||||
yield return null;
|
||||
Canvas.ForceUpdateCanvases();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,8 @@ namespace AibisDream
|
||||
|
||||
#endregion
|
||||
|
||||
private const float MainMenuFadeDuration = 0.5f;
|
||||
|
||||
private BindProperty<TalkSceneSO> _currentTalkSceneSo;
|
||||
public override void OnSingletonInit()
|
||||
{
|
||||
@@ -36,9 +38,28 @@ namespace AibisDream
|
||||
// 场景So事件注册
|
||||
_currentTalkSceneSo = new BindProperty<TalkSceneSO>();
|
||||
|
||||
ActionKit.Sequence()
|
||||
.Callback(() => EnumEventSystem.Global.Send(GameLoopEnum.AppStart))
|
||||
.Start(this);
|
||||
StartCoroutine(AppBootstrapCoroutine());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 启动主界面:先黑屏,待本地化与 UI 就绪后再淡出,避免玩家看到初始化过程。
|
||||
/// </summary>
|
||||
private IEnumerator AppBootstrapCoroutine()
|
||||
{
|
||||
var playTool = UIManager.Instance.GetPanel<PlayToolPanel>();
|
||||
UIManager.Instance.ShowPanel<PlayToolPanel>();
|
||||
playTool?.ApplyFadeScreenCovered(true);
|
||||
|
||||
yield return LocalizationKit.WaitUntilReady();
|
||||
|
||||
EnumEventSystem.Global.Send(GameLoopEnum.AppStart);
|
||||
|
||||
yield return LocalizationKit.WaitForUIRefresh();
|
||||
|
||||
if (playTool != null)
|
||||
{
|
||||
yield return playTool.FadeOutAsync(MainMenuFadeDuration);
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadAllSceneSos()
|
||||
@@ -202,7 +223,12 @@ namespace AibisDream
|
||||
|
||||
private IEnumerator RestartCoroutine()
|
||||
{
|
||||
UIManager.Instance.GetPanel<PlayToolPanel>().FadeInSync(0.1f);
|
||||
var playTool = UIManager.Instance.GetPanel<PlayToolPanel>();
|
||||
UIManager.Instance.ShowPanel<PlayToolPanel>();
|
||||
if (playTool != null)
|
||||
{
|
||||
yield return playTool.FadeInAsync(MainMenuFadeDuration);
|
||||
}
|
||||
|
||||
// 清理所有系统注册
|
||||
if (FixSystemCenter.SystemDic != null)
|
||||
@@ -210,10 +236,15 @@ namespace AibisDream
|
||||
FixSystemCenter.SystemDic.Clear();
|
||||
}
|
||||
|
||||
playTool?.ClearPresentationEffects();
|
||||
|
||||
// 执行场景卸载等功能
|
||||
CameraKit.Instance.ResetCamera();
|
||||
yield return SceneLoader.Instance.UnloadSceneAsync();
|
||||
DialogController.Instance.StopDialog();
|
||||
|
||||
yield return LocalizationKit.WaitUntilReady();
|
||||
|
||||
EnumEventSystem.Global.Send(GameLoopEnum.GameQuit);
|
||||
// 音频继续
|
||||
AudioManager.Instance.UnPauseAll();
|
||||
@@ -222,7 +253,12 @@ namespace AibisDream
|
||||
// 关闭结束面板
|
||||
UIManager.Instance.HidePanel<EndPanel>();
|
||||
|
||||
yield return UIManager.Instance.GetPanel<PlayToolPanel>().FadeOutAsync();
|
||||
yield return LocalizationKit.WaitForUIRefresh();
|
||||
|
||||
if (playTool != null)
|
||||
{
|
||||
yield return playTool.FadeOutAsync(MainMenuFadeDuration);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -263,6 +263,12 @@ public class EyeTarget : MonoBehaviour
|
||||
return;
|
||||
}
|
||||
|
||||
if (!shader.isSupported)
|
||||
{
|
||||
Debug.LogError($"[EyeTarget] AIBIS/EyeUnifiedSprite 在当前平台不受支持:{name}", this);
|
||||
return;
|
||||
}
|
||||
|
||||
Material currentMaterial = Application.isPlaying
|
||||
? spriteRenderer.material
|
||||
: spriteRenderer.sharedMaterial;
|
||||
|
||||
@@ -23,9 +23,14 @@ namespace AibisDream
|
||||
/// <summary>Persistence:本遮罩=0,UI Canvas=1,Dialog Canvas=3。</summary>
|
||||
[SerializeField] private int sortingOrder;
|
||||
|
||||
[Tooltip("Assign in Inspector so the shader is included in builds. Falls back to Shader.Find at runtime.")]
|
||||
[SerializeField] private Shader overlayShader;
|
||||
|
||||
private Canvas overlayCanvas;
|
||||
private Image overlayImage;
|
||||
private Material instanceMaterial;
|
||||
private bool overlayShaderAvailable;
|
||||
private bool overlayFallbackLogged;
|
||||
private EyeVisualSettings activeSettings;
|
||||
private Coroutine autoBlinkRoutine;
|
||||
private Tween blinkTween;
|
||||
@@ -251,6 +256,7 @@ namespace AibisDream
|
||||
return Application.isPlaying
|
||||
&& moduleActive
|
||||
&& !editorPreviewActive
|
||||
&& overlayShaderAvailable
|
||||
&& settings != null
|
||||
&& settings.enableViewportOverlay;
|
||||
}
|
||||
@@ -279,6 +285,12 @@ namespace AibisDream
|
||||
}
|
||||
|
||||
PrepareHierarchyIfNeeded();
|
||||
if (!overlayShaderAvailable || instanceMaterial == null)
|
||||
{
|
||||
DisableOverlayFallback();
|
||||
return;
|
||||
}
|
||||
|
||||
ApplyCanvasRenderSettings();
|
||||
activeSettings = settings;
|
||||
ApplySettings(settings);
|
||||
@@ -409,6 +421,16 @@ namespace AibisDream
|
||||
EnsureOverlayHierarchy();
|
||||
hierarchyReady = overlayCanvas != null;
|
||||
|
||||
if (!overlayShaderAvailable || instanceMaterial == null)
|
||||
{
|
||||
if (moduleActive || editorPreviewActive)
|
||||
{
|
||||
DisableOverlayFallback();
|
||||
}
|
||||
|
||||
yield break;
|
||||
}
|
||||
|
||||
if (activeSettings != null && instanceMaterial != null)
|
||||
{
|
||||
PushViewportParams(activeSettings);
|
||||
@@ -420,46 +442,134 @@ namespace AibisDream
|
||||
|
||||
private void EnsureOverlayHierarchy()
|
||||
{
|
||||
if (overlayCanvas == null)
|
||||
{
|
||||
overlayCanvas = FindExistingOverlayCanvas();
|
||||
}
|
||||
|
||||
if (overlayCanvas == null)
|
||||
{
|
||||
var canvasGo = new GameObject("EyeViewportOverlayCanvas");
|
||||
canvasGo.transform.SetParent(transform, false);
|
||||
|
||||
overlayCanvas = canvasGo.AddComponent<Canvas>();
|
||||
overlayCanvas.pixelPerfect = false;
|
||||
|
||||
var scaler = canvasGo.AddComponent<CanvasScaler>();
|
||||
scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
|
||||
scaler.referenceResolution = new Vector2(1920f, 1080f);
|
||||
scaler.matchWidthOrHeight = 0.5f;
|
||||
|
||||
canvasGo.AddComponent<CanvasScaler>();
|
||||
canvasGo.AddComponent<GraphicRaycaster>();
|
||||
}
|
||||
|
||||
var imageGo = new GameObject("Overlay", typeof(RectTransform));
|
||||
imageGo.transform.SetParent(canvasGo.transform, false);
|
||||
NormalizeCanvasTransform(overlayCanvas.transform);
|
||||
overlayCanvas.pixelPerfect = false;
|
||||
|
||||
var rect = (RectTransform)imageGo.transform;
|
||||
rect.anchorMin = Vector2.zero;
|
||||
rect.anchorMax = Vector2.one;
|
||||
rect.offsetMin = Vector2.zero;
|
||||
rect.offsetMax = Vector2.zero;
|
||||
var scaler = overlayCanvas.GetComponent<CanvasScaler>();
|
||||
if (scaler == null)
|
||||
{
|
||||
scaler = overlayCanvas.gameObject.AddComponent<CanvasScaler>();
|
||||
}
|
||||
scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
|
||||
scaler.referenceResolution = new Vector2(1920f, 1080f);
|
||||
scaler.matchWidthOrHeight = 0.5f;
|
||||
|
||||
overlayImage = imageGo.AddComponent<Image>();
|
||||
overlayImage.raycastTarget = false;
|
||||
overlayImage.color = Color.black;
|
||||
SetupMaterial();
|
||||
if (overlayCanvas.GetComponent<GraphicRaycaster>() == null)
|
||||
{
|
||||
overlayCanvas.gameObject.AddComponent<GraphicRaycaster>();
|
||||
}
|
||||
|
||||
EnsureOverlayImage();
|
||||
if (overlayImage != null && instanceMaterial == null && !TrySetupOverlayMaterial())
|
||||
{
|
||||
SetOverlayActive(false);
|
||||
}
|
||||
|
||||
ApplyCanvasRenderSettings();
|
||||
}
|
||||
|
||||
private void SetupMaterial()
|
||||
private Canvas FindExistingOverlayCanvas()
|
||||
{
|
||||
Shader shader = Shader.Find("UI/EyeViewportOverlay");
|
||||
foreach (var canvas in GetComponentsInChildren<Canvas>(true))
|
||||
{
|
||||
if (canvas != null && canvas.gameObject.name == "EyeViewportOverlayCanvas")
|
||||
{
|
||||
return canvas;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void EnsureOverlayImage()
|
||||
{
|
||||
if (overlayImage == null && overlayCanvas != null)
|
||||
{
|
||||
Transform existing = overlayCanvas.transform.Find("Overlay");
|
||||
if (existing != null)
|
||||
{
|
||||
overlayImage = existing.GetComponent<Image>();
|
||||
}
|
||||
}
|
||||
|
||||
if (overlayImage == null)
|
||||
{
|
||||
var imageGo = new GameObject("Overlay", typeof(RectTransform));
|
||||
imageGo.transform.SetParent(overlayCanvas.transform, false);
|
||||
overlayImage = imageGo.AddComponent<Image>();
|
||||
}
|
||||
|
||||
var rect = overlayImage.rectTransform;
|
||||
rect.anchorMin = Vector2.zero;
|
||||
rect.anchorMax = Vector2.one;
|
||||
rect.offsetMin = Vector2.zero;
|
||||
rect.offsetMax = Vector2.zero;
|
||||
rect.localScale = Vector3.one;
|
||||
overlayImage.raycastTarget = false;
|
||||
overlayImage.color = Color.black;
|
||||
}
|
||||
|
||||
private static void NormalizeCanvasTransform(Transform canvasTransform)
|
||||
{
|
||||
if (canvasTransform == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
canvasTransform.localPosition = Vector3.zero;
|
||||
canvasTransform.localRotation = Quaternion.identity;
|
||||
canvasTransform.localScale = Vector3.one;
|
||||
}
|
||||
|
||||
private void DisableOverlayFallback()
|
||||
{
|
||||
StopEffects();
|
||||
SetOverlayActive(false);
|
||||
|
||||
if (overlayFallbackLogged)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
overlayFallbackLogged = true;
|
||||
Debug.LogWarning(
|
||||
"[EyeViewportOverlay] 遮罩 shader 不可用,已跳过眼洞遮罩(视觉模块仍可正常使用,只是没有椭圆暗角/眨眼)。",
|
||||
this);
|
||||
}
|
||||
|
||||
private bool TrySetupOverlayMaterial()
|
||||
{
|
||||
overlayShaderAvailable = false;
|
||||
|
||||
Shader shader = overlayShader != null
|
||||
? overlayShader
|
||||
: Shader.Find("UI/EyeViewportOverlay");
|
||||
|
||||
if (shader == null)
|
||||
{
|
||||
Debug.LogError("[EyeViewportOverlay] 找不到 UI/EyeViewportOverlay shader。", this);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!shader.isSupported)
|
||||
{
|
||||
Debug.LogError("[EyeViewportOverlay] UI/EyeViewportOverlay shader 在当前平台不受支持。", this);
|
||||
return false;
|
||||
}
|
||||
|
||||
instanceMaterial = new Material(shader)
|
||||
@@ -468,6 +578,8 @@ namespace AibisDream
|
||||
hideFlags = HideFlags.DontSave
|
||||
};
|
||||
overlayImage.material = instanceMaterial;
|
||||
overlayShaderAvailable = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
private void ApplyCanvasRenderSettings()
|
||||
@@ -478,7 +590,8 @@ namespace AibisDream
|
||||
}
|
||||
|
||||
overlayCanvas.renderMode = RenderMode.ScreenSpaceCamera;
|
||||
overlayCanvas.worldCamera = ResolveUICamera();
|
||||
Camera uiCamera = ResolveUICamera();
|
||||
overlayCanvas.worldCamera = uiCamera;
|
||||
overlayCanvas.planeDistance = OverlayPlaneDistance;
|
||||
overlayCanvas.sortingLayerName = OverlaySortingLayer;
|
||||
overlayCanvas.sortingOrder = sortingOrder;
|
||||
|
||||
@@ -42,7 +42,6 @@ namespace AibisDream.UI
|
||||
private void Awake()
|
||||
{
|
||||
InitRefs();
|
||||
EnumEventSystem.Global.Register(GameLoopEnum.GameQuit, HideAll);
|
||||
}
|
||||
|
||||
private void InitRefs()
|
||||
@@ -240,14 +239,13 @@ namespace AibisDream.UI
|
||||
_signBoard.CloseSignBoard();
|
||||
}
|
||||
|
||||
private void HideAll()
|
||||
/// <summary>
|
||||
/// 清理演出层内容,但不影响黑屏遮罩(用于返回主界面时在遮罩下重置状态)。
|
||||
/// </summary>
|
||||
public void ClearPresentationEffects()
|
||||
{
|
||||
_timeFlowsVersion++;
|
||||
|
||||
_fadeImage.DOKill();
|
||||
_fadeImage.color = Color.clear;
|
||||
_fadeImage.gameObject.SetActive(false);
|
||||
|
||||
_fullScreenImage.FadeOut(0.1f);
|
||||
_showObjImage.FadeOut(0.1f);
|
||||
_showObjPanel.SetActive(false);
|
||||
|
||||
@@ -21,6 +21,13 @@ Shader "AibisDream/MemoryTuningSprite"
|
||||
_UVDistortFade ("UV Distort Fade", Range(0,1)) = 0
|
||||
_MemoryGrayscale ("Memory Grayscale", Range(0,1)) = 0
|
||||
_MemoryContrast ("Memory Contrast", Range(0,3)) = 1
|
||||
|
||||
[HideInInspector] _StencilComp ("Stencil Comparison", Float) = 8
|
||||
[HideInInspector] _Stencil ("Stencil ID", Float) = 0
|
||||
[HideInInspector] _StencilOp ("Stencil Operation", Float) = 0
|
||||
[HideInInspector] _StencilWriteMask ("Stencil Write Mask", Float) = 255
|
||||
[HideInInspector] _StencilReadMask ("Stencil Read Mask", Float) = 255
|
||||
[HideInInspector] _ColorMask ("Color Mask", Float) = 15
|
||||
}
|
||||
|
||||
SubShader
|
||||
@@ -37,7 +44,18 @@ Shader "AibisDream/MemoryTuningSprite"
|
||||
Cull Off
|
||||
Lighting Off
|
||||
ZWrite Off
|
||||
ZTest [unity_GUIZTestMode]
|
||||
Blend SrcAlpha OneMinusSrcAlpha
|
||||
ColorMask [_ColorMask]
|
||||
|
||||
Stencil
|
||||
{
|
||||
Ref [_Stencil]
|
||||
Comp [_StencilComp]
|
||||
Pass [_StencilOp]
|
||||
ReadMask [_StencilReadMask]
|
||||
WriteMask [_StencilWriteMask]
|
||||
}
|
||||
|
||||
Pass
|
||||
{
|
||||
@@ -114,7 +132,9 @@ Shader "AibisDream/MemoryTuningSprite"
|
||||
{
|
||||
half pixels = max(1.0, lerp(_PixelMax, _PixelMin, strength));
|
||||
pixels = lerp(pixels, max(1.0, density), step(0.001, density));
|
||||
float2 aspectPixels = float2(pixels, max(1.0, pixels * _MainTex_TexelSize.z / _MainTex_TexelSize.w));
|
||||
float texW = max(1.0, _MainTex_TexelSize.z);
|
||||
float texH = max(1.0, abs(_MainTex_TexelSize.w));
|
||||
float2 aspectPixels = float2(pixels, max(1.0, pixels * texW / texH));
|
||||
return round((uv - 0.5) * aspectPixels) / aspectPixels + 0.5;
|
||||
}
|
||||
|
||||
@@ -130,7 +150,8 @@ Shader "AibisDream/MemoryTuningSprite"
|
||||
return uv + side * wave * volFxStrength * edgeMask;
|
||||
}
|
||||
|
||||
half4 BlurSample(float2 uv, half strength)
|
||||
// 仅模糊 RGB;alpha 由调用方取自中心采样,避免图集透明边被混进导致整图变透明(移动端常见)。
|
||||
half3 BlurRgb(float2 uv, half strength)
|
||||
{
|
||||
float angle = radians(111.0);
|
||||
float radial = distance(uv, 0.5) * 0.0026;
|
||||
@@ -138,21 +159,27 @@ Shader "AibisDream/MemoryTuningSprite"
|
||||
float2 stepDir = normalize(float2(sin(angle), cos(angle)));
|
||||
float2 stepUv = stepDir * stepSize;
|
||||
|
||||
half4 col = SampleSprite(uv) * 0.18;
|
||||
col += SampleSprite(uv + stepUv * 1.0) * 0.15;
|
||||
col += SampleSprite(uv - stepUv * 1.0) * 0.15;
|
||||
col += SampleSprite(uv + stepUv * 2.0) * 0.12;
|
||||
col += SampleSprite(uv - stepUv * 2.0) * 0.12;
|
||||
col += SampleSprite(uv + stepUv * 3.0) * 0.09;
|
||||
col += SampleSprite(uv - stepUv * 3.0) * 0.09;
|
||||
col += SampleSprite(uv + stepUv * 4.0) * 0.05;
|
||||
col += SampleSprite(uv - stepUv * 4.0) * 0.05;
|
||||
return col;
|
||||
#if defined(SHADER_API_MOBILE)
|
||||
half3 rgb = SampleSprite(uv).rgb * 0.34;
|
||||
rgb += SampleSprite(uv + stepUv).rgb * 0.33;
|
||||
rgb += SampleSprite(uv - stepUv).rgb * 0.33;
|
||||
#else
|
||||
half3 rgb = SampleSprite(uv).rgb * 0.18;
|
||||
rgb += SampleSprite(uv + stepUv).rgb * 0.15;
|
||||
rgb += SampleSprite(uv - stepUv).rgb * 0.15;
|
||||
rgb += SampleSprite(uv + stepUv * 2.0).rgb * 0.12;
|
||||
rgb += SampleSprite(uv - stepUv * 2.0).rgb * 0.12;
|
||||
rgb += SampleSprite(uv + stepUv * 3.0).rgb * 0.09;
|
||||
rgb += SampleSprite(uv - stepUv * 3.0).rgb * 0.09;
|
||||
rgb += SampleSprite(uv + stepUv * 4.0).rgb * 0.05;
|
||||
rgb += SampleSprite(uv - stepUv * 4.0).rgb * 0.05;
|
||||
#endif
|
||||
return rgb;
|
||||
}
|
||||
|
||||
half4 ChromaticSample(float2 uv, half4 source, half strength)
|
||||
{
|
||||
float aspect = max(0.001, _MainTex_TexelSize.z / _MainTex_TexelSize.w);
|
||||
float aspect = max(0.001, abs(_MainTex_TexelSize.z) / max(1.0, abs(_MainTex_TexelSize.w)));
|
||||
float angle = 0.496 * 6.2831853;
|
||||
float2 dirA = float2(cos(angle) / aspect, sin(angle));
|
||||
float2 dirB = -dirA;
|
||||
@@ -164,7 +191,9 @@ Shader "AibisDream/MemoryTuningSprite"
|
||||
half3 splitRgb = (colA.rgb + colB.rgb) * 0.5865;
|
||||
half splitAlpha = max(max(colA.a, colB.a), source.a);
|
||||
half4 splitCol = half4(splitRgb, splitAlpha);
|
||||
return lerp(source, splitCol, 0.85 * response);
|
||||
half4 result = lerp(source, splitCol, 0.85 * response);
|
||||
result.a = source.a;
|
||||
return result;
|
||||
}
|
||||
|
||||
half4 frag(Varyings input) : SV_Target
|
||||
@@ -187,9 +216,12 @@ Shader "AibisDream/MemoryTuningSprite"
|
||||
float2 pixelUv = PixelSnap(uv, pixelate, _PixelatePixelDensity);
|
||||
uv = lerp(uv, pixelUv, pixelate);
|
||||
|
||||
half4 col = lerp(SampleSprite(uv), BlurSample(uv, blur), blur);
|
||||
half4 sharp = SampleSprite(uv);
|
||||
half3 rgb = lerp(sharp.rgb, BlurRgb(uv, blur), blur);
|
||||
half4 col = half4(rgb, sharp.a);
|
||||
col = ChromaticSample(uv, col, clarity);
|
||||
col *= input.color;
|
||||
col.a *= input.color.a;
|
||||
col.rgb *= input.color.rgb;
|
||||
return col;
|
||||
}
|
||||
ENDHLSL
|
||||
|
||||
@@ -144,7 +144,6 @@ title: MemoryDeepIn
|
||||
tags: event
|
||||
---
|
||||
<<clear_screen>>
|
||||
<<ModuleHightLight Memory false>>
|
||||
<<switch_fix_system_to Memory>>
|
||||
<<jump 进入记忆>>
|
||||
===
|
||||
@@ -155,7 +154,6 @@ tags: event
|
||||
title: UFDeepIn
|
||||
tags: event
|
||||
---
|
||||
<<ModuleHightLight UF false>>
|
||||
<<jump UF深入检查>>
|
||||
===
|
||||
|
||||
@@ -168,7 +166,6 @@ position: -9,21
|
||||
---
|
||||
<<clear_screen>>
|
||||
<<switch_fix_system_to Eye>>
|
||||
<<ModuleHightLight Eye false>>
|
||||
===
|
||||
|
||||
|
||||
|
||||
@@ -59,13 +59,6 @@ UfModule: 拒绝访问!需要A+级权限进行深入检查。 #line:00d6e4d
|
||||
me: 还是再检查一次吧。 #line:0cdd59e
|
||||
<<Reset_Plug>>
|
||||
<<endif>>
|
||||
<<ModuleHightLight Eye false>>
|
||||
<<ModuleHightLight Emo false>>
|
||||
<<ModuleHightLight Logic false>>
|
||||
<<ModuleHightLight Speak false>>
|
||||
<<ModuleHightLight Color false>>
|
||||
<<ModuleHightLight UF false>>
|
||||
<<ModuleHightLight Memory false>>
|
||||
<<hide_dialog>>
|
||||
<<clear_screen>>
|
||||
|
||||
@@ -173,7 +166,6 @@ position: 572,-2497
|
||||
Error: 检测到未知来源的异常显像! #line:0afe40d
|
||||
<<wait 0.3>>
|
||||
<<set $PlugCount=$PlugCount+1>>
|
||||
<<ModuleHightLight Eye false>>
|
||||
<<ModuleAlarm Eye true>>
|
||||
me: 无色彩信号…<waitfor=0.2>?……<waitfor=0.3>异常显像? #line:0b14c70
|
||||
<<if $colorChecked == false>>
|
||||
@@ -243,7 +235,6 @@ MemModule: 已与记忆模块建立连接! #line:08a12cc
|
||||
//这里有理解误区:玩家会以为记忆就存储在卡带里;需要处理
|
||||
<<wait 0.1>>
|
||||
->深入检查 #line:0749c3a
|
||||
<<ModuleHightLight Memory false>>
|
||||
<<hide_dialog>>
|
||||
<<jump MemoryDeepIn>>
|
||||
<<else>>
|
||||
@@ -256,7 +247,6 @@ MemModule: 已与记忆模块建立连接! #line:08a12cc
|
||||
<<endif>>
|
||||
<<wait 0.3>>
|
||||
MemModule: 检查完成!未发现关键错误。 #line:0dde0d2
|
||||
<<ModuleHightLight Memory false>>
|
||||
<<wait 0.3>>
|
||||
me: 记忆模块一切正常。 #line:067e962
|
||||
<<set $memoryChecked = true>>
|
||||
@@ -295,7 +285,6 @@ ChipModule: 已与附加模块建立连接! #line:03032df
|
||||
<<wait 1>>
|
||||
<<if $colorChecked ==false>>
|
||||
<<set $PlugCount=$PlugCount+1>>
|
||||
<<ModuleHightLight Color false>>
|
||||
me: 这似乎是美工机体的特殊模块…<waitfor=0.2>让我查查数据库。 #line:01e03c0
|
||||
<<hide_dialog>>
|
||||
<<open_progress_window 数据库查询 "正在查询:色觉晶圆训练槽……" 2>>
|
||||
@@ -347,7 +336,6 @@ Linking: 正在建立连接… #line:0445421
|
||||
<<wait 0.2>>
|
||||
EmoModule: 已与情绪模块建立连接! #line:00d2d0b
|
||||
->检查 #line:0b6168e
|
||||
<<ModuleHightLight Emo false>>
|
||||
<<hide_dialog>>
|
||||
Analysing:------ #line:0cb133b
|
||||
<<if $emoChecked == false>>
|
||||
@@ -388,7 +376,6 @@ Linking: 正在建立连接… #line:0b59a02
|
||||
<<wait 0.2>>
|
||||
SpeakerModule: 已与表达模块建立连接! #line:0ce06c1
|
||||
->检查 #line:03d9dfe
|
||||
<<ModuleHightLight Speak false>>
|
||||
<<hide_dialog>>
|
||||
Analysing:------ #line:058f3df
|
||||
<<if $speakerChecked == false>>
|
||||
@@ -423,7 +410,6 @@ Linking: 正在建立连接… #line:09de170
|
||||
<<wait 0.2>>
|
||||
LogicModule: 已与逻辑模块建立连接! #line:0d49573
|
||||
->检查 #line:0a649d5
|
||||
<<ModuleHightLight Logic false>>
|
||||
<<hide_dialog>>
|
||||
Analysing:------ #line:0a6b872
|
||||
<<if $logicChecked == false>>
|
||||
|
||||
@@ -292,7 +292,6 @@ position: -1045,-2332
|
||||
|
||||
<<if $eyeTargetTriggerCount == 3>>
|
||||
<<ModuleAlarm Eye false>>
|
||||
<<ModuleHightLight Memory true>>
|
||||
<<set $isFinishedEyeCheck=true>>
|
||||
<<Set_MouseMovementLockState EyeManager false>>
|
||||
<<jump 视觉检查状态>>
|
||||
|
||||
@@ -6,8 +6,6 @@ position: -449,-3574
|
||||
<<fade_in 1>>
|
||||
<<switch_fix_system_to "BodyModule" "Head">>
|
||||
<<fade_out 1>>
|
||||
<<ModuleHightLight Eye false>>
|
||||
<<ModuleHightLight Memory true>>
|
||||
<<jump 进入记忆检查>>
|
||||
===
|
||||
|
||||
@@ -86,7 +84,6 @@ position: -871,-2773
|
||||
<<set $ufDiscussCount=3>>
|
||||
<<set $eyeDiscussCount=2>>
|
||||
<<switch_fix_system_to "BodyModule">>
|
||||
<<ModuleHightLight Memory false>>
|
||||
<<jump 记忆检查状态>>
|
||||
<<endif>>
|
||||
|
||||
@@ -206,4 +203,4 @@ ppm: 如果公司这么讨厌的话,<waitfor=0.2>我就不在那里干就好
|
||||
<<stop_music event:/Music/mem_pp_2>>
|
||||
<<play_sfx event:/Scriptal/mem_out>>
|
||||
<<jump End_memoryPaly>>
|
||||
===
|
||||
===
|
||||
|
||||
@@ -21,7 +21,6 @@ me: 还没结束…<waitfor=0.1>保险起见,<waitfor=0.1>我们进视觉复
|
||||
<<fade_out 0.1>>
|
||||
<<clear_tasks>>
|
||||
Task: 检查视觉模块 #line:037c944
|
||||
<<ModuleHightLight Eye true>>
|
||||
<<DropCable>>
|
||||
<<set $eyeChecked = false>>
|
||||
===
|
||||
@@ -128,7 +127,6 @@ EyeModule: 已与视觉模块建立连接! #line:0dc8d9d
|
||||
Error: 未检测到色彩信号! #line:0059fae
|
||||
Error: 检测到丢失和记忆模块的连接。 #line:0638bb4
|
||||
<<wait 0.1>>
|
||||
<<ModuleHightLight Eye false>>
|
||||
<<ModuleAlarm Eye true>>
|
||||
<<if $eyeChecked==false>>
|
||||
me: 看起来是生效了。<waitfor=0.2><br>不过,<waitfor=0.1>还是要深入检查,亲眼确认一下。 #line:08c9f56
|
||||
|
||||
@@ -34,6 +34,9 @@ GraphicsSettings:
|
||||
- {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0}
|
||||
- {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0}
|
||||
- {fileID: 10783, guid: 0000000000000000f000000000000000, type: 0}
|
||||
- {fileID: 4800000, guid: 6652ed847ed1bc641bd702f03c650adf, type: 3}
|
||||
- {fileID: 4800000, guid: 9f7b2ef66c2842c496327822f79da521, type: 3}
|
||||
- {fileID: 4800000, guid: f7f1f0a7430f4f44fa1d7af89e1e013f, type: 3}
|
||||
m_PreloadedShaders: []
|
||||
m_PreloadShadersBatchTimeLimit: -1
|
||||
m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0}
|
||||
|
||||
Reference in New Issue
Block a user