diff --git a/Assets/GameContent/Scene_Dream/Materials/DreamDataOverflow.mat b/Assets/GameContent/Scene_Dream/Materials/DreamDataOverflow.mat deleted file mode 100644 index 89cc8cc8d..000000000 --- a/Assets/GameContent/Scene_Dream/Materials/DreamDataOverflow.mat +++ /dev/null @@ -1,39 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!21 &2100000 -Material: - serializedVersion: 8 - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_Name: DreamDataOverflow - m_Shader: {fileID: 4800000, guid: 6c30d8e44b1b4b4ab9414a90e069f290, type: 3} - m_Parent: {fileID: 0} - m_ModifiedSerializedProperties: 0 - m_ValidKeywords: [] - m_InvalidKeywords: [] - m_LightmapFlags: 4 - m_EnableInstancingVariants: 0 - m_DoubleSidedGI: 0 - m_CustomRenderQueue: -1 - stringTagMap: {} - disabledShaderPasses: [] - m_LockedProperties: - m_SavedProperties: - serializedVersion: 3 - m_TexEnvs: - - _MainTex: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - m_Ints: [] - m_Floats: - - _OverflowChromatic: 0.006 - - _OverflowExposure: 1.45 - - _OverflowGlow: 0.65 - - _OverflowIntensity: 0 - - _OverflowNoise: 0.08 - m_Colors: - - _Color: {r: 1, g: 1, b: 1, a: 1} - m_BuildTextureStacks: [] diff --git a/Assets/GameContent/Scene_Dream/Materials/DreamDataOverflow.shader b/Assets/GameContent/Scene_Dream/Materials/DreamDataOverflow.shader deleted file mode 100644 index d274de458..000000000 --- a/Assets/GameContent/Scene_Dream/Materials/DreamDataOverflow.shader +++ /dev/null @@ -1,154 +0,0 @@ -Shader "AibisDream/DreamDataOverflow" -{ - Properties - { - [PerRendererData] _MainTex("Sprite Texture", 2D) = "white" {} - _Color("Tint", Color) = (1,1,1,1) - _OverflowIntensity("Overflow Intensity", Range(0, 1)) = 0 - _OverflowExposure("Overflow Exposure", Range(0, 3)) = 1.45 - _OverflowGlow("Overflow Glow", Range(0, 2)) = 0.65 - _OverflowChromatic("Overflow Chromatic", Range(0, 0.04)) = 0.006 - _OverflowNoise("Overflow Noise", Range(0, 0.5)) = 0.08 - } - - SubShader - { - Tags - { - "Queue" = "Transparent" - "RenderType" = "Transparent" - "RenderPipeline" = "UniversalPipeline" - "IgnoreProjector" = "True" - "CanUseSpriteAtlas" = "True" - } - - Cull Off - ZWrite Off - Blend SrcAlpha OneMinusSrcAlpha - - HLSLINCLUDE - #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" - - struct Attributes - { - float4 positionOS : POSITION; - float2 uv : TEXCOORD0; - float4 color : COLOR; - }; - - struct Varyings - { - float4 positionHCS : SV_POSITION; - float2 uv : TEXCOORD0; - float4 color : COLOR; - float4 screenPosition : TEXCOORD1; - }; - - TEXTURE2D(_MainTex); - SAMPLER(sampler_MainTex); - float4 _MainTex_ST; - float4 _MainTex_TexelSize; - float4 _Color; - float _OverflowIntensity; - float _OverflowExposure; - float _OverflowGlow; - float _OverflowChromatic; - float _OverflowNoise; - - float hash21(float2 value) - { - value = frac(value * float2(123.34, 456.21)); - value += dot(value, value + 45.32); - return frac(value.x * value.y); - } - - Varyings vert(Attributes input) - { - Varyings output; - output.positionHCS = TransformObjectToHClip(input.positionOS.xyz); - output.uv = TRANSFORM_TEX(input.uv, _MainTex); - output.color = input.color * _Color; - output.screenPosition = ComputeScreenPos(output.positionHCS); - return output; - } - - half4 SampleSprite(float2 uv) - { - return SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv); - } - - half4 frag(Varyings input) : SV_Target - { - float intensity = saturate(_OverflowIntensity); - float pulse = 0.92 + sin(_Time.y * 17.0 + input.uv.y * 23.0) * 0.08; - float activeIntensity = saturate(intensity * pulse); - - float2 radial = input.uv - 0.5; - float radialLength = max(length(radial), 0.001); - float2 chromaticDirection = radial / radialLength; - float chromaticOffset = _OverflowChromatic * activeIntensity; - - half4 center = SampleSprite(input.uv); - half red = SampleSprite(input.uv + chromaticDirection * chromaticOffset).r; - half blue = SampleSprite(input.uv - chromaticDirection * chromaticOffset).b; - half3 chromatic = half3(red, center.g, blue); - - float2 texel = _MainTex_TexelSize.xy * lerp(1.5, 7.0, activeIntensity); - half4 blur = center * 0.2; - blur += SampleSprite(input.uv + float2(texel.x, 0)) * 0.1; - blur += SampleSprite(input.uv - float2(texel.x, 0)) * 0.1; - blur += SampleSprite(input.uv + float2(0, texel.y)) * 0.1; - blur += SampleSprite(input.uv - float2(0, texel.y)) * 0.1; - blur += SampleSprite(input.uv + texel) * 0.1; - blur += SampleSprite(input.uv - texel) * 0.1; - blur += SampleSprite(input.uv + float2(texel.x, -texel.y)) * 0.1; - blur += SampleSprite(input.uv + float2(-texel.x, texel.y)) * 0.1; - - half luminance = dot(chromatic, half3(0.2126, 0.7152, 0.0722)); - half glowLuminance = dot(blur.rgb, half3(0.2126, 0.7152, 0.0722)); - half whiteAmount = saturate(activeIntensity * (_OverflowExposure * 0.38 + luminance * 0.8)); - half3 exposed = lerp(chromatic, half3(1, 1, 1), whiteAmount); - exposed += blur.rgb * glowLuminance * _OverflowGlow * activeIntensity; - - float2 screenUv = input.screenPosition.xy / max(input.screenPosition.w, 0.0001); - float noiseSeed = floor(_Time.y * 24.0); - float noise = hash21(floor(screenUv * _ScreenParams.xy * 0.32) + noiseSeed); - float speck = smoothstep(0.82, 1.0, noise) * _OverflowNoise * activeIntensity; - float scan = sin((screenUv.y * _ScreenParams.y + _Time.y * 90.0) * 0.12) * 0.5 + 0.5; - exposed += speck * lerp(0.55, 1.0, scan); - - half4 result; - result.rgb = exposed * input.color.rgb; - result.a = max(center.a, blur.a * activeIntensity * _OverflowGlow * 0.45) * input.color.a; - clip(result.a - 0.001); - return result; - } - ENDHLSL - - Pass - { - Name "DreamDataOverflow2D" - Tags { "LightMode" = "Universal2D" } - - HLSLPROGRAM - #pragma vertex vert - #pragma fragment frag - #pragma target 3.0 - ENDHLSL - } - - Pass - { - Name "DreamDataOverflowUnlit" - Tags { "LightMode" = "SRPDefaultUnlit" } - - HLSLPROGRAM - #pragma vertex vert - #pragma fragment frag - #pragma target 3.0 - ENDHLSL - } - } - - Fallback "Sprites/Default" -} diff --git a/Assets/GameContent/Scene_Dream/Materials/DreamDataOverflow.shader.meta b/Assets/GameContent/Scene_Dream/Materials/DreamDataOverflow.shader.meta deleted file mode 100644 index a2f307aeb..000000000 --- a/Assets/GameContent/Scene_Dream/Materials/DreamDataOverflow.shader.meta +++ /dev/null @@ -1,9 +0,0 @@ -fileFormatVersion: 2 -guid: 6c30d8e44b1b4b4ab9414a90e069f290 -ShaderImporter: - externalObjects: {} - defaultTextures: [] - nonModifiableTextures: [] - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Render/OceanAsciiDoor.mat b/Assets/Render/OceanAsciiDoor.mat index 62b28286c..a07a8ae31 100644 --- a/Assets/Render/OceanAsciiDoor.mat +++ b/Assets/Render/OceanAsciiDoor.mat @@ -31,17 +31,22 @@ Material: m_Floats: - _BodyBright: 0.492 - _BodyDensity: 0.359 + - _CrestScale: 1 - _CrestBright: 0.752 - _CrestWidth: 0.92 - _FoamIntensity: 0.894 - _FoamSpeed: 0.133 - - _GridCols: 91.7 - - _GridRows: 64.4 - - _HorizonRow: 0 - - _PerspectiveStrength: 0 - - _ShoreRows: 5 - - _WaveCount: 7 - - _WaveSpeed: 1.43 + - _GlyphSpeed: 3.2 + - _GridCols: 92 + - _GridRows: 66 + - _HorizonRow: 2 + - _PerspectiveStrength: 0.76 + - _ShoreRows: 4 + - _WaveBodyWidth: 0.68 + - _WaveCount: 4 + - _WavePhase: 7.5 + - _WaveSpeed: 2.6 + - _WaveStartTime: 0 m_Colors: - _BgColor: {r: 0, g: 0, b: 0, a: 1} - _Color: {r: 1, g: 1, b: 1, a: 1} diff --git a/Assets/Render/OceanAsciiDoor.shader b/Assets/Render/OceanAsciiDoor.shader index a7314841e..5abc1de97 100644 --- a/Assets/Render/OceanAsciiDoor.shader +++ b/Assets/Render/OceanAsciiDoor.shader @@ -9,10 +9,20 @@ Shader "Custom/OceanAsciiDoor" _GridCols ("Grid Columns", Range(20, 200)) = 80 _GridRows ("Grid Rows", Range(15, 150)) = 55 + [Header(Perspective)] + _HorizonRow ("Horizon Offset (Rows)", Range(0, 12)) = 0 + _PerspectiveStrength ("Perspective Strength", Range(0, 1)) = 0.75 + [Header(Wave)] - _WaveSpeed ("Wave Speed", Range(0, 1.0)) = 0.15 + _WaveSpeed ("Wave Travel (Rows/Second)", Range(0, 8.0)) = 2.6 _WaveCount ("Wave Count", Range(2, 10)) = 5 _ShoreRows ("Shore Rows", Range(1, 8)) = 3 + _WaveBodyWidth ("Wave Body Width", Range(0.25, 0.95)) = 0.68 + _CrestScale ("Crest Scale", Range(0.5, 2.0)) = 1.0 + _GlyphSpeed ("Glyph Flicker Speed", Range(0, 8.0)) = 3.2 + + [HideInInspector] _WaveStartTime ("Wave Start Time", Float) = 0 + [HideInInspector] _WavePhase ("Wave Start Phase", Float) = 0 [Header(Intensity)] _CrestBright ("Crest Brightness", Range(0.3, 1)) = 0.85 @@ -65,9 +75,16 @@ Shader "Custom/OceanAsciiDoor" fixed4 _BgColor; float _GridCols; float _GridRows; + float _HorizonRow; + float _PerspectiveStrength; float _WaveSpeed; float _WaveCount; float _ShoreRows; + float _WaveBodyWidth; + float _CrestScale; + float _GlyphSpeed; + float _WaveStartTime; + float _WavePhase; float _CrestBright; float _BodyBright; @@ -154,10 +171,10 @@ Shader "Custom/OceanAsciiDoor" float bodyNoise(float c, float r, float t) { return ( - sin(c * 1.3 + r * 0.7 + t * 0.11) * 0.35 + - sin(c * 0.37 + r * 1.17 + t * 0.07) * 0.30 + - sin(c * 2.1 + r * 0.31 + t * 0.19) * 0.20 + - sin(c * 0.71 + r * 2.03 + t * 0.05) * 0.15 + sin(c * 1.3 + r * 0.7 + t * 0.83) * 0.35 + + sin(c * 0.37 + r * 1.17 + t * 0.51) * 0.30 + + sin(c * 2.1 + r * 0.31 + t * 1.07) * 0.20 + + sin(c * 0.71 + r * 2.03 + t * 0.37) * 0.15 ) * 0.5 + 0.5; } @@ -182,8 +199,25 @@ Shader "Custom/OceanAsciiDoor" { float2 uv = i.uv; - float r = (1.0 - uv.y) * _GridRows; - float c = uv.x * _GridCols; + // Project the flat character grid onto a low, receding sea plane. + // Rows and columns become denser near the horizon while the foreground + // stays broad, matching the perspective of the glass-sea animation. + float horizonUv = saturate(_HorizonRow / max(1.0, _GridRows)); + float rawDepth = 1.0 - uv.y; + float screenDepth = saturate( + (rawDepth - horizonUv) / max(0.001, 1.0 - horizonUv)); + float perspective = saturate(_PerspectiveStrength); + float depthExponent = lerp(1.0, 0.42, perspective); + float projectedDepth = pow(screenDepth, depthExponent); + + float farColumnDensity = lerp(1.0, 2.35, perspective); + float columnDensity = lerp( + farColumnDensity, + 1.0, + smoothstep(0.0, 1.0, screenDepth)); + + float r = projectedDepth * _GridRows; + float c = (uv.x - 0.5) * _GridCols * columnDensity + _GridCols * 0.5; float shoreY = _GridRows - _ShoreRows; float sp = shoreY / max(1.0, _WaveCount); @@ -198,9 +232,12 @@ Shader "Custom/OceanAsciiDoor" float cellC = floor(c); float cellR = floor(r); - // HTML's T increments by 1 per frame (~30fps) - float T = _Time.y * _WaveSpeed * 30.0; - float time = _Time.y; + // CodeSea owns a local clock. DreamDoorSystem resets it only when + // entering CodeSea, so the reveal is deterministic while reframing + // from fullscreen back into the door remains continuous. + float localTime = max(0.0, _Time.y - _WaveStartTime); + float waveTravel = _WavePhase + localTime * _WaveSpeed; + float glyphTime = localTime * _GlyphSpeed; // ── Wave layer computation ─────────────────────────────── float bestDepth = 999.0; @@ -209,26 +246,32 @@ Shader "Custom/OceanAsciiDoor" for (float wi = 0; wi < _WaveCount + 2; wi++) { float wSeed = hash11(wi * 7.31); - float wSpeed = 0.12 + wSeed * 0.06; float baseY = -sp + wi * sp; - baseY += T * wSpeed * (1.0 + saturate(baseY / max(1.0, shoreY)) * 0.4); + // Every crest advances from the horizon toward the viewer with + // only a small depth variation. Keeping a shared travel phase + // makes the bands read as one ocean instead of unrelated noise. + float depthSpeed = lerp(0.92, 1.12, saturate(baseY / max(1.0, shoreY))); + baseY += waveTravel * depthSpeed; baseY = baseY - floor(baseY / (_GridRows + sp)) * (_GridRows + sp) - sp; float p1 = hash11(wi * 3.17) * 6.2832; float p2 = hash11(wi * 5.23) * 6.2832; float p3 = hash11(wi * 9.41) * 6.2832; - p1 += time * 0.008; - p2 -= time * 0.005; - p3 += time * 0.011; + p1 += localTime * 0.045; + p2 -= localTime * 0.070; + p3 += localTime * 0.100; - float a1 = 1.5 + hash11(wi * 2.71) * 1.0; - float a2 = 0.45 + hash11(wi * 4.13) * 0.3; - float a3 = 0.18 + hash11(wi * 6.67) * 0.12; + // Long, broad crests echo the gold montage's composition. + // Higher-frequency detail is deliberately restrained so the + // result remains a readable wave rather than code rain. + float a1 = (1.15 + hash11(wi * 2.71) * 0.65) * _CrestScale; + float a2 = (0.32 + hash11(wi * 4.13) * 0.20) * _CrestScale; + float a3 = (0.10 + hash11(wi * 6.67) * 0.08) * _CrestScale; - float f1 = 0.045 + hash11(wi * 1.23) * 0.025; - float f2 = 0.10 + hash11(wi * 8.37) * 0.05; - float f3 = 0.19 + hash11(wi * 11.03) * 0.07; + float f1 = 0.026 + hash11(wi * 1.23) * 0.014; + float f2 = 0.072 + hash11(wi * 8.37) * 0.030; + float f3 = 0.140 + hash11(wi * 11.03) * 0.040; float crest = baseY + sin(cellC * f1 + p1) * a1 @@ -250,37 +293,36 @@ Shader "Custom/OceanAsciiDoor" if (bestWaveY > -900.0 && cellR < shoreY) { float depthVal = bestDepth; - float depthRatio = saturate(depthVal / max(0.001, sp)); + float bodyDepth = max(1.5, sp * _WaveBodyWidth); + float depthRatio = saturate(depthVal / bodyDepth); float proximity = saturate(bestWaveY / max(0.001, shoreY)); - if (depthVal < 1.0) + if (depthVal < 1.35) { // ── CREST ──────────────────────────────────── bright = (0.55 + proximity * 0.45) * _CrestBright; - // HTML: idx = floor((c * 0.35 + T * 0.07) % CREST_CHARS.length) - float rawIdx = cellC * 0.35 + T * 0.07; + float rawIdx = cellC * 0.35 + glyphTime * 1.4; int idx = ((int)floor(rawIdx)) % 8; if (idx < 0) idx += 8; charId = crestCharId(idx); } - else + else if (depthVal < bodyDepth) { // ── WAVE BODY ──────────────────────────────── - bright = pow(1.0 - depthRatio, 1.5) * (0.18 + proximity * 0.62) * _BodyBright; + bright = pow(1.0 - depthRatio, 1.1) * (0.24 + proximity * 0.66) * _BodyBright; if (bright >= 0.03) { - float n = bodyNoise(cellC, cellR, T * 0.06); - float threshold = depthRatio * depthRatio * 0.65; + float n = bodyNoise(cellC, cellR, glyphTime); + float threshold = lerp(0.12, 0.42, pow(depthRatio, 1.3)); if (n < threshold) { bright = 0.0; } else { - // HTML: charNoise → sin > 0 ? '1' : '0' - charId = sin(cellC * 0.97 + cellR * 1.53 + T * 0.13) > 0 ? 4 : 3; + charId = sin(cellC * 0.97 + cellR * 1.53 + glyphTime * 1.9) > 0 ? 4 : 3; } } else @@ -293,15 +335,14 @@ Shader "Custom/OceanAsciiDoor" { // ── Shore foam ─────────────────────────────────── float dInShore = (cellR - shoreY) / max(1.0, _ShoreRows); - float n = bodyNoise(cellC, cellR, T * 0.2); + float n = bodyNoise(cellC, cellR, glyphTime * 1.15); bright = (1.0 - dInShore) * (0.3 + n * 0.6) * _BodyBright; if (bright >= 0.06) { if (cellR < shoreY + 1.0) { - // HTML: CREST_CHARS[floor((c*0.4+T*0.1) % 8)] - float rawCi = cellC * 0.4 + T * 0.1; + float rawCi = cellC * 0.4 + glyphTime * 1.6; int ci = ((int)floor(rawCi)) % 8; if (ci < 0) ci += 8; charId = crestCharId(ci); diff --git a/Assets/Render/Renderer2Dtest.asset b/Assets/Render/Renderer2Dtest.asset index bcd8aa5d8..077a33279 100644 --- a/Assets/Render/Renderer2Dtest.asset +++ b/Assets/Render/Renderer2Dtest.asset @@ -1015,6 +1015,21 @@ MonoBehaviour: m_Name: ShapesRenderFeature m_EditorClassIdentifier: m_Active: 1 +--- !u!114 &3946563994926508291 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 2d8f4db9a2fd4f108b1374528137ff26, type: 3} + m_Name: Distort + m_EditorClassIdentifier: + _active: 1 + _shader: {fileID: 4800000, guid: 9c32f8d52c844eaab1fc42000e1eef87, type: 3} + _motionMul: 1 --- !u!114 &6583965737676714203 MonoBehaviour: m_ObjectHideFlags: 3 @@ -1164,6 +1179,8 @@ MonoBehaviour: _camDistance: 100 _passes: m_List: + - {fileID: 3946563994926508291} + - {fileID: 1034310385565965676} - {fileID: -5125607493159684606} - {fileID: 744099657206943436} - {fileID: 9177025314149218120} @@ -1172,7 +1189,6 @@ MonoBehaviour: - {fileID: 1261959898020507823} - {fileID: 6583965737676714203} - {fileID: 9138616806790232041} - - {fileID: 1034310385565965676} _blitShader: {fileID: 4800000, guid: a8a709d9db2241741ab3032b946ef258, type: 3} --- !u!114 &7850692704183786000 MonoBehaviour: diff --git a/Assets/Scenes/梦境.meta b/Assets/Scenes/梦境.meta new file mode 100644 index 000000000..6c033a2c9 --- /dev/null +++ b/Assets/Scenes/梦境.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7988f83001aead045b454dbca8307233 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes/梦境.unity b/Assets/Scenes/梦境.unity index ab91f0c68..bf0e55103 100644 --- a/Assets/Scenes/梦境.unity +++ b/Assets/Scenes/梦境.unity @@ -175,7 +175,7 @@ SpriteRenderer: m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: a97c105638bdf8b4a8650670310a4cd3, type: 2} + - {fileID: 2100000, guid: 6e39f75d9dd84cf1b04f8c59a7243b26, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -195,7 +195,7 @@ SpriteRenderer: m_LightmapParameters: {fileID: 0} m_SortingLayerID: 844151739 m_SortingLayer: 1 - m_SortingOrder: 4 + m_SortingOrder: 3 m_Sprite: {fileID: 21300000, guid: 65581c14d5b5dad4e991ee88882656de, type: 3} m_Color: {r: 1, g: 1, b: 1, a: 1} m_FlipX: 0 @@ -417,8 +417,8 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: c0c737b07db74d53bd47f7b140346ad4, type: 3} - m_Name: - m_EditorClassIdentifier: + m_Name: + m_EditorClassIdentifier: director: {fileID: 132823524} starfieldRenderer: {fileID: 1420961919} initialBlur: 0.58 @@ -488,7 +488,7 @@ SpriteRenderer: m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: db54ed6c97bf4f05a79f53b268f0c52a, type: 2} + - {fileID: 2100000, guid: a97c105638bdf8b4a8650670310a4cd3, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -520,6 +520,55 @@ SpriteRenderer: m_WasSpriteAssigned: 0 m_MaskInteraction: 0 m_SpriteSortPoint: 0 +--- !u!1 &262036610 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 262036612} + - component: {fileID: 262036611} + m_Layer: 0 + m_Name: BloomEffect + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &262036611 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 262036610} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 172515602e62fb746b5d573b38a5fe58, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IsGlobal: 1 + priority: 0 + blendDistance: 0 + weight: 0 + sharedProfile: {fileID: 11400000, guid: 16aa9506970514f408d2bfa36ab28503, type: 2} +--- !u!4 &262036612 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 262036610} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 3.1244357, y: -3.317876, z: -0.14737558} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &308098823 GameObject: m_ObjectHideFlags: 0 @@ -661,10 +710,16 @@ MonoBehaviour: - {fileID: 8430225} frameRenderers: - {fileID: 1847534534} + whiteDoorFrameSprite: {fileID: 21300000, guid: 356fae38f61f35945b658949635636e7, type: 3} + seaDoorFrameSprite: {fileID: 21300000, guid: b902de86335e5354099fae67e3eef00f, type: 3} sceneBlackOverlay: {fileID: 1373573734} - glassSeaVideoClip: {fileID: 32900000, guid: 9ed84eb452114d46b39fa43322d186ec, type: 3} - glassSeaTargetTexture: {fileID: 8400000, guid: d873791053c443c1a79eedd22a687780, type: 2} - glassSeaPrepareTimeout: 5 + glassSeaAnimator: {fileID: 444731254618205656} + glassSeaStateName: DoorGlassSeaLoop + glassSeaFramedStateName: DoorGlassSeaFramedLoop + glassSeaCoverOverscan: 1.02 + codeSeaStartPhase: 7.5 + codeSeaWaveSpeed: 2.6 + codeSeaGlyphSpeed: 3.2 terminalUI: {fileID: 1195418928} doorShellTransform: {fileID: 0} terminalShapeReference: {fileID: 1847534534} @@ -1069,7 +1124,7 @@ SpriteRenderer: m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: db54ed6c97bf4f05a79f53b268f0c52a, type: 2} + - {fileID: 2100000, guid: a97c105638bdf8b4a8650670310a4cd3, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -1090,15 +1145,15 @@ SpriteRenderer: m_SortingLayerID: 844151739 m_SortingLayer: 1 m_SortingOrder: 5 - m_Sprite: {fileID: 0} + m_Sprite: {fileID: 21300000, guid: c05241fc4e3410d49b9e9a24cd632d95, type: 3} m_Color: {r: 1, g: 1, b: 1, a: 1} m_FlipX: 0 m_FlipY: 0 m_DrawMode: 0 - m_Size: {x: 17.860466, y: 10.046512} + m_Size: {x: 9.6, y: 5.4} m_AdaptiveModeThreshold: 0.5 m_SpriteTileMode: 0 - m_WasSpriteAssigned: 0 + m_WasSpriteAssigned: 1 m_MaskInteraction: 0 m_SpriteSortPoint: 0 --- !u!95 &762853995 @@ -1512,7 +1567,7 @@ MonoBehaviour: typewriterCharDelay: 0.025 bootSpeedMultiplier: 4 bootSequence: - - text: 'root@sys:~$ dream.render --stop --session 0742' + - text: root@sys:~$ dream.render --stop --session 0742 style: 3 delayAfter: 0.15 - text: '[ OK ] Dream renderer stopped.' @@ -1521,7 +1576,7 @@ MonoBehaviour: - text: '[ RAW ] Untitled_Greybox_0 exposed.' style: 0 delayAfter: 0.35 - - text: 'root@sys:~$ trace --tail /log/dream_0742.rec' + - text: root@sys:~$ trace --tail /log/dream_0742.rec style: 3 delayAfter: 0.15 - text: '[0005] audio.play("sea_ambient", source=door.rear)' @@ -2110,54 +2165,6 @@ Transform: m_Children: [] m_Father: {fileID: 132823523} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!21 &1583441590 -Material: - serializedVersion: 8 - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_Name: Sprites/Default - m_Shader: {fileID: 4800000, guid: f4ae6a3baad97d44aad69d7b6dd52a4c, type: 3} - m_Parent: {fileID: 0} - m_ModifiedSerializedProperties: 0 - m_ValidKeywords: [] - m_InvalidKeywords: [] - m_LightmapFlags: 4 - m_EnableInstancingVariants: 0 - m_DoubleSidedGI: 0 - m_CustomRenderQueue: -1 - stringTagMap: {} - disabledShaderPasses: [] - m_LockedProperties: - m_SavedProperties: - serializedVersion: 3 - m_TexEnvs: - - _AlphaTex: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _MainTex: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - m_Ints: [] - m_Floats: - - PixelSnap: 0 - - _BlurRadius: 0 - - _BlurSamples: 32 - - _Brightness: 1.24 - - _EnableExternalAlpha: 0 - - _FrostIntensity: 0.03 - - _FrostScale: 35 - - _Saturation: 1.17 - - _TintStrength: 0 - m_Colors: - - _Color: {r: 1, g: 1, b: 1, a: 1} - - _Flip: {r: 1, g: 1, b: 1, a: 1} - - _GlassTint: {r: 0.9, g: 0.95, b: 1, a: 1} - - _RendererColor: {r: 1, g: 1, b: 1, a: 1} - m_BuildTextureStacks: [] --- !u!1 &1644308977 GameObject: m_ObjectHideFlags: 0 @@ -2432,7 +2439,7 @@ Transform: m_GameObject: {fileID: 1847534532} serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: -0.09, y: 0.32, z: 0} + m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 0.72805655, y: 0.72805655, z: 0.72805655} m_ConstrainProportionsScale: 0 m_Children: [] @@ -2478,8 +2485,8 @@ SpriteRenderer: m_LightmapParameters: {fileID: 0} m_SortingLayerID: 844151739 m_SortingLayer: 1 - m_SortingOrder: 9 - m_Sprite: {fileID: 21300000, guid: 1b578f08ade58004eadbd22363f79662, type: 3} + m_SortingOrder: 5 + m_Sprite: {fileID: 21300000, guid: 356fae38f61f35945b658949635636e7, type: 3} m_Color: {r: 1, g: 1, b: 1, a: 1} m_FlipX: 0 m_FlipY: 0 @@ -2616,7 +2623,7 @@ SpriteRenderer: m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: e04544198a7d4f88ba592bf1feebbca2, type: 2} + - {fileID: 2100000, guid: a97c105638bdf8b4a8650670310a4cd3, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -2636,8 +2643,8 @@ SpriteRenderer: m_LightmapParameters: {fileID: 0} m_SortingLayerID: 844151739 m_SortingLayer: 1 - m_SortingOrder: 5 - m_Sprite: {fileID: 21300000, guid: 0d38a05e2cc64f5bb1958d3bdf78925d, type: 3} + m_SortingOrder: 4 + m_Sprite: {fileID: -1062889630, guid: 2160bf4f857aa5f4d853c824268588d0, type: 3} m_Color: {r: 1, g: 1, b: 1, a: 0} m_FlipX: 0 m_FlipY: 0 @@ -2648,6 +2655,27 @@ SpriteRenderer: m_WasSpriteAssigned: 1 m_MaskInteraction: 0 m_SpriteSortPoint: 0 +--- !u!95 &444731254618205656 +Animator: + serializedVersion: 5 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1961593256904873106} + m_Enabled: 0 + m_Avatar: {fileID: 0} + m_Controller: {fileID: 9100000, guid: ab2a8b6b0c9747c8adf9ddbb0b332f3d, type: 2} + m_CullingMode: 0 + m_UpdateMode: 0 + m_ApplyRootMotion: 0 + m_LinearVelocityBlending: 0 + m_StabilizeFeet: 0 + m_WarningMessage: + m_HasTransformHierarchy: 1 + m_AllowConstantClipSamplingOptimization: 1 + m_KeepAnimatorStateOnDisable: 0 + m_WriteDefaultValuesOnDisable: 0 --- !u!4 &871445756458438719 Transform: m_ObjectHideFlags: 0 @@ -2688,6 +2716,7 @@ GameObject: m_Component: - component: {fileID: 871445756458438719} - component: {fileID: 444731254618205655} + - component: {fileID: 444731254618205656} m_Layer: 0 m_Name: DoorGlassSea m_TagString: Untagged @@ -2752,7 +2781,7 @@ SpriteRenderer: m_LightmapParameters: {fileID: 0} m_SortingLayerID: 844151739 m_SortingLayer: 1 - m_SortingOrder: 5 + m_SortingOrder: 4 m_Sprite: {fileID: 7482667652216324306, guid: 311925a002f4447b3a28927169b83ea6, type: 3} m_Color: {r: 1, g: 1, b: 1, a: 0} m_FlipX: 0 @@ -2773,3 +2802,4 @@ SceneRoots: - {fileID: 1784701442} - {fileID: 861686055} - {fileID: 383939068} + - {fileID: 262036612} diff --git a/Assets/Scenes/梦境/DreamBloom.asset b/Assets/Scenes/梦境/DreamBloom.asset new file mode 100644 index 000000000..f626fb1d5 --- /dev/null +++ b/Assets/Scenes/梦境/DreamBloom.asset @@ -0,0 +1,294 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &-1446237002707825744 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 318746fcd28a4c69b04bd76bb679e99e, type: 3} + m_Name: BloomVol + m_EditorClassIdentifier: + active: 1 + m_Intencity: + m_OverrideState: 1 + m_Value: 12 + m_Threshold: + m_OverrideState: 1 + m_Value: + _curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0.9048157 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + _pixels: + - {r: 0.9048157, g: 0.9048157, b: 0.9048157, a: 0.9048157} + - {r: 0.9051064, g: 0.9051064, b: 0.9051064, a: 0.9051064} + - {r: 0.9059531, g: 0.9059531, b: 0.9059531, a: 0.9059531} + - {r: 0.9073174, g: 0.9073174, b: 0.9073174, a: 0.9073174} + - {r: 0.909161, g: 0.909161, b: 0.909161, a: 0.909161} + - {r: 0.91144544, g: 0.91144544, b: 0.91144544, a: 0.91144544} + - {r: 0.9141325, g: 0.9141325, b: 0.9141325, a: 0.9141325} + - {r: 0.9171838, g: 0.9171838, b: 0.9171838, a: 0.9171838} + - {r: 0.92056096, g: 0.92056096, b: 0.92056096, a: 0.92056096} + - {r: 0.92422575, g: 0.92422575, b: 0.92422575, a: 0.92422575} + - {r: 0.9281397, g: 0.9281397, b: 0.9281397, a: 0.9281397} + - {r: 0.9322645, g: 0.9322645, b: 0.9322645, a: 0.9322645} + - {r: 0.9365619, g: 0.9365619, b: 0.9365619, a: 0.9365619} + - {r: 0.9409934, g: 0.9409934, b: 0.9409934, a: 0.9409934} + - {r: 0.9455209, g: 0.9455209, b: 0.9455209, a: 0.9455209} + - {r: 0.9501058, g: 0.9501058, b: 0.9501058, a: 0.9501058} + - {r: 0.9547099, g: 0.9547099, b: 0.9547099, a: 0.9547099} + - {r: 0.9592948, g: 0.9592948, b: 0.9592948, a: 0.9592948} + - {r: 0.96382225, g: 0.96382225, b: 0.96382225, a: 0.96382225} + - {r: 0.9682538, g: 0.9682538, b: 0.9682538, a: 0.9682538} + - {r: 0.97255117, g: 0.97255117, b: 0.97255117, a: 0.97255117} + - {r: 0.976676, g: 0.976676, b: 0.976676, a: 0.976676} + - {r: 0.9805899, g: 0.9805899, b: 0.9805899, a: 0.9805899} + - {r: 0.9842547, g: 0.9842547, b: 0.9842547, a: 0.9842547} + - {r: 0.98763186, g: 0.98763186, b: 0.98763186, a: 0.98763186} + - {r: 0.9906832, g: 0.9906832, b: 0.9906832, a: 0.9906832} + - {r: 0.99337023, g: 0.99337023, b: 0.99337023, a: 0.99337023} + - {r: 0.9956547, g: 0.9956547, b: 0.9956547, a: 0.9956547} + - {r: 0.9974983, g: 0.9974983, b: 0.9974983, a: 0.9974983} + - {r: 0.99886256, g: 0.99886256, b: 0.99886256, a: 0.99886256} + - {r: 0.99970925, g: 0.99970925, b: 0.99970925, a: 0.99970925} + - {r: 1, g: 1, b: 1, a: 1} + m_Scatter: + m_OverrideState: 1 + m_Value: 0.271 + m_Color: + m_OverrideState: 0 + m_Value: + _grad: + serializedVersion: 2 + key0: {r: 1, g: 1, b: 1, a: 0} + key1: {r: 1, g: 1, b: 1, a: 0} + key2: {r: 0, g: 0, b: 0, a: 0} + key3: {r: 0, g: 0, b: 0, a: 0} + key4: {r: 0, g: 0, b: 0, a: 0} + key5: {r: 0, g: 0, b: 0, a: 0} + key6: {r: 0, g: 0, b: 0, a: 0} + key7: {r: 0, g: 0, b: 0, a: 0} + ctime0: 0 + ctime1: 65535 + ctime2: 0 + ctime3: 0 + ctime4: 0 + ctime5: 0 + ctime6: 0 + ctime7: 0 + atime0: 0 + atime1: 0 + atime2: 0 + atime3: 0 + atime4: 0 + atime5: 0 + atime6: 0 + atime7: 0 + m_Mode: 0 + m_ColorSpace: -1 + m_NumColorKeys: 2 + m_NumAlphaKeys: 2 + _pixels: + - {r: 1, g: 1, b: 1, a: 0} + - {r: 1, g: 1, b: 1, a: 0} + - {r: 1, g: 1, b: 1, a: 0} + - {r: 1, g: 1, b: 1, a: 0} + - {r: 1, g: 1, b: 1, a: 0} + - {r: 1, g: 1, b: 1, a: 0} + - {r: 1, g: 1, b: 1, a: 0} + - {r: 1, g: 1, b: 1, a: 0} + - {r: 1, g: 1, b: 1, a: 0} + - {r: 1, g: 1, b: 1, a: 0} + - {r: 1, g: 1, b: 1, a: 0} + - {r: 1, g: 1, b: 1, a: 0} + - {r: 1, g: 1, b: 1, a: 0} + - {r: 1, g: 1, b: 1, a: 0} + - {r: 1, g: 1, b: 1, a: 0} + - {r: 1, g: 1, b: 1, a: 0} + - {r: 1, g: 1, b: 1, a: 0} + - {r: 1, g: 1, b: 1, a: 0} + - {r: 1, g: 1, b: 1, a: 0} + - {r: 1, g: 1, b: 1, a: 0} + - {r: 1, g: 1, b: 1, a: 0} + - {r: 1, g: 1, b: 1, a: 0} + - {r: 1, g: 1, b: 1, a: 0} + - {r: 1, g: 1, b: 1, a: 0} + - {r: 1, g: 1, b: 1, a: 0} + - {r: 1, g: 1, b: 1, a: 0} + - {r: 1, g: 1, b: 1, a: 0} + - {r: 1, g: 1, b: 1, a: 0} + - {r: 1, g: 1, b: 1, a: 0} + - {r: 1, g: 1, b: 1, a: 0} + - {r: 1, g: 1, b: 1, a: 0} + - {r: 1, g: 1, b: 1, a: 0} + m_Flicker: + m_OverrideState: 0 + m_Value: 1 +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d7fd9488000d3734a9e00ee676215985, type: 3} + m_Name: DreamBloom + m_EditorClassIdentifier: + components: + - {fileID: -1446237002707825744} + - {fileID: 687241930581274603} + - {fileID: 7186872832086462168} +--- !u!114 &687241930581274603 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d94e4d16c32d4354919ca310e9b07591, type: 3} + m_Name: AdjustmentsVol + m_EditorClassIdentifier: + active: 1 + m_Tint: + m_OverrideState: 0 + m_Value: {r: 1, g: 1, b: 1, a: 1} + m_Threshold: + m_OverrideState: 1 + m_Value: + _curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + _pixels: + - {r: 1, g: 1, b: 1, a: 1} + - {r: 1, g: 1, b: 1, a: 1} + - {r: 1, g: 1, b: 1, a: 1} + - {r: 1, g: 1, b: 1, a: 1} + - {r: 1, g: 1, b: 1, a: 1} + - {r: 1, g: 1, b: 1, a: 1} + - {r: 1, g: 1, b: 1, a: 1} + - {r: 1, g: 1, b: 1, a: 1} + - {r: 1, g: 1, b: 1, a: 1} + - {r: 1, g: 1, b: 1, a: 1} + - {r: 1, g: 1, b: 1, a: 1} + - {r: 1, g: 1, b: 1, a: 1} + - {r: 1, g: 1, b: 1, a: 1} + - {r: 1, g: 1, b: 1, a: 1} + - {r: 1, g: 1, b: 1, a: 1} + - {r: 1, g: 1, b: 1, a: 1} + - {r: 1, g: 1, b: 1, a: 1} + - {r: 1, g: 1, b: 1, a: 1} + - {r: 1, g: 1, b: 1, a: 1} + - {r: 1, g: 1, b: 1, a: 1} + - {r: 1, g: 1, b: 1, a: 1} + - {r: 1, g: 1, b: 1, a: 1} + - {r: 1, g: 1, b: 1, a: 1} + - {r: 1, g: 1, b: 1, a: 1} + - {r: 1, g: 1, b: 1, a: 1} + - {r: 1, g: 1, b: 1, a: 1} + - {r: 1, g: 1, b: 1, a: 1} + - {r: 1, g: 1, b: 1, a: 1} + - {r: 1, g: 1, b: 1, a: 1} + - {r: 1, g: 1, b: 1, a: 1} + - {r: 1, g: 1, b: 1, a: 1} + - {r: 1, g: 1, b: 1, a: 1} + m_Hue: + m_OverrideState: 0 + m_Value: 0 + m_Saturation: + m_OverrideState: 0 + m_Value: 0 + m_Brightness: + m_OverrideState: 1 + m_Value: 0 + m_Contrast: + m_OverrideState: 0 + m_Value: 0 + m_Alpha: + m_OverrideState: 0 + m_Value: 0 +--- !u!114 &7186872832086462168 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 584f4d053daa4e17a331821f306111c9, type: 3} + m_Name: ChromaticVol + m_EditorClassIdentifier: + active: 0 + _Weight: + m_OverrideState: 1 + m_Value: 1 + _Intensity: + m_OverrideState: 1 + m_Value: 0.283 + _Radial: + m_OverrideState: 0 + m_Value: 0.041 + _Alpha: + m_OverrideState: 1 + m_Value: 0.244 + _Angle: + m_OverrideState: 0 + m_Value: 0 + _Split: + m_OverrideState: 0 + m_Value: 0.098 + _Sat: + m_OverrideState: 0 + m_Value: 1 + _Mono: + m_OverrideState: 1 + m_Value: 1 diff --git a/Assets/GameContent/Scene_Dream/Materials/DreamDataOverflow.mat.meta b/Assets/Scenes/梦境/DreamBloom.asset.meta similarity index 64% rename from Assets/GameContent/Scene_Dream/Materials/DreamDataOverflow.mat.meta rename to Assets/Scenes/梦境/DreamBloom.asset.meta index 5f9152ca1..9bf233313 100644 --- a/Assets/GameContent/Scene_Dream/Materials/DreamDataOverflow.mat.meta +++ b/Assets/Scenes/梦境/DreamBloom.asset.meta @@ -1,8 +1,8 @@ fileFormatVersion: 2 -guid: db54ed6c97bf4f05a79f53b268f0c52a +guid: 16aa9506970514f408d2bfa36ab28503 NativeFormatImporter: externalObjects: {} - mainObjectFileID: 2100000 + mainObjectFileID: 11400000 userData: assetBundleName: assetBundleVariant: diff --git a/Assets/Scripts/Dialog System/BaseYarnCommand.cs b/Assets/Scripts/Dialog System/BaseYarnCommand.cs index ee673d3a6..8402b8337 100644 --- a/Assets/Scripts/Dialog System/BaseYarnCommand.cs +++ b/Assets/Scripts/Dialog System/BaseYarnCommand.cs @@ -347,22 +347,6 @@ namespace AibisDream yield return SpriteShowcase.Instance.ShowObj(picName, duration); } - [YarnCommand("dream_overflow_on")] - public static IEnumerator DreamOverflowOn(string preset = "entry", float duration = 0.35f) - { - var showcase = SpriteShowcase.Instance; - if (showcase == null) yield break; - yield return showcase.SetDreamOverflow(preset, 1f, duration); - } - - [YarnCommand("dream_overflow_off")] - public static IEnumerator DreamOverflowOff(float duration = 0.8f) - { - var showcase = SpriteShowcase.Instance; - if (showcase == null) yield break; - yield return showcase.SetDreamOverflow(null, 0f, duration); - } - [YarnCommand("show_sprite_motion")] public static IEnumerator ShowSpriteMotion(string picName, string motionProfile, float duration = 0.35f) { diff --git a/Assets/Scripts/SceneManagement/DreamDoorSystem.cs b/Assets/Scripts/SceneManagement/DreamDoorSystem.cs index beda35eec..7b41d6fcb 100644 --- a/Assets/Scripts/SceneManagement/DreamDoorSystem.cs +++ b/Assets/Scripts/SceneManagement/DreamDoorSystem.cs @@ -4,7 +4,6 @@ using AibisDream.UI; using AibisDream.Utility; using DG.Tweening; using UnityEngine; -using UnityEngine.Video; namespace AibisDream { @@ -21,12 +20,23 @@ namespace AibisDream [Tooltip("仅放门的静态 background,不要把 glassSea/codeSea/overlay 拖进来。")] [SerializeField] private Renderer[] backgroundRenderers; [SerializeField] private Renderer[] frameRenderers; + [SerializeField] private Sprite whiteDoorFrameSprite; + [SerializeField] private Sprite seaDoorFrameSprite; [SerializeField] private SpriteRenderer sceneBlackOverlay; - [Header("Door Sea Memory")] - [SerializeField] private VideoClip glassSeaVideoClip; - [SerializeField] private RenderTexture glassSeaTargetTexture; - [SerializeField, Min(0.5f)] private float glassSeaPrepareTimeout = 5f; + [Header("Door Sea Animation")] + [SerializeField] private Animator glassSeaAnimator; + [SerializeField] private string glassSeaStateName = "DoorGlassSeaLoop"; + [SerializeField] private string glassSeaFramedStateName = "DoorGlassSeaFramedLoop"; + [SerializeField, Min(1f)] private float glassSeaCoverOverscan = 1.02f; + + [Header("Code Sea Animation")] + [Tooltip("代码海切入时的固定波浪相位(单位:字符网格行)。用于匹配金色海浪切换前的构图。")] + [SerializeField] private float codeSeaStartPhase = 7.5f; + [Tooltip("代码海由远向近推进的速度(单位:字符网格行/秒)。")] + [SerializeField, Min(0f)] private float codeSeaWaveSpeed = 2.6f; + [Tooltip("0/1 和波浪符号独立于海浪移动的闪烁速度。")] + [SerializeField, Min(0f)] private float codeSeaGlyphSpeed = 3.2f; [Header("Terminal(挂在 Door 子节点上即可,无需 Canvas)")] [SerializeField] private DreamTerminalUI terminalUI; @@ -55,6 +65,7 @@ namespace AibisDream [SerializeField] private string morphStartTimelineName = "姐姐/Glitch"; private Transform _codeSeaTransform; + private Vector3 _codeSeaOriginalLocalPosition; private Vector3 _codeSeaOriginalScale; private Color _codeSeaOriginalColor; private Transform _terminalUiTransform; @@ -62,15 +73,16 @@ namespace AibisDream private Vector3 _terminalUiOriginalLocalPosition; private Transform _doorShellTransform; private Vector3 _doorShellOriginalScale; - private VideoPlayer _glassSeaVideoPlayer; - private Material _glassSeaMaterial; - private bool _glassSeaVideoPrepared; - private bool _glassSeaVideoFailed; - private bool _glassSeaFrameReady; + private Vector3 _glassSeaOriginalLocalPosition; + private Vector3 _glassSeaOriginalLocalScale; + private string _glassSeaCurrentStateName; + private MaterialPropertyBlock _codeSeaPropertyBlock; + private bool _codeSeaPlaybackActive; + private static readonly int WaveStartTimeId = Shader.PropertyToID("_WaveStartTime"); + private static readonly int WavePhaseId = Shader.PropertyToID("_WavePhase"); + private static readonly int WaveSpeedId = Shader.PropertyToID("_WaveSpeed"); + private static readonly int GlyphSpeedId = Shader.PropertyToID("_GlyphSpeed"); private DoorPresentationPhase _presentationPhase = DoorPresentationPhase.Hidden; - - private static readonly int UseVideoId = Shader.PropertyToID("_UseVideo"); - private enum FrameHidePhase { Never, @@ -98,21 +110,26 @@ namespace AibisDream if (glassSea != null) { - _glassSeaMaterial = glassSea.material; - SetGlassSeaVideoVisible(false); + _glassSeaOriginalLocalPosition = glassSea.transform.localPosition; + _glassSeaOriginalLocalScale = glassSea.transform.localScale; + if (glassSeaAnimator == null) + glassSeaAnimator = glassSea.GetComponent(); + glassSea.SetAlpha(0); + StopGlassSeaAnimation(resetToFirstFrame: true); glassSea.gameObject.SetActive(false); } - InitializeGlassSeaVideo(); + SetDoorFrameSprite(hasSea: false); if (codeSea != null) { - codeSea.SetAlpha(0); - codeSea.gameObject.SetActive(false); _codeSeaTransform = codeSea.transform; + _codeSeaOriginalLocalPosition = _codeSeaTransform.localPosition; _codeSeaOriginalScale = _codeSeaTransform.localScale; _codeSeaOriginalColor = codeSea.color; + codeSea.SetAlpha(0); + codeSea.gameObject.SetActive(false); } if (flashOverlay != null) @@ -139,26 +156,14 @@ namespace AibisDream _presentationPhase = DoorPresentationPhase.Hidden; } - public override void OnSingletonDestroy() - { - if (_glassSeaVideoPlayer != null) - { - _glassSeaVideoPlayer.prepareCompleted -= OnGlassSeaVideoPrepared; - _glassSeaVideoPlayer.frameReady -= OnGlassSeaVideoFrameReady; - _glassSeaVideoPlayer.errorReceived -= OnGlassSeaVideoError; - } - - base.OnSingletonDestroy(); - } - /// /// 显示普通门。该命令是一个完整状态切换,会清掉之前残留的海景、代码海浪和终端。 /// public IEnumerator ShowDoor(float duration = 0f) { StopAllEffects(); - EnsureDoorBaseVisible(); - ResetGlassSeaImmediate(stopVideo: true); + EnsureDoorBaseVisible(hasSea: false); + ResetGlassSeaImmediate(); ResetCodeSeaImmediate(); ResetTerminalImmediate(); _presentationPhase = DoorPresentationPhase.Door; @@ -167,6 +172,36 @@ namespace AibisDream yield return new WaitForSeconds(duration); } + /// + /// 进入“仔细听”的门近景。首次是白底门,之后直接显示门后的金色海浪。 + /// + public IEnumerator ShowListenView(bool showSea, float duration = 0f) + { + StopAllEffects(); + EnsureDoorBaseVisible(showSea); + ResetCodeSeaImmediate(); + ResetTerminalImmediate(); + + var showcase = SpriteShowcase.Instance; + if (showcase != null) + showcase.SetLargePresentationImmediate(1f, 1f); + + if (showSea && glassSea != null) + { + glassSea.SetAlpha(1f); + StartGlassSeaAnimation(glassSeaFramedStateName); + _presentationPhase = DoorPresentationPhase.GlassSea; + } + else + { + ResetGlassSeaImmediate(); + _presentationPhase = DoorPresentationPhase.Door; + } + + if (duration > 0f) + yield return new WaitForSeconds(duration); + } + /// /// 隐藏整个门 /// @@ -184,16 +219,16 @@ namespace AibisDream yield break; StopAllEffects(); - EnsureDoorBaseVisible(); + EnsureDoorBaseVisible(hasSea: true); ResetCodeSeaImmediate(); ResetTerminalImmediate(); if (_presentationPhase != DoorPresentationPhase.GlassSea || !glassSea.gameObject.activeSelf) glassSea.SetAlpha(0f); - glassSea.gameObject.SetActive(true); + StartGlassSeaAnimation(glassSeaFramedStateName); _presentationPhase = DoorPresentationPhase.GlassSea; - yield return EnsureGlassSeaVideoPlaying(); + yield return glassSea.DOFade(1f, Mathf.Max(0f, duration)) .SetEase(Ease.InOutSine) .WaitForCompletion(); @@ -203,7 +238,6 @@ namespace AibisDream { if (glassSea == null) { - PauseGlassSeaVideo(); yield break; } @@ -217,13 +251,92 @@ namespace AibisDream } glassSea.SetAlpha(0f); + StopGlassSeaAnimation(resetToFirstFrame: true); glassSea.gameObject.SetActive(false); - PauseGlassSeaVideo(); if (_presentationPhase == DoorPresentationPhase.GlassSea) _presentationPhase = DoorPresentationPhase.Door; } + /// + /// 只调整近景门图片的缩放与透明度,不包含白幕、Bloom 或海浪状态切换。 + /// + public IEnumerator TweenListenCloseup(float scale, float alpha, float duration) + { + var showcase = SpriteShowcase.Instance; + if (showcase == null) + yield break; + + yield return showcase.AnimateLargePresentation(scale, alpha, duration); + } + + public void SetListenCloseup(float scale, float alpha) + { + SpriteShowcase.Instance?.SetLargePresentationImmediate(scale, alpha); + } + + /// + /// 全白遮罩下调用的瞬时状态切换:隐藏门底和门框,仅显示全屏金色海浪。 + /// + public void ShowGlassSeaFullscreen() + { + if (doorRoot != null) + doorRoot.gameObject.SetActive(true); + + SetBackgroundVisible(false); + SetFrameVisible(false); + ResetCodeSeaImmediate(); + EnsureGlassSeaVisible(glassSeaStateName); + } + + /// + /// 全白遮罩下调用的瞬时状态切换:恢复门底和门框,金色海浪留在门后。 + /// + public void ShowGlassSeaFramed() + { + ResetCodeSeaImmediate(); + EnsureDoorBaseVisible(hasSea: true); + EnsureGlassSeaVisible(glassSeaFramedStateName); + } + + /// + /// 全白时切到无门的全屏 CodeSea;状态职责与 ShowGlassSeaFullscreen 一致。 + /// + public void ShowCodeSeaFullscreen() + { + if (doorRoot != null) + doorRoot.gameObject.SetActive(true); + + var restartPlayback = _presentationPhase != DoorPresentationPhase.CodeSea + || !_codeSeaPlaybackActive; + SetBackgroundVisible(false); + SetFrameVisible(false); + ResetGlassSeaImmediate(); + EnsureCodeSeaVisible(restartPlayback); + } + + /// + /// 全白时恢复门框,CodeSea 保持显示在门内。 + /// + public void ShowCodeSeaFramed() + { + var restartPlayback = _presentationPhase != DoorPresentationPhase.CodeSea + || !_codeSeaPlaybackActive; + ResetGlassSeaImmediate(); + EnsureDoorBaseVisible(hasSea: false); + EnsureCodeSeaFramedVisible(restartPlayback); + } + + private void ResetListenTransitionImmediate() + { + var panel = UIManager.Instance != null + ? UIManager.Instance.GetPanel() + : null; + panel?.FadeOutSync(0f); + + SpriteShowcase.Instance?.ResetLargePresentationImmediate(); + } + #endregion #region Phase 2: CodeSea 浮现 (GlassSea 交叉淡出) @@ -233,15 +346,21 @@ namespace AibisDream if (codeSea == null) yield break; + var restartPlayback = _presentationPhase != DoorPresentationPhase.CodeSea + || !_codeSeaPlaybackActive; StopAllEffects(); - EnsureDoorBaseVisible(); + EnsureDoorBaseVisible(hasSea: false); ResetTerminalImmediate(); codeSea.color = _codeSeaOriginalColor; if (_codeSeaTransform != null) + { + _codeSeaTransform.localPosition = _codeSeaOriginalLocalPosition; _codeSeaTransform.localScale = _codeSeaOriginalScale; + } codeSea.SetAlpha(0f); codeSea.gameObject.SetActive(true); + BeginCodeSeaPlayback(restartPlayback); _presentationPhase = DoorPresentationPhase.CodeSea; if (frameHidePhase == FrameHidePhase.OnCodeSea) @@ -259,10 +378,10 @@ namespace AibisDream if (glassSea != null) { glassSea.SetAlpha(0f); + StopGlassSeaAnimation(resetToFirstFrame: true); glassSea.gameObject.SetActive(false); } - StopGlassSeaVideo(); } #endregion @@ -302,12 +421,16 @@ namespace AibisDream SetFrameVisible(false); if (glassSea != null) + { + StopGlassSeaAnimation(resetToFirstFrame: true); glassSea.gameObject.SetActive(false); - - StopGlassSeaVideo(); + } if (codeSea != null) + { codeSea.gameObject.SetActive(false); + ResetCodeSeaPlayback(); + } if (flashOverlay != null) flashOverlay.SetAlpha(0f); @@ -387,6 +510,7 @@ namespace AibisDream DOTween.Kill(_doorShellTransform); DOTween.Kill(flashOverlay); DOTween.Kill(sceneBlackOverlay); + SpriteShowcase.Instance?.StopLargePresentationAnimation(); } #endregion @@ -396,19 +520,20 @@ namespace AibisDream public void HideAll() { StopAllEffects(); + ResetListenTransitionImmediate(); HideDoor(); SetBackgroundVisible(true); SetFrameVisible(true); + SetDoorFrameSprite(hasSea: false); ResetDoorShellScale(); if (glassSea != null) { glassSea.SetAlpha(0); + StopGlassSeaAnimation(resetToFirstFrame: true); glassSea.gameObject.SetActive(false); } - StopGlassSeaVideo(); - if (codeSea != null) { codeSea.color = _codeSeaOriginalColor; @@ -417,6 +542,7 @@ namespace AibisDream if (_codeSeaTransform != null) _codeSeaTransform.localScale = _codeSeaOriginalScale; } + ResetCodeSeaPlayback(); if (terminalUI != null) { @@ -436,6 +562,12 @@ namespace AibisDream if (sceneBlackOverlay != null) sceneBlackOverlay.SetAlpha(0); + var showcase = SpriteShowcase.Instance; + if (showcase != null) + { + showcase.HideLargePresentationImmediate(); + } + _presentationPhase = DoorPresentationPhase.Hidden; } @@ -443,30 +575,44 @@ namespace AibisDream #region Presentation State - private void EnsureDoorBaseVisible() + private void EnsureDoorBaseVisible(bool hasSea = false) { if (doorRoot != null) doorRoot.gameObject.SetActive(true); SetBackgroundVisible(true); SetFrameVisible(true); + SetDoorFrameSprite(hasSea); ResetDoorShellScale(); } - private void ResetGlassSeaImmediate(bool stopVideo) + private void ResetGlassSeaImmediate() { DOTween.Kill(glassSea); if (glassSea != null) { glassSea.SetAlpha(0f); + StopGlassSeaAnimation(resetToFirstFrame: true); glassSea.gameObject.SetActive(false); } + } - if (stopVideo) - StopGlassSeaVideo(); + private void EnsureGlassSeaVisible(string stateName) + { + if (glassSea == null) + return; + + glassSea.SetAlpha(1f); + if (!glassSea.gameObject.activeSelf + || glassSeaAnimator == null + || !glassSeaAnimator.enabled + || _glassSeaCurrentStateName != stateName) + StartGlassSeaAnimation(stateName); else - PauseGlassSeaVideo(); + FitGlassSeaToCameraCover(); + + _presentationPhase = DoorPresentationPhase.GlassSea; } private void ResetCodeSeaImmediate() @@ -474,6 +620,8 @@ namespace AibisDream DOTween.Kill(_codeSeaTransform); DOTween.Kill(codeSea); + ResetCodeSeaPlayback(); + if (codeSea == null) return; @@ -482,7 +630,62 @@ namespace AibisDream codeSea.gameObject.SetActive(false); if (_codeSeaTransform != null) + { + _codeSeaTransform.localPosition = _codeSeaOriginalLocalPosition; _codeSeaTransform.localScale = _codeSeaOriginalScale; + } + } + + private void EnsureCodeSeaVisible(bool restartPlayback) + { + if (codeSea == null) + return; + + codeSea.color = _codeSeaOriginalColor; + codeSea.SetAlpha(1f); + codeSea.gameObject.SetActive(true); + BeginCodeSeaPlayback(restartPlayback); + FitCodeSeaToCameraCover(); + _presentationPhase = DoorPresentationPhase.CodeSea; + } + + private void EnsureCodeSeaFramedVisible(bool restartPlayback) + { + if (codeSea == null) + return; + + codeSea.color = _codeSeaOriginalColor; + codeSea.SetAlpha(1f); + codeSea.gameObject.SetActive(true); + BeginCodeSeaPlayback(restartPlayback); + + if (_codeSeaTransform != null) + { + _codeSeaTransform.localPosition = _codeSeaOriginalLocalPosition; + _codeSeaTransform.localScale = _codeSeaOriginalScale; + } + + _presentationPhase = DoorPresentationPhase.CodeSea; + } + + private void BeginCodeSeaPlayback(bool restartPlayback) + { + if (codeSea == null || (_codeSeaPlaybackActive && !restartPlayback)) + return; + + _codeSeaPropertyBlock ??= new MaterialPropertyBlock(); + codeSea.GetPropertyBlock(_codeSeaPropertyBlock); + _codeSeaPropertyBlock.SetFloat(WaveStartTimeId, Time.time); + _codeSeaPropertyBlock.SetFloat(WavePhaseId, codeSeaStartPhase); + _codeSeaPropertyBlock.SetFloat(WaveSpeedId, codeSeaWaveSpeed); + _codeSeaPropertyBlock.SetFloat(GlyphSpeedId, codeSeaGlyphSpeed); + codeSea.SetPropertyBlock(_codeSeaPropertyBlock); + _codeSeaPlaybackActive = true; + } + + private void ResetCodeSeaPlayback() + { + _codeSeaPlaybackActive = false; } private void ResetTerminalImmediate() @@ -510,118 +713,121 @@ namespace AibisDream #endregion - #region GlassSea Video + #region GlassSea Animation - private void InitializeGlassSeaVideo() + private void StartGlassSeaAnimation(string stateName = null) { - if (glassSeaVideoClip == null || glassSeaTargetTexture == null) + if (glassSea == null) return; + + stateName = string.IsNullOrEmpty(stateName) ? glassSeaStateName : stateName; + + glassSea.gameObject.SetActive(true); + if (glassSeaAnimator != null && glassSeaAnimator.runtimeAnimatorController != null) { - SetGlassSeaVideoVisible(false); - return; + glassSeaAnimator.enabled = true; + glassSeaAnimator.Play(stateName, 0, 0f); + glassSeaAnimator.Update(0f); + _glassSeaCurrentStateName = stateName; } - _glassSeaVideoPlayer = GetComponent(); - if (_glassSeaVideoPlayer == null) - _glassSeaVideoPlayer = gameObject.AddComponent(); - - _glassSeaVideoPlayer.playOnAwake = false; - _glassSeaVideoPlayer.source = VideoSource.VideoClip; - _glassSeaVideoPlayer.clip = glassSeaVideoClip; - _glassSeaVideoPlayer.renderMode = VideoRenderMode.RenderTexture; - _glassSeaVideoPlayer.targetTexture = glassSeaTargetTexture; - _glassSeaVideoPlayer.audioOutputMode = VideoAudioOutputMode.None; - _glassSeaVideoPlayer.isLooping = true; - _glassSeaVideoPlayer.skipOnDrop = true; - _glassSeaVideoPlayer.waitForFirstFrame = true; - _glassSeaVideoPlayer.sendFrameReadyEvents = true; - - _glassSeaVideoPlayer.prepareCompleted += OnGlassSeaVideoPrepared; - _glassSeaVideoPlayer.frameReady += OnGlassSeaVideoFrameReady; - _glassSeaVideoPlayer.errorReceived += OnGlassSeaVideoError; - - _glassSeaVideoPrepared = false; - _glassSeaVideoFailed = false; - _glassSeaFrameReady = false; - SetGlassSeaVideoVisible(false); - _glassSeaVideoPlayer.Prepare(); + FitGlassSeaToCameraCover(); } - private IEnumerator EnsureGlassSeaVideoPlaying() + private void StopGlassSeaAnimation(bool resetToFirstFrame) { - if (_glassSeaVideoPlayer == null || _glassSeaVideoFailed) + if (glassSeaAnimator == null) return; + + if (resetToFirstFrame + && glassSeaAnimator.runtimeAnimatorController != null + && glassSeaAnimator.gameObject.activeInHierarchy) { - SetGlassSeaVideoVisible(false); - yield break; + var stateName = string.IsNullOrEmpty(_glassSeaCurrentStateName) + ? glassSeaStateName + : _glassSeaCurrentStateName; + glassSeaAnimator.enabled = true; + glassSeaAnimator.Play(stateName, 0, 0f); + glassSeaAnimator.Update(0f); } - if (!_glassSeaVideoPrepared && !_glassSeaVideoPlayer.isPrepared) - { - float deadline = Time.realtimeSinceStartup + glassSeaPrepareTimeout; - while (!_glassSeaVideoPrepared && !_glassSeaVideoFailed && Time.realtimeSinceStartup < deadline) - yield return null; + glassSeaAnimator.enabled = false; + _glassSeaCurrentStateName = null; + } - if (!_glassSeaVideoPrepared && !_glassSeaVideoPlayer.isPrepared) - { - _glassSeaVideoFailed = true; - _glassSeaVideoPlayer.Stop(); - SetGlassSeaVideoVisible(false); - Debug.LogWarning("[DreamDoorSystem] 海景视频准备超时,回退到静态海报。", this); - yield break; - } + private void FitGlassSeaToCameraCover() + { + FitSpriteToCameraCover( + glassSea, + _glassSeaOriginalLocalPosition, + _glassSeaOriginalLocalScale); + } + + private void FitCodeSeaToCameraCover() + { + FitSpriteToCameraCover( + codeSea, + _codeSeaOriginalLocalPosition, + _codeSeaOriginalScale); + } + + private void FitSpriteToCameraCover( + SpriteRenderer target, + Vector3 originalLocalPosition, + Vector3 originalLocalScale) + { + if (target == null || target.sprite == null) return; + + var targetCamera = ResolveDoorCamera(); + if (targetCamera == null) return; + + var seaTransform = target.transform; + var parent = seaTransform.parent; + var depth = Vector3.Dot(seaTransform.position - targetCamera.transform.position, targetCamera.transform.forward); + depth = Mathf.Max(depth, targetCamera.nearClipPlane + 0.05f); + + float viewWidth; + float viewHeight; + if (targetCamera.orthographic) + { + viewHeight = targetCamera.orthographicSize * 2f; + viewWidth = viewHeight * targetCamera.aspect; + } + else + { + var bottomLeft = targetCamera.ViewportToWorldPoint(new Vector3(0f, 0f, depth)); + var bottomRight = targetCamera.ViewportToWorldPoint(new Vector3(1f, 0f, depth)); + var topLeft = targetCamera.ViewportToWorldPoint(new Vector3(0f, 1f, depth)); + viewWidth = Vector3.Distance(bottomLeft, bottomRight); + viewHeight = Vector3.Distance(bottomLeft, topLeft); } - _glassSeaVideoPrepared = true; - if (!_glassSeaVideoPlayer.isPlaying) - _glassSeaVideoPlayer.Play(); + var spriteSize = target.sprite.bounds.size; + if (spriteSize.x <= 0.001f || spriteSize.y <= 0.001f) return; - if (!_glassSeaFrameReady) + var parentScale = parent != null ? parent.lossyScale : Vector3.one; + var localScale = Mathf.Max( + viewWidth / (spriteSize.x * Mathf.Max(Mathf.Abs(parentScale.x), 0.001f)), + viewHeight / (spriteSize.y * Mathf.Max(Mathf.Abs(parentScale.y), 0.001f))); + localScale *= glassSeaCoverOverscan; + + var worldCenter = targetCamera.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, depth)); + var localCenter = parent != null ? parent.InverseTransformPoint(worldCenter) : worldCenter; + localCenter.z = originalLocalPosition.z; + + seaTransform.localPosition = localCenter; + seaTransform.localScale = new Vector3(localScale, localScale, originalLocalScale.z); + } + + private Camera ResolveDoorCamera() + { + foreach (var candidate in Camera.allCameras) { - float firstFrameDeadline = Time.realtimeSinceStartup + 1f; - while (!_glassSeaFrameReady && !_glassSeaVideoFailed && Time.realtimeSinceStartup < firstFrameDeadline) - yield return null; + if (candidate != null + && candidate.isActiveAndEnabled + && candidate.gameObject.scene == gameObject.scene) + return candidate; } - } - private void PauseGlassSeaVideo() - { - if (_glassSeaVideoPlayer != null && _glassSeaVideoPlayer.isPlaying) - _glassSeaVideoPlayer.Pause(); - } - - private void StopGlassSeaVideo() - { - if (_glassSeaVideoPlayer != null) - _glassSeaVideoPlayer.Stop(); - - _glassSeaFrameReady = false; - SetGlassSeaVideoVisible(false); - } - - private void OnGlassSeaVideoPrepared(VideoPlayer source) - { - _glassSeaVideoPrepared = true; - _glassSeaVideoFailed = false; - } - - private void OnGlassSeaVideoFrameReady(VideoPlayer source, long frameIndex) - { - _glassSeaFrameReady = true; - SetGlassSeaVideoVisible(true); - } - - private void OnGlassSeaVideoError(VideoPlayer source, string message) - { - _glassSeaVideoFailed = true; - _glassSeaVideoPrepared = false; - _glassSeaFrameReady = false; - SetGlassSeaVideoVisible(false); - Debug.LogWarning($"[DreamDoorSystem] 海景视频播放失败,回退到静态海报:{message}", this); - } - - private void SetGlassSeaVideoVisible(bool visible) - { - if (_glassSeaMaterial != null && _glassSeaMaterial.HasProperty(UseVideoId)) - _glassSeaMaterial.SetFloat(UseVideoId, visible ? 1f : 0f); + return Camera.main; } #endregion @@ -637,6 +843,24 @@ namespace AibisDream } } + private void SetDoorFrameSprite(bool hasSea) + { + var targetSprite = hasSea ? seaDoorFrameSprite : whiteDoorFrameSprite; + if (targetSprite == null) + return; + + if (frameRenderers != null) + { + foreach (var frameRenderer in frameRenderers) + { + if (frameRenderer is SpriteRenderer spriteRenderer) + spriteRenderer.sprite = targetSprite; + } + } + + SpriteShowcase.Instance?.SetLargeSpriteImmediate(targetSprite); + } + private void SetBackgroundVisible(bool visible) { if (backgroundRenderers == null) return; diff --git a/Assets/Scripts/SceneManagement/DreamDoorYarnCommand.cs b/Assets/Scripts/SceneManagement/DreamDoorYarnCommand.cs index 35a3de779..8f9706c4e 100644 --- a/Assets/Scripts/SceneManagement/DreamDoorYarnCommand.cs +++ b/Assets/Scripts/SceneManagement/DreamDoorYarnCommand.cs @@ -1,47 +1,130 @@ using System.Collections; +using UnityEngine; using Yarn.Unity; namespace AibisDream { public static class DreamDoorYarnCommand { + private static DreamDoorSystem ResolveSystem() + { + if (DreamDoorSystem.Instance != null) + return DreamDoorSystem.Instance; + + var system = Object.FindObjectOfType(includeInactive: true); + if (system == null) + { + Debug.LogError("[DreamDoorYarnCommand] 当前场景中不存在 DreamDoorSystem,已跳过门演出命令。"); + return null; + } + + if (!system.gameObject.activeSelf) + system.gameObject.SetActive(true); + + return DreamDoorSystem.Instance != null ? DreamDoorSystem.Instance : system; + } + /// /// 显示整个门(仅 background + Frame)。默认门是隐藏的,需先调用此命令。 /// [YarnCommand("show_door")] public static IEnumerator ShowDoor(float duration = 0f) { - yield return DreamDoorSystem.Instance.ShowDoor(duration); + var system = ResolveSystem(); + if (system == null) yield break; + yield return system.ShowDoor(duration); + } + + [YarnCommand("show_door_listen_view")] + public static IEnumerator ShowDoorListenView(bool showSea = false, float duration = 0f) + { + var system = ResolveSystem(); + if (system == null) yield break; + yield return system.ShowListenView(showSea, duration); } [YarnCommand("show_door_glass_sea")] public static IEnumerator ShowDoorGlassSea(float duration = 2f) { - yield return DreamDoorSystem.Instance.ShowGlassSea(duration); + var system = ResolveSystem(); + if (system == null) yield break; + yield return system.ShowGlassSea(duration); } [YarnCommand("hide_door_glass_sea")] public static IEnumerator HideDoorGlassSea(float duration = 1f) { - yield return DreamDoorSystem.Instance.HideGlassSea(duration); + var system = ResolveSystem(); + if (system == null) yield break; + yield return system.HideGlassSea(duration); + } + + [YarnCommand("tween_door_closeup")] + public static IEnumerator TweenDoorCloseup(float scale, float alpha, float duration) + { + var system = ResolveSystem(); + if (system == null) yield break; + yield return system.TweenListenCloseup(scale, alpha, duration); + } + + [YarnCommand("tween_door_closeup_async")] + public static void TweenDoorCloseupAsync(float scale, float alpha, float duration) + { + var system = ResolveSystem(); + if (system == null) return; + system.StartCoroutine(system.TweenListenCloseup(scale, alpha, duration)); + } + + [YarnCommand("set_door_closeup")] + public static void SetDoorCloseup(float scale, float alpha) + { + ResolveSystem()?.SetListenCloseup(scale, alpha); + } + + [YarnCommand("show_door_glass_sea_fullscreen")] + public static void ShowDoorGlassSeaFullscreen() + { + ResolveSystem()?.ShowGlassSeaFullscreen(); + } + + [YarnCommand("show_door_glass_sea_framed")] + public static void ShowDoorGlassSeaFramed() + { + ResolveSystem()?.ShowGlassSeaFramed(); } [YarnCommand("show_door_code_sea")] public static IEnumerator ShowDoorCodeSea(float duration = 2f) { - yield return DreamDoorSystem.Instance.ShowCodeSea(duration); + var system = ResolveSystem(); + if (system == null) yield break; + yield return system.ShowCodeSea(duration); + } + + [YarnCommand("show_door_code_sea_fullscreen")] + public static void ShowDoorCodeSeaFullscreen() + { + ResolveSystem()?.ShowCodeSeaFullscreen(); + } + + [YarnCommand("show_door_code_sea_framed")] + public static void ShowDoorCodeSeaFramed() + { + ResolveSystem()?.ShowCodeSeaFramed(); } [YarnCommand("show_dream_terminal")] public static IEnumerator ShowDreamTerminal() { - yield return DreamDoorSystem.Instance.ShowTerminal(); + var system = ResolveSystem(); + if (system == null) yield break; + yield return system.ShowTerminal(); } [YarnCommand("hide_dream_door")] public static void HideDreamDoor() { - DreamDoorSystem.Instance.HideAll(); + ResolveSystem()?.HideAll(); } } } diff --git a/Assets/Scripts/SceneManagement/SpriteShowcase.cs b/Assets/Scripts/SceneManagement/SpriteShowcase.cs index 96e8ad112..184886e82 100644 --- a/Assets/Scripts/SceneManagement/SpriteShowcase.cs +++ b/Assets/Scripts/SceneManagement/SpriteShowcase.cs @@ -20,33 +20,6 @@ namespace AibisDream [SerializeField] private SpriteRenderer _backgroundSpriteRenderer; [SerializeField] private SpriteRenderer _largeSpriteRenderer; - private struct DreamOverflowSettings - { - public float exposure; - public float glow; - public float chromatic; - public float noise; - - public DreamOverflowSettings(float exposure, float glow, float chromatic, float noise) - { - this.exposure = exposure; - this.glow = glow; - this.chromatic = chromatic; - this.noise = noise; - } - } - - private static readonly int OverflowIntensityId = Shader.PropertyToID("_OverflowIntensity"); - private static readonly int OverflowExposureId = Shader.PropertyToID("_OverflowExposure"); - private static readonly int OverflowGlowId = Shader.PropertyToID("_OverflowGlow"); - private static readonly int OverflowChromaticId = Shader.PropertyToID("_OverflowChromatic"); - private static readonly int OverflowNoiseId = Shader.PropertyToID("_OverflowNoise"); - - private MaterialPropertyBlock _dreamOverflowBlock; - private DreamOverflowSettings _dreamOverflowSettings; - private float _dreamOverflowIntensity; - private int _dreamOverflowTransitionVersion; - private SpriteRenderer _smallMotionRenderer; private SpriteMask _smallMotionMask; private DG.Tweening.Sequence _smallMotionSequence; @@ -56,15 +29,20 @@ namespace AibisDream private Vector3 _smallMotionBaseOffset; private string _currentSmallPicName; + private DG.Tweening.Sequence _largePresentationSequence; + private Vector3 _largeBaseLocalPosition; + private Quaternion _largeBaseLocalRotation; + private Vector3 _largeBaseLocalScale; + private float _largeBaseAlpha; + // 通过 activeSelf 判断当前状态 private bool IsSmallShowing => _spriteRenderer.gameObject.activeSelf; private bool IsLargeShowing => _largeSpriteRenderer != null && _largeSpriteRenderer.gameObject.activeSelf; public override void OnSingletonInit() { - _dreamOverflowSettings = EntryOverflowSettings(); - ResetDreamOverflow(); CaptureSmallBaseTransform(); + CaptureLargeBaseTransform(); // 初始状态:隐藏 _spriteRenderer.gameObject.SetActive(false); @@ -80,127 +58,13 @@ namespace AibisDream private void OnDisable() { - ResetDreamOverflow(); + HideLargePresentationImmediate(); } public override void OnSingletonDestroy() { - ResetDreamOverflow(); - } - - private static DreamOverflowSettings EntryOverflowSettings() - { - return new DreamOverflowSettings( - exposure: 1.45f, - glow: 0.65f, - chromatic: 0.006f, - noise: 0.08f); - } - - private static DreamOverflowSettings RuptureOverflowSettings() - { - return new DreamOverflowSettings( - exposure: 2.4f, - glow: 1.15f, - chromatic: 0.018f, - noise: 0.2f); - } - - private static DreamOverflowSettings ResolveDreamOverflowSettings(string preset) - { - var normalized = string.IsNullOrWhiteSpace(preset) - ? "entry" - : preset.Trim().ToLowerInvariant(); - - switch (normalized) - { - case "entry": - return EntryOverflowSettings(); - case "rupture": - return RuptureOverflowSettings(); - default: - Debug.LogWarning($"[SpriteShowcase] Unknown dream overflow preset '{preset}', using 'entry'."); - return EntryOverflowSettings(); - } - } - - /// - /// Drives the local overexposure/glow effect used by dream sprites. - /// The effect is applied through MaterialPropertyBlock so no material instances are created. - /// - public IEnumerator SetDreamOverflow(string preset, float target, float duration) - { - if (!string.IsNullOrWhiteSpace(preset)) - { - _dreamOverflowSettings = ResolveDreamOverflowSettings(preset); - } - - target = Mathf.Clamp01(target); - duration = Mathf.Max(0f, duration); - - var version = ++_dreamOverflowTransitionVersion; - var start = _dreamOverflowIntensity; - - if (duration <= 0f || !gameObject.activeInHierarchy) - { - _dreamOverflowIntensity = target; - ApplyDreamOverflow(); - yield break; - } - - var elapsed = 0f; - while (elapsed < duration) - { - if (version != _dreamOverflowTransitionVersion) - { - yield break; - } - - elapsed += Time.deltaTime; - var progress = Mathf.SmoothStep(0f, 1f, Mathf.Clamp01(elapsed / duration)); - _dreamOverflowIntensity = Mathf.Lerp(start, target, progress); - ApplyDreamOverflow(); - yield return null; - } - - if (version == _dreamOverflowTransitionVersion) - { - _dreamOverflowIntensity = target; - ApplyDreamOverflow(); - } - } - - private void ResetDreamOverflow() - { - _dreamOverflowTransitionVersion++; - _dreamOverflowIntensity = 0f; - ApplyDreamOverflow(); - } - - private void ApplyDreamOverflow() - { - ApplyDreamOverflow(_spriteRenderer); - ApplyDreamOverflow(_largeSpriteRenderer); - ApplyDreamOverflow(_smallMotionRenderer); - } - - private void ApplyDreamOverflow(SpriteRenderer target) - { - if (target == null) return; - - if (_dreamOverflowBlock == null) - { - _dreamOverflowBlock = new MaterialPropertyBlock(); - } - - target.GetPropertyBlock(_dreamOverflowBlock); - _dreamOverflowBlock.SetFloat(OverflowIntensityId, _dreamOverflowIntensity); - _dreamOverflowBlock.SetFloat(OverflowExposureId, _dreamOverflowSettings.exposure); - _dreamOverflowBlock.SetFloat(OverflowGlowId, _dreamOverflowSettings.glow); - _dreamOverflowBlock.SetFloat(OverflowChromaticId, _dreamOverflowSettings.chromatic); - _dreamOverflowBlock.SetFloat(OverflowNoiseId, _dreamOverflowSettings.noise); - target.SetPropertyBlock(_dreamOverflowBlock); - _dreamOverflowBlock.Clear(); + HideLargePresentationImmediate(); + base.OnSingletonDestroy(); } private void CaptureSmallBaseTransform() @@ -213,6 +77,104 @@ namespace AibisDream _smallBaseLocalScale = tr.localScale; } + private void CaptureLargeBaseTransform() + { + if (_largeSpriteRenderer == null) return; + + var tr = _largeSpriteRenderer.transform; + _largeBaseLocalPosition = tr.localPosition; + _largeBaseLocalRotation = tr.localRotation; + _largeBaseLocalScale = tr.localScale; + _largeBaseAlpha = _largeSpriteRenderer.color.a; + } + + public IEnumerator AnimateLargePresentation(float scaleMultiplier, float targetAlpha, float duration) + { + if (_largeSpriteRenderer == null) yield break; + + KillLargePresentationTweens(); + _largeSpriteRenderer.gameObject.SetActive(true); + + scaleMultiplier = Mathf.Max(0.01f, scaleMultiplier); + targetAlpha = Mathf.Clamp01(targetAlpha); + duration = Mathf.Max(0f, duration); + + var targetScale = new Vector3( + _largeBaseLocalScale.x * scaleMultiplier, + _largeBaseLocalScale.y * scaleMultiplier, + _largeBaseLocalScale.z); + + if (duration <= 0f) + { + _largeSpriteRenderer.transform.localPosition = _largeBaseLocalPosition; + _largeSpriteRenderer.transform.localRotation = _largeBaseLocalRotation; + _largeSpriteRenderer.transform.localScale = targetScale; + _largeSpriteRenderer.SetAlpha(targetAlpha); + yield break; + } + + _largePresentationSequence = DOTween.Sequence(); + _largePresentationSequence.Join( + _largeSpriteRenderer.transform.DOScale(targetScale, duration).SetEase(Ease.InOutSine)); + _largePresentationSequence.Join( + _largeSpriteRenderer.transform.DOLocalMove(_largeBaseLocalPosition, duration).SetEase(Ease.InOutSine)); + _largePresentationSequence.Join( + _largeSpriteRenderer.DOFade(targetAlpha, duration).SetEase(Ease.InOutSine)); + + yield return _largePresentationSequence.WaitForCompletion(); + _largePresentationSequence = null; + } + + public void SetLargePresentationImmediate(float scaleMultiplier, float alpha) + { + if (_largeSpriteRenderer == null) return; + + KillLargePresentationTweens(); + scaleMultiplier = Mathf.Max(0.01f, scaleMultiplier); + + _largeSpriteRenderer.transform.localPosition = _largeBaseLocalPosition; + _largeSpriteRenderer.transform.localRotation = _largeBaseLocalRotation; + _largeSpriteRenderer.transform.localScale = new Vector3( + _largeBaseLocalScale.x * scaleMultiplier, + _largeBaseLocalScale.y * scaleMultiplier, + _largeBaseLocalScale.z); + _largeSpriteRenderer.SetAlpha(Mathf.Clamp01(alpha)); + } + + public void StopLargePresentationAnimation() + { + KillLargePresentationTweens(); + } + + public void ResetLargePresentationImmediate() + { + if (_largeSpriteRenderer == null) return; + + KillLargePresentationTweens(); + _largeSpriteRenderer.transform.localPosition = _largeBaseLocalPosition; + _largeSpriteRenderer.transform.localRotation = _largeBaseLocalRotation; + _largeSpriteRenderer.transform.localScale = _largeBaseLocalScale; + _largeSpriteRenderer.SetAlpha(_largeBaseAlpha); + } + + public void HideLargePresentationImmediate() + { + if (_largeSpriteRenderer == null) return; + + ResetLargePresentationImmediate(); + _largeSpriteRenderer.gameObject.SetActive(false); + } + + private void KillLargePresentationTweens() + { + _largePresentationSequence?.Kill(); + _largePresentationSequence = null; + + if (_largeSpriteRenderer == null) return; + DOTween.Kill(_largeSpriteRenderer); + DOTween.Kill(_largeSpriteRenderer.transform); + } + private static string NormalizeDreamPicName(string picName) { if (string.IsNullOrEmpty(picName)) return picName; @@ -242,7 +204,6 @@ namespace AibisDream CopySmallRendererSettings(_smallMotionRenderer, 1, SpriteMaskInteraction.VisibleInsideMask); _smallMotionRenderer.gameObject.SetActive(false); _smallMotionRenderer.SetAlpha(0); - ApplyDreamOverflow(_smallMotionRenderer); } private void CopySmallRendererSettings(SpriteRenderer target, int sortingOrderOffset, SpriteMaskInteraction maskInteraction) @@ -626,11 +587,26 @@ namespace AibisDream if (_largeSpriteRenderer == null) yield break; + ResetLargePresentationImmediate(); _largeSpriteRenderer.gameObject.SetActive(true); + _largeSpriteRenderer.SetAlpha(0f); yield return LoadDreamSpriteInto(_largeSpriteRenderer, picName); - yield return _largeSpriteRenderer.DOFade(1, duration).WaitForCompletion(); + if (duration <= 0f) + { + _largeSpriteRenderer.SetAlpha(1f); + } + else + { + yield return _largeSpriteRenderer.DOFade(1, duration).WaitForCompletion(); + } + } + + public void SetLargeSpriteImmediate(Sprite sprite) + { + if (_largeSpriteRenderer != null && sprite != null) + _largeSpriteRenderer.sprite = sprite; } /// @@ -704,8 +680,18 @@ namespace AibisDream { if (_largeSpriteRenderer == null) yield break; - yield return _largeSpriteRenderer.DOFade(0, duration).WaitForCompletion(); + KillLargePresentationTweens(); + if (duration <= 0f) + { + _largeSpriteRenderer.SetAlpha(0f); + } + else + { + yield return _largeSpriteRenderer.DOFade(0, duration).WaitForCompletion(); + } + _largeSpriteRenderer.gameObject.SetActive(false); + ResetLargePresentationImmediate(); } ///