feat(dream): 完善梦境门与星空聚焦演出
This commit is contained in:
+2
-1
@@ -75,7 +75,8 @@
|
||||
*.psd filter=lfs diff=lfs merge=lfs -text
|
||||
*.psb filter=lfs diff=lfs merge=lfs -text
|
||||
*.bank filter=lfs diff=lfs merge=lfs -text
|
||||
*.mp4 filter=lfs diff=lfs merge=lfs -text
|
||||
|
||||
# DOTween editor images - exclude from LFS (stored as regular binaries, Unity re-import causes false changes)
|
||||
Assets/Plugins/Demigiant/DOTween/Editor/Imgs/*.png -filter -diff -merge
|
||||
Assets/Plugins/Demigiant/DOTween/Editor/Imgs/*.jpg -filter -diff -merge
|
||||
Assets/Plugins/Demigiant/DOTween/Editor/Imgs/*.jpg -filter -diff -merge
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
%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: DreamSeaMemory
|
||||
m_Shader: {fileID: 4800000, guid: a8d86af0aff94e1794fa50e65ac676d5, 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}
|
||||
- _VideoTex:
|
||||
m_Texture: {fileID: 8400000, guid: d873791053c443c1a79eedd22a687780, type: 2}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Ints: []
|
||||
m_Floats:
|
||||
- _Contrast: 1
|
||||
- _DitherStrength: 0.002
|
||||
- _Levels: 10
|
||||
- _UseVideo: 0
|
||||
m_Colors:
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _PixelGrid: {r: 360, g: 640, b: 0, a: 0}
|
||||
m_BuildTextureStacks: []
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e04544198a7d4f88ba592bf1feebbca2
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,40 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!84 &8400000
|
||||
RenderTexture:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: DreamSeaMemory
|
||||
m_ImageContentsHash:
|
||||
serializedVersion: 2
|
||||
Hash: 00000000000000000000000000000000
|
||||
m_ForcedFallbackFormat: 4
|
||||
m_DownscaleFallback: 0
|
||||
m_IsAlphaChannelOptional: 0
|
||||
serializedVersion: 5
|
||||
m_Width: 720
|
||||
m_Height: 1280
|
||||
m_AntiAliasing: 1
|
||||
m_MipCount: -1
|
||||
m_DepthStencilFormat: 0
|
||||
m_ColorFormat: 4
|
||||
m_MipMap: 0
|
||||
m_GenerateMips: 0
|
||||
m_SRGB: 1
|
||||
m_UseDynamicScale: 0
|
||||
m_BindMS: 0
|
||||
m_EnableCompatibleFormat: 1
|
||||
m_EnableRandomWrite: 0
|
||||
m_TextureSettings:
|
||||
serializedVersion: 2
|
||||
m_FilterMode: 1
|
||||
m_Aniso: 0
|
||||
m_MipBias: 0
|
||||
m_WrapU: 1
|
||||
m_WrapV: 1
|
||||
m_WrapW: 1
|
||||
m_Dimension: 2
|
||||
m_VolumeDepth: 1
|
||||
m_ShadowSamplingMode: 2
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d873791053c443c1a79eedd22a687780
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 8400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,120 @@
|
||||
Shader "AibisDream/DreamSeaMemory"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
[PerRendererData] _MainTex ("Poster Texture", 2D) = "white" {}
|
||||
_VideoTex ("Video Texture", 2D) = "black" {}
|
||||
_UseVideo ("Use Prepared Video", Range(0, 1)) = 0
|
||||
_Color ("Tint", Color) = (1,1,1,1)
|
||||
_PixelGrid ("Virtual Pixel Grid", Vector) = (240,426,0,0)
|
||||
_Contrast ("Contrast", Range(0.5, 2)) = 1
|
||||
_Levels ("Luminance Levels", Range(2, 16)) = 10
|
||||
_DitherStrength ("Dither Strength", Range(0, 0.1)) = 0.002
|
||||
}
|
||||
|
||||
SubShader
|
||||
{
|
||||
Tags
|
||||
{
|
||||
"Queue"="Transparent"
|
||||
"IgnoreProjector"="True"
|
||||
"RenderType"="Transparent"
|
||||
"PreviewType"="Plane"
|
||||
"CanUseSpriteAtlas"="True"
|
||||
}
|
||||
|
||||
Cull Off
|
||||
Lighting Off
|
||||
ZWrite Off
|
||||
Blend SrcAlpha OneMinusSrcAlpha
|
||||
|
||||
Pass
|
||||
{
|
||||
CGPROGRAM
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#pragma target 3.0
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
|
||||
struct appdata
|
||||
{
|
||||
float4 vertex : POSITION;
|
||||
float4 color : COLOR;
|
||||
float2 uv : TEXCOORD0;
|
||||
};
|
||||
|
||||
struct v2f
|
||||
{
|
||||
float4 vertex : SV_POSITION;
|
||||
fixed4 color : COLOR;
|
||||
float2 uv : TEXCOORD0;
|
||||
};
|
||||
|
||||
sampler2D _MainTex;
|
||||
sampler2D _VideoTex;
|
||||
fixed4 _Color;
|
||||
float _UseVideo;
|
||||
float4 _PixelGrid;
|
||||
float _Contrast;
|
||||
float _Levels;
|
||||
float _DitherStrength;
|
||||
|
||||
v2f vert(appdata v)
|
||||
{
|
||||
v2f o;
|
||||
o.vertex = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.uv;
|
||||
o.color = v.color * _Color;
|
||||
return o;
|
||||
}
|
||||
|
||||
float Bayer4x4(float2 pixel)
|
||||
{
|
||||
int x = ((int)pixel.x) & 3;
|
||||
int y = ((int)pixel.y) & 3;
|
||||
int index = x + y * 4;
|
||||
|
||||
if (index == 0) return 0.0 / 16.0;
|
||||
if (index == 1) return 8.0 / 16.0;
|
||||
if (index == 2) return 2.0 / 16.0;
|
||||
if (index == 3) return 10.0 / 16.0;
|
||||
if (index == 4) return 12.0 / 16.0;
|
||||
if (index == 5) return 4.0 / 16.0;
|
||||
if (index == 6) return 14.0 / 16.0;
|
||||
if (index == 7) return 6.0 / 16.0;
|
||||
if (index == 8) return 3.0 / 16.0;
|
||||
if (index == 9) return 11.0 / 16.0;
|
||||
if (index == 10) return 1.0 / 16.0;
|
||||
if (index == 11) return 9.0 / 16.0;
|
||||
if (index == 12) return 15.0 / 16.0;
|
||||
if (index == 13) return 7.0 / 16.0;
|
||||
if (index == 14) return 13.0 / 16.0;
|
||||
return 5.0 / 16.0;
|
||||
}
|
||||
|
||||
fixed4 frag(v2f i) : SV_Target
|
||||
{
|
||||
float2 grid = max(_PixelGrid.xy, float2(1.0, 1.0));
|
||||
float2 pixel = floor(i.uv * grid);
|
||||
float2 sampleUv = (pixel + 0.5) / grid;
|
||||
|
||||
fixed4 poster = tex2D(_MainTex, sampleUv);
|
||||
fixed4 video = tex2D(_VideoTex, sampleUv);
|
||||
float3 source = lerp(poster.rgb, video.rgb, saturate(_UseVideo));
|
||||
|
||||
float luminance = dot(source, float3(0.299, 0.587, 0.114));
|
||||
luminance = saturate((luminance - 0.5) * _Contrast + 0.5);
|
||||
luminance = saturate(luminance + (Bayer4x4(pixel) - 0.5) * _DitherStrength);
|
||||
|
||||
float levels = max(2.0, floor(_Levels + 0.5));
|
||||
luminance = floor(luminance * (levels - 1.0) + 0.5) / (levels - 1.0);
|
||||
|
||||
return fixed4(luminance.xxx * i.color.rgb, poster.a * i.color.a);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
Fallback "Sprites/Default"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a8d86af0aff94e1794fa50e65ac676d5
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
@@ -0,0 +1,27 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9ed84eb452114d46b39fa43322d186ec
|
||||
VideoClipImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
frameRange: 0
|
||||
startFrame: -1
|
||||
endFrame: -1
|
||||
colorSpace: 0
|
||||
deinterlace: 0
|
||||
encodeAlpha: 0
|
||||
flipVertical: 0
|
||||
flipHorizontal: 0
|
||||
importAudio: 0
|
||||
targetSettings:
|
||||
0:
|
||||
enableTranscoding: 0
|
||||
codec: 0
|
||||
resizeFormat: 0
|
||||
aspectRatio: 0
|
||||
customWidth: 1
|
||||
customHeight: 1
|
||||
bitrateMode: 2
|
||||
spatialQuality: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
@@ -0,0 +1,114 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0d38a05e2cc64f5bb1958d3bdf78925d
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 12
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 0
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -8,6 +8,7 @@ Shader "AIBIS/KiteFocusSprite"
|
||||
[Header(Focus Blur)]
|
||||
_BlurAmount ("Blur Amount", Range(0, 1)) = 0
|
||||
_BlurSize ("Blur Size", Range(0, 0.05)) = 0.012
|
||||
[HideInInspector] _UseSoftFocus ("Use Soft Focus", Float) = 0
|
||||
_DefocusBloom ("Defocus Highlight Bloom", Range(0, 1)) = 0.32
|
||||
_HaloStrength ("Large Circle Halo", Range(0, 0.6)) = 0.22
|
||||
_ChromaticFringe ("Lens Color Fringe", Range(0, 0.6)) = 0.14
|
||||
@@ -75,6 +76,7 @@ Shader "AIBIS/KiteFocusSprite"
|
||||
fixed4 _Color;
|
||||
float _BlurAmount;
|
||||
float _BlurSize;
|
||||
float _UseSoftFocus;
|
||||
float _DefocusBloom;
|
||||
float _HaloStrength;
|
||||
float _ChromaticFringe;
|
||||
@@ -150,6 +152,33 @@ Shader "AIBIS/KiteFocusSprite"
|
||||
return result * 0.125;
|
||||
}
|
||||
|
||||
half4 SoftFocusBlur(float2 uv, float radius)
|
||||
{
|
||||
float nearRadius = radius * 0.48;
|
||||
half4 result = samplePremultiplied(uv) * 0.20;
|
||||
|
||||
result += samplePremultiplied(uv + float2( nearRadius, 0)) * 0.08;
|
||||
result += samplePremultiplied(uv + float2(-nearRadius, 0)) * 0.08;
|
||||
result += samplePremultiplied(uv + float2(0, nearRadius)) * 0.08;
|
||||
result += samplePremultiplied(uv + float2(0, -nearRadius)) * 0.08;
|
||||
|
||||
result += samplePremultiplied(uv + float2( nearRadius, nearRadius)) * 0.055;
|
||||
result += samplePremultiplied(uv + float2(-nearRadius, nearRadius)) * 0.055;
|
||||
result += samplePremultiplied(uv + float2( nearRadius, -nearRadius)) * 0.055;
|
||||
result += samplePremultiplied(uv + float2(-nearRadius, -nearRadius)) * 0.055;
|
||||
|
||||
result += samplePremultiplied(uv + float2( radius, 0)) * 0.04;
|
||||
result += samplePremultiplied(uv + float2(-radius, 0)) * 0.04;
|
||||
result += samplePremultiplied(uv + float2(0, radius)) * 0.04;
|
||||
result += samplePremultiplied(uv + float2(0, -radius)) * 0.04;
|
||||
|
||||
result += samplePremultiplied(uv + float2( radius, radius)) * 0.025;
|
||||
result += samplePremultiplied(uv + float2(-radius, radius)) * 0.025;
|
||||
result += samplePremultiplied(uv + float2( radius, -radius)) * 0.025;
|
||||
result += samplePremultiplied(uv + float2(-radius, -radius)) * 0.025;
|
||||
return result;
|
||||
}
|
||||
|
||||
fixed4 frag(v2f i) : SV_Target
|
||||
{
|
||||
float blurAmt = saturate(_BlurAmount);
|
||||
@@ -164,6 +193,18 @@ Shader "AIBIS/KiteFocusSprite"
|
||||
|
||||
float2 texel = max(abs(_MainTex_TexelSize.xy), float2(1e-5, 1e-5));
|
||||
float radius = (length(texel) * 0.5 + _BlurSize) * (0.28 + blurAmt * 1.72);
|
||||
|
||||
if (_UseSoftFocus > 0.5)
|
||||
{
|
||||
half4 softBlurred = SoftFocusBlur(i.uv, radius);
|
||||
half4 softSharp = sharp;
|
||||
softSharp.rgb *= softSharp.a;
|
||||
half4 softColor = lerp(softSharp, softBlurred, smoothstep(0.0, 1.0, blurAmt));
|
||||
softColor.rgb *= i.color.rgb * i.color.a;
|
||||
softColor.a *= i.color.a;
|
||||
return softColor;
|
||||
}
|
||||
|
||||
half4 disc = ApertureDisc(i.uv, radius);
|
||||
half4 halo = WideHalo(i.uv, radius * 1.85);
|
||||
half4 blurred = lerp(disc, halo, saturate(_HaloStrength * blurAmt));
|
||||
|
||||
+39
-24
@@ -421,20 +421,20 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
director: {fileID: 132823524}
|
||||
starfieldRenderer: {fileID: 1420961919}
|
||||
initialBlur: 0.78
|
||||
blurSize: 0.009
|
||||
initialBlur: 0.58
|
||||
blurSize: 0.0045
|
||||
firstAttemptStart: 0.45
|
||||
firstFocusDuration: 0.48
|
||||
firstNearFocusBlur: 0.38
|
||||
firstHoldDuration: 0.14
|
||||
firstSlipDuration: 0.38
|
||||
firstSlipBlur: 0.72
|
||||
secondAttemptStart: 1.72
|
||||
secondFocusDuration: 0.55
|
||||
secondNearFocusBlur: 0.28
|
||||
secondHoldDuration: 0.18
|
||||
secondSlipDuration: 0.46
|
||||
unresolvedBlur: 0.62
|
||||
firstFocusDuration: 0.72
|
||||
firstNearFocusBlur: 0.16
|
||||
firstHoldDuration: 0.1
|
||||
firstSlipDuration: 0.42
|
||||
firstSlipBlur: 0.52
|
||||
secondAttemptStart: 1.85
|
||||
secondFocusDuration: 0.82
|
||||
secondNearFocusBlur: 0.08
|
||||
secondHoldDuration: 0.12
|
||||
secondSlipDuration: 0.5
|
||||
unresolvedBlur: 0.44
|
||||
blurFadeStart: 4
|
||||
blurFadeDuration: 3.2
|
||||
--- !u!1 &218986882
|
||||
@@ -663,6 +663,9 @@ MonoBehaviour:
|
||||
frameRenderers:
|
||||
- {fileID: 1847534534}
|
||||
sceneBlackOverlay: {fileID: 1373573734}
|
||||
glassSeaVideoClip: {fileID: 32900000, guid: 9ed84eb452114d46b39fa43322d186ec, type: 3}
|
||||
glassSeaTargetTexture: {fileID: 8400000, guid: d873791053c443c1a79eedd22a687780, type: 2}
|
||||
glassSeaPrepareTimeout: 5
|
||||
terminalUI: {fileID: 1195418928}
|
||||
doorShellTransform: {fileID: 0}
|
||||
terminalShapeReference: {fileID: 1847534534}
|
||||
@@ -1510,15 +1513,27 @@ MonoBehaviour:
|
||||
typewriterCharDelay: 0.025
|
||||
bootSpeedMultiplier: 4
|
||||
bootSequence:
|
||||
- text: '>> SYSTEM: Reality_Engine.sys stopped.'
|
||||
- text: 'root@sys:~$ dream.render --stop --session 0742'
|
||||
style: 3
|
||||
delayAfter: 0.2
|
||||
- text: '>> SYSTEM: Rendering underlying code...'
|
||||
delayAfter: 0.15
|
||||
- text: '[ OK ] Dream renderer stopped.'
|
||||
style: 0
|
||||
delayAfter: 0.25
|
||||
- text: '[ RAW ] Untitled_Greybox_0 exposed.'
|
||||
style: 0
|
||||
delayAfter: 0.35
|
||||
- text: 'root@sys:~$ trace --tail /log/dream_0742.rec'
|
||||
style: 3
|
||||
delayAfter: 0.2
|
||||
- text: '>> LOADING: Ocean_Simulation.sh ... OK'
|
||||
delayAfter: 0.15
|
||||
- text: '[0005] audio.play("sea_ambient", source=door.rear)'
|
||||
style: 3
|
||||
delayAfter: 0.8
|
||||
delayAfter: 0.1
|
||||
- text: '[0006] memory.project("glass_sea")'
|
||||
style: 3
|
||||
delayAfter: 0.1
|
||||
- text: '[ WARN ] memory source unresolved; overflow detected.'
|
||||
style: 1
|
||||
delayAfter: 0.4
|
||||
- text: "root@sys:~$ print_string(\"\u6D77\u662F\u5B58\u5728\u7684\u5417?\")"
|
||||
style: 2
|
||||
delayAfter: 0.5
|
||||
@@ -1791,7 +1806,7 @@ SpriteRenderer:
|
||||
m_RenderingLayerMask: 1
|
||||
m_RendererPriority: 0
|
||||
m_Materials:
|
||||
- {fileID: 2100000, guid: a97c105638bdf8b4a8650670310a4cd3, type: 2}
|
||||
- {fileID: 2100000, guid: 78265ded39f017d45a2afc117effab89, type: 2}
|
||||
m_StaticBatchInfo:
|
||||
firstSubMesh: 0
|
||||
subMeshCount: 0
|
||||
@@ -2602,7 +2617,7 @@ SpriteRenderer:
|
||||
m_RenderingLayerMask: 1
|
||||
m_RendererPriority: 0
|
||||
m_Materials:
|
||||
- {fileID: 1583441590}
|
||||
- {fileID: 2100000, guid: e04544198a7d4f88ba592bf1feebbca2, type: 2}
|
||||
m_StaticBatchInfo:
|
||||
firstSubMesh: 0
|
||||
subMeshCount: 0
|
||||
@@ -2623,7 +2638,7 @@ SpriteRenderer:
|
||||
m_SortingLayerID: 844151739
|
||||
m_SortingLayer: 1
|
||||
m_SortingOrder: 5
|
||||
m_Sprite: {fileID: 21300000, guid: 8e0b68f1e994fc24b80e5a480c61602b, type: 3}
|
||||
m_Sprite: {fileID: 21300000, guid: 0d38a05e2cc64f5bb1958d3bdf78925d, type: 3}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 0}
|
||||
m_FlipX: 0
|
||||
m_FlipY: 0
|
||||
@@ -2643,8 +2658,8 @@ Transform:
|
||||
m_GameObject: {fileID: 1961593256904873106}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: -0.07, y: -0.03, z: 0}
|
||||
m_LocalScale: {x: 0.7074555, y: 0.62522215, z: 0.8706811}
|
||||
m_LocalPosition: {x: 0.02, y: 0.03, z: 0}
|
||||
m_LocalScale: {x: 0.636667, y: 0.615, z: 0.8706811}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 450371655}
|
||||
|
||||
@@ -4,6 +4,7 @@ using AibisDream.UI;
|
||||
using AibisDream.Utility;
|
||||
using DG.Tweening;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Video;
|
||||
|
||||
namespace AibisDream
|
||||
{
|
||||
@@ -22,6 +23,11 @@ namespace AibisDream
|
||||
[SerializeField] private Renderer[] frameRenderers;
|
||||
[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("Terminal(挂在 Door 子节点上即可,无需 Canvas)")]
|
||||
[SerializeField] private DreamTerminalUI terminalUI;
|
||||
|
||||
@@ -56,6 +62,14 @@ 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 DoorPresentationPhase _presentationPhase = DoorPresentationPhase.Hidden;
|
||||
|
||||
private static readonly int UseVideoId = Shader.PropertyToID("_UseVideo");
|
||||
|
||||
private enum FrameHidePhase
|
||||
{
|
||||
@@ -64,6 +78,15 @@ namespace AibisDream
|
||||
OnTerminal
|
||||
}
|
||||
|
||||
private enum DoorPresentationPhase
|
||||
{
|
||||
Hidden,
|
||||
Door,
|
||||
GlassSea,
|
||||
CodeSea,
|
||||
Terminal
|
||||
}
|
||||
|
||||
public override void OnSingletonInit()
|
||||
{
|
||||
if (doorRoot != null)
|
||||
@@ -75,10 +98,14 @@ namespace AibisDream
|
||||
|
||||
if (glassSea != null)
|
||||
{
|
||||
_glassSeaMaterial = glassSea.material;
|
||||
SetGlassSeaVideoVisible(false);
|
||||
glassSea.SetAlpha(0);
|
||||
glassSea.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
InitializeGlassSeaVideo();
|
||||
|
||||
if (codeSea != null)
|
||||
{
|
||||
codeSea.SetAlpha(0);
|
||||
@@ -108,19 +135,33 @@ namespace AibisDream
|
||||
_terminalUiOriginalScale = _terminalUiTransform.localScale;
|
||||
_terminalUiOriginalLocalPosition = _terminalUiTransform.localPosition;
|
||||
}
|
||||
|
||||
_presentationPhase = DoorPresentationPhase.Hidden;
|
||||
}
|
||||
|
||||
public override void OnSingletonDestroy()
|
||||
{
|
||||
if (_glassSeaVideoPlayer != null)
|
||||
{
|
||||
_glassSeaVideoPlayer.prepareCompleted -= OnGlassSeaVideoPrepared;
|
||||
_glassSeaVideoPlayer.frameReady -= OnGlassSeaVideoFrameReady;
|
||||
_glassSeaVideoPlayer.errorReceived -= OnGlassSeaVideoError;
|
||||
}
|
||||
|
||||
base.OnSingletonDestroy();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 显示整个门(仅 background + Frame,GlassSea/CodeSea 保持隐藏直到各自命令调用)
|
||||
/// 显示普通门。该命令是一个完整状态切换,会清掉之前残留的海景、代码海浪和终端。
|
||||
/// </summary>
|
||||
public IEnumerator ShowDoor(float duration = 0f)
|
||||
{
|
||||
if (doorRoot != null)
|
||||
doorRoot.gameObject.SetActive(true);
|
||||
|
||||
SetBackgroundVisible(true);
|
||||
SetFrameVisible(true);
|
||||
ResetDoorShellScale();
|
||||
StopAllEffects();
|
||||
EnsureDoorBaseVisible();
|
||||
ResetGlassSeaImmediate(stopVideo: true);
|
||||
ResetCodeSeaImmediate();
|
||||
ResetTerminalImmediate();
|
||||
_presentationPhase = DoorPresentationPhase.Door;
|
||||
|
||||
if (duration > 0f)
|
||||
yield return new WaitForSeconds(duration);
|
||||
@@ -139,18 +180,48 @@ namespace AibisDream
|
||||
|
||||
public IEnumerator ShowGlassSea(float duration = 2f)
|
||||
{
|
||||
if (glassSea == null)
|
||||
yield break;
|
||||
|
||||
StopAllEffects();
|
||||
EnsureDoorBaseVisible();
|
||||
ResetCodeSeaImmediate();
|
||||
ResetTerminalImmediate();
|
||||
|
||||
if (_presentationPhase != DoorPresentationPhase.GlassSea || !glassSea.gameObject.activeSelf)
|
||||
glassSea.SetAlpha(0f);
|
||||
|
||||
glassSea.gameObject.SetActive(true);
|
||||
yield return glassSea.DOFade(1f, duration)
|
||||
_presentationPhase = DoorPresentationPhase.GlassSea;
|
||||
yield return EnsureGlassSeaVideoPlaying();
|
||||
yield return glassSea.DOFade(1f, Mathf.Max(0f, duration))
|
||||
.SetEase(Ease.InOutSine)
|
||||
.WaitForCompletion();
|
||||
}
|
||||
|
||||
public IEnumerator HideGlassSea(float duration = 1f)
|
||||
{
|
||||
yield return glassSea.DOFade(0f, duration)
|
||||
.SetEase(Ease.InOutSine)
|
||||
.WaitForCompletion();
|
||||
if (glassSea == null)
|
||||
{
|
||||
PauseGlassSeaVideo();
|
||||
yield break;
|
||||
}
|
||||
|
||||
DOTween.Kill(glassSea);
|
||||
|
||||
if (glassSea.gameObject.activeSelf)
|
||||
{
|
||||
yield return glassSea.DOFade(0f, Mathf.Max(0f, duration))
|
||||
.SetEase(Ease.InOutSine)
|
||||
.WaitForCompletion();
|
||||
}
|
||||
|
||||
glassSea.SetAlpha(0f);
|
||||
glassSea.gameObject.SetActive(false);
|
||||
PauseGlassSeaVideo();
|
||||
|
||||
if (_presentationPhase == DoorPresentationPhase.GlassSea)
|
||||
_presentationPhase = DoorPresentationPhase.Door;
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -159,21 +230,39 @@ namespace AibisDream
|
||||
|
||||
public IEnumerator ShowCodeSea(float duration = 2f)
|
||||
{
|
||||
if (codeSea == null)
|
||||
yield break;
|
||||
|
||||
StopAllEffects();
|
||||
EnsureDoorBaseVisible();
|
||||
ResetTerminalImmediate();
|
||||
|
||||
codeSea.color = _codeSeaOriginalColor;
|
||||
if (_codeSeaTransform != null)
|
||||
_codeSeaTransform.localScale = _codeSeaOriginalScale;
|
||||
codeSea.SetAlpha(0f);
|
||||
codeSea.gameObject.SetActive(true);
|
||||
_presentationPhase = DoorPresentationPhase.CodeSea;
|
||||
|
||||
if (frameHidePhase == FrameHidePhase.OnCodeSea)
|
||||
SetFrameVisible(false);
|
||||
|
||||
var seq = DOTween.Sequence();
|
||||
seq.Append(codeSea.DOFade(1f, duration).SetEase(Ease.InOutSine));
|
||||
seq.Append(codeSea.DOFade(1f, Mathf.Max(0f, duration)).SetEase(Ease.InOutSine));
|
||||
if (glassSea != null && glassSea.gameObject.activeSelf)
|
||||
{
|
||||
seq.Join(glassSea.DOFade(0f, duration * 0.7f).SetEase(Ease.InSine));
|
||||
seq.Join(glassSea.DOFade(0f, Mathf.Max(0f, duration) * 0.7f).SetEase(Ease.InSine));
|
||||
}
|
||||
|
||||
yield return seq.WaitForCompletion();
|
||||
|
||||
if (glassSea != null)
|
||||
{
|
||||
glassSea.SetAlpha(0f);
|
||||
glassSea.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
StopGlassSeaVideo();
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -182,6 +271,7 @@ namespace AibisDream
|
||||
|
||||
public IEnumerator ShowTerminal()
|
||||
{
|
||||
_presentationPhase = DoorPresentationPhase.Terminal;
|
||||
yield return AnimateDoorToTerminal();
|
||||
if (terminalUI != null)
|
||||
{
|
||||
@@ -214,6 +304,8 @@ namespace AibisDream
|
||||
if (glassSea != null)
|
||||
glassSea.gameObject.SetActive(false);
|
||||
|
||||
StopGlassSeaVideo();
|
||||
|
||||
if (codeSea != null)
|
||||
codeSea.gameObject.SetActive(false);
|
||||
|
||||
@@ -288,6 +380,7 @@ namespace AibisDream
|
||||
|
||||
public void StopAllEffects()
|
||||
{
|
||||
DOTween.Kill(glassSea);
|
||||
DOTween.Kill(_codeSeaTransform);
|
||||
DOTween.Kill(codeSea);
|
||||
DOTween.Kill(_terminalUiTransform);
|
||||
@@ -314,6 +407,8 @@ namespace AibisDream
|
||||
glassSea.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
StopGlassSeaVideo();
|
||||
|
||||
if (codeSea != null)
|
||||
{
|
||||
codeSea.color = _codeSeaOriginalColor;
|
||||
@@ -340,6 +435,193 @@ namespace AibisDream
|
||||
|
||||
if (sceneBlackOverlay != null)
|
||||
sceneBlackOverlay.SetAlpha(0);
|
||||
|
||||
_presentationPhase = DoorPresentationPhase.Hidden;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Presentation State
|
||||
|
||||
private void EnsureDoorBaseVisible()
|
||||
{
|
||||
if (doorRoot != null)
|
||||
doorRoot.gameObject.SetActive(true);
|
||||
|
||||
SetBackgroundVisible(true);
|
||||
SetFrameVisible(true);
|
||||
ResetDoorShellScale();
|
||||
}
|
||||
|
||||
private void ResetGlassSeaImmediate(bool stopVideo)
|
||||
{
|
||||
DOTween.Kill(glassSea);
|
||||
|
||||
if (glassSea != null)
|
||||
{
|
||||
glassSea.SetAlpha(0f);
|
||||
glassSea.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
if (stopVideo)
|
||||
StopGlassSeaVideo();
|
||||
else
|
||||
PauseGlassSeaVideo();
|
||||
}
|
||||
|
||||
private void ResetCodeSeaImmediate()
|
||||
{
|
||||
DOTween.Kill(_codeSeaTransform);
|
||||
DOTween.Kill(codeSea);
|
||||
|
||||
if (codeSea == null)
|
||||
return;
|
||||
|
||||
codeSea.color = _codeSeaOriginalColor;
|
||||
codeSea.SetAlpha(0f);
|
||||
codeSea.gameObject.SetActive(false);
|
||||
|
||||
if (_codeSeaTransform != null)
|
||||
_codeSeaTransform.localScale = _codeSeaOriginalScale;
|
||||
}
|
||||
|
||||
private void ResetTerminalImmediate()
|
||||
{
|
||||
DOTween.Kill(_terminalUiTransform);
|
||||
|
||||
if (terminalUI != null)
|
||||
{
|
||||
terminalUI.Alpha = 0f;
|
||||
terminalUI.ResetVisualState();
|
||||
}
|
||||
|
||||
if (_terminalUiTransform != null)
|
||||
{
|
||||
_terminalUiTransform.localPosition = _terminalUiOriginalLocalPosition;
|
||||
_terminalUiTransform.localScale = _terminalUiOriginalScale;
|
||||
}
|
||||
|
||||
if (flashOverlay != null)
|
||||
flashOverlay.SetAlpha(0f);
|
||||
|
||||
if (sceneBlackOverlay != null)
|
||||
sceneBlackOverlay.SetAlpha(0f);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GlassSea Video
|
||||
|
||||
private void InitializeGlassSeaVideo()
|
||||
{
|
||||
if (glassSeaVideoClip == null || glassSeaTargetTexture == null)
|
||||
{
|
||||
SetGlassSeaVideoVisible(false);
|
||||
return;
|
||||
}
|
||||
|
||||
_glassSeaVideoPlayer = GetComponent<VideoPlayer>();
|
||||
if (_glassSeaVideoPlayer == null)
|
||||
_glassSeaVideoPlayer = gameObject.AddComponent<VideoPlayer>();
|
||||
|
||||
_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();
|
||||
}
|
||||
|
||||
private IEnumerator EnsureGlassSeaVideoPlaying()
|
||||
{
|
||||
if (_glassSeaVideoPlayer == null || _glassSeaVideoFailed)
|
||||
{
|
||||
SetGlassSeaVideoVisible(false);
|
||||
yield break;
|
||||
}
|
||||
|
||||
if (!_glassSeaVideoPrepared && !_glassSeaVideoPlayer.isPrepared)
|
||||
{
|
||||
float deadline = Time.realtimeSinceStartup + glassSeaPrepareTimeout;
|
||||
while (!_glassSeaVideoPrepared && !_glassSeaVideoFailed && Time.realtimeSinceStartup < deadline)
|
||||
yield return null;
|
||||
|
||||
if (!_glassSeaVideoPrepared && !_glassSeaVideoPlayer.isPrepared)
|
||||
{
|
||||
_glassSeaVideoFailed = true;
|
||||
_glassSeaVideoPlayer.Stop();
|
||||
SetGlassSeaVideoVisible(false);
|
||||
Debug.LogWarning("[DreamDoorSystem] 海景视频准备超时,回退到静态海报。", this);
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
|
||||
_glassSeaVideoPrepared = true;
|
||||
if (!_glassSeaVideoPlayer.isPlaying)
|
||||
_glassSeaVideoPlayer.Play();
|
||||
|
||||
if (!_glassSeaFrameReady)
|
||||
{
|
||||
float firstFrameDeadline = Time.realtimeSinceStartup + 1f;
|
||||
while (!_glassSeaFrameReady && !_glassSeaVideoFailed && Time.realtimeSinceStartup < firstFrameDeadline)
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Playables;
|
||||
using Yarn.Unity;
|
||||
|
||||
namespace AibisDream
|
||||
{
|
||||
@@ -12,6 +14,7 @@ namespace AibisDream
|
||||
{
|
||||
private static readonly int BlurAmountId = Shader.PropertyToID("_BlurAmount");
|
||||
private static readonly int BlurSizeId = Shader.PropertyToID("_BlurSize");
|
||||
private static readonly int UseSoftFocusId = Shader.PropertyToID("_UseSoftFocus");
|
||||
|
||||
[Header("References")]
|
||||
[SerializeField] private PlayableDirector director;
|
||||
@@ -60,6 +63,114 @@ namespace AibisDream
|
||||
|
||||
private MaterialPropertyBlock propertyBlock;
|
||||
|
||||
[YarnCommand("starfield_prepare")]
|
||||
public static void PrepareStarfieldCommand()
|
||||
{
|
||||
var controller = FindFirstObjectByType<StarfieldDefocusController>();
|
||||
if (controller == null)
|
||||
{
|
||||
Debug.LogWarning("[StarfieldDefocusController] No active controller found for starfield_prepare.");
|
||||
return;
|
||||
}
|
||||
|
||||
controller.PrepareStarfield();
|
||||
}
|
||||
|
||||
[YarnCommand("starfield_focus")]
|
||||
public static IEnumerator PlayFocusAttemptCommand(int attempt)
|
||||
{
|
||||
var controller = FindFirstObjectByType<StarfieldDefocusController>();
|
||||
if (controller == null)
|
||||
{
|
||||
Debug.LogWarning("[StarfieldDefocusController] No active controller found for starfield_focus.");
|
||||
yield break;
|
||||
}
|
||||
|
||||
yield return controller.PlayFocusAttempt(attempt);
|
||||
}
|
||||
|
||||
[YarnCommand("starfield_descend")]
|
||||
public static IEnumerator DescendToSeaCommand()
|
||||
{
|
||||
var controller = FindFirstObjectByType<StarfieldDefocusController>();
|
||||
if (controller == null)
|
||||
{
|
||||
Debug.LogWarning("[StarfieldDefocusController] No active controller found for starfield_descend.");
|
||||
yield break;
|
||||
}
|
||||
|
||||
yield return controller.DescendToSea();
|
||||
}
|
||||
|
||||
private void PrepareStarfield()
|
||||
{
|
||||
if (!TryValidateReferences())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
director.Stop();
|
||||
SetTimelineTime(0f);
|
||||
}
|
||||
|
||||
private IEnumerator PlayFocusAttempt(int attempt)
|
||||
{
|
||||
if (!TryValidateReferences())
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
float startTime;
|
||||
float endTime;
|
||||
switch (attempt)
|
||||
{
|
||||
case 1:
|
||||
startTime = firstAttemptStart;
|
||||
endTime = firstAttemptStart + firstFocusDuration + firstHoldDuration + firstSlipDuration;
|
||||
break;
|
||||
case 2:
|
||||
startTime = secondAttemptStart;
|
||||
endTime = secondAttemptStart + secondFocusDuration + secondHoldDuration + secondSlipDuration;
|
||||
break;
|
||||
default:
|
||||
Debug.LogWarning($"[StarfieldDefocusController] Unsupported focus attempt '{attempt}'. Expected 1 or 2.", this);
|
||||
yield break;
|
||||
}
|
||||
|
||||
director.Pause();
|
||||
SetTimelineTime(startTime);
|
||||
|
||||
float duration = Mathf.Max(0.01f, endTime - startTime);
|
||||
float elapsed = 0f;
|
||||
while (elapsed < duration)
|
||||
{
|
||||
elapsed += Time.deltaTime;
|
||||
SetTimelineTime(Mathf.Lerp(startTime, endTime, Mathf.Clamp01(elapsed / duration)));
|
||||
yield return null;
|
||||
}
|
||||
|
||||
SetTimelineTime(endTime);
|
||||
}
|
||||
|
||||
private IEnumerator DescendToSea()
|
||||
{
|
||||
if (!TryValidateReferences())
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
director.Pause();
|
||||
SetTimelineTime(blurFadeStart);
|
||||
director.Play();
|
||||
|
||||
while (director.state == PlayState.Playing)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
|
||||
ApplyAtTime((float)director.time);
|
||||
}
|
||||
|
||||
private void Reset()
|
||||
{
|
||||
director = GetComponent<PlayableDirector>();
|
||||
@@ -87,6 +198,45 @@ namespace AibisDream
|
||||
ApplyAtTime((float)director.time);
|
||||
}
|
||||
|
||||
private bool TryValidateReferences()
|
||||
{
|
||||
if (director == null)
|
||||
{
|
||||
Debug.LogWarning("[StarfieldDefocusController] PlayableDirector is not assigned.", this);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (director.playableAsset == null)
|
||||
{
|
||||
Debug.LogWarning("[StarfieldDefocusController] PlayableDirector has no Timeline asset.", this);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (starfieldRenderer == null)
|
||||
{
|
||||
Debug.LogWarning("[StarfieldDefocusController] Starfield SpriteRenderer is not assigned.", this);
|
||||
return false;
|
||||
}
|
||||
|
||||
var material = starfieldRenderer.sharedMaterial;
|
||||
if (material == null || !material.HasProperty(BlurAmountId) || !material.HasProperty(BlurSizeId))
|
||||
{
|
||||
Debug.LogWarning(
|
||||
"[StarfieldDefocusController] Starfield material must support _BlurAmount and _BlurSize.",
|
||||
starfieldRenderer);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void SetTimelineTime(float time)
|
||||
{
|
||||
director.time = Mathf.Clamp(time, 0f, (float)director.duration);
|
||||
director.Evaluate();
|
||||
ApplyAtTime((float)director.time);
|
||||
}
|
||||
|
||||
private void ApplyAtTime(float time)
|
||||
{
|
||||
if (starfieldRenderer == null)
|
||||
@@ -98,6 +248,7 @@ namespace AibisDream
|
||||
starfieldRenderer.GetPropertyBlock(propertyBlock);
|
||||
propertyBlock.SetFloat(BlurAmountId, EvaluateBlur(time));
|
||||
propertyBlock.SetFloat(BlurSizeId, blurSize);
|
||||
propertyBlock.SetFloat(UseSoftFocusId, 1f);
|
||||
starfieldRenderer.SetPropertyBlock(propertyBlock);
|
||||
}
|
||||
|
||||
@@ -118,7 +269,10 @@ namespace AibisDream
|
||||
|
||||
if (time < firstFocusEnd)
|
||||
{
|
||||
return SmoothLerp(initialBlur, firstNearFocusBlur, InverseLerp(firstAttemptStart, firstFocusEnd, time));
|
||||
return EvaluateFocusTurn(
|
||||
initialBlur,
|
||||
firstNearFocusBlur,
|
||||
InverseLerp(firstAttemptStart, firstFocusEnd, time));
|
||||
}
|
||||
|
||||
if (time < firstHoldEnd)
|
||||
@@ -138,7 +292,10 @@ namespace AibisDream
|
||||
|
||||
if (time < secondFocusEnd)
|
||||
{
|
||||
return SmoothLerp(firstSlipBlur, secondNearFocusBlur, InverseLerp(secondAttemptStart, secondFocusEnd, time));
|
||||
return EvaluateFocusTurn(
|
||||
firstSlipBlur,
|
||||
secondNearFocusBlur,
|
||||
InverseLerp(secondAttemptStart, secondFocusEnd, time));
|
||||
}
|
||||
|
||||
if (time < secondHoldEnd)
|
||||
@@ -159,6 +316,29 @@ namespace AibisDream
|
||||
return SmoothLerp(unresolvedBlur, 0f, InverseLerp(blurFadeStart, blurFadeStart + blurFadeDuration, time));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simulates turning a focus ring toward focus, passing the focal plane,
|
||||
/// then reversing back. The following slip phase still lets the image
|
||||
/// drift out of focus, keeping both attempts deliberately unsuccessful.
|
||||
/// </summary>
|
||||
private static float EvaluateFocusTurn(float fromBlur, float nearFocusBlur, float t)
|
||||
{
|
||||
t = Mathf.Clamp01(t);
|
||||
float overshootBlur = Mathf.Lerp(nearFocusBlur, fromBlur, 0.68f);
|
||||
|
||||
if (t < 0.44f)
|
||||
{
|
||||
return SmoothLerp(fromBlur, nearFocusBlur, t / 0.44f);
|
||||
}
|
||||
|
||||
if (t < 0.72f)
|
||||
{
|
||||
return SmoothLerp(nearFocusBlur, overshootBlur, (t - 0.44f) / 0.28f);
|
||||
}
|
||||
|
||||
return SmoothLerp(overshootBlur, nearFocusBlur, (t - 0.72f) / 0.28f);
|
||||
}
|
||||
|
||||
private static float InverseLerp(float from, float to, float value)
|
||||
{
|
||||
return Mathf.Clamp01((value - from) / Mathf.Max(0.0001f, to - from));
|
||||
|
||||
@@ -98,14 +98,14 @@ namespace AibisDream.UI
|
||||
[Header("启动日志")]
|
||||
[SerializeField] private List<BootLogEntry> bootSequence = new()
|
||||
{
|
||||
new BootLogEntry { text = "root@sys:~$ ./boot --test", style = LogStyle.Dim, delayAfter = 0.2f },
|
||||
new BootLogEntry { text = "[ OK ] Test passed.", style = LogStyle.Normal, delayAfter = 0.2f },
|
||||
new BootLogEntry { text = "root@sys:~$ render --target ocean && aplay sea.wav", style = LogStyle.Dim, delayAfter = 0.2f },
|
||||
new BootLogEntry { text = "[ OK ] Ocean rendered. Audio stream started.", style = LogStyle.Normal, delayAfter = 0.2f },
|
||||
new BootLogEntry { text = "root@sys:~$ render --stop", style = LogStyle.Dim, delayAfter = 0.2f },
|
||||
new BootLogEntry { text = "[ OK ] Render pipeline closed.", style = LogStyle.Normal, delayAfter = 0.2f },
|
||||
new BootLogEntry { text = "root@sys:~$ showcode", style = LogStyle.Alert, delayAfter = 0.2f },
|
||||
new BootLogEntry { text = "root@sys:~$ print_string(\"海是存在的吗?\")", style = LogStyle.Highlight, delayAfter = 0.2f },
|
||||
new BootLogEntry { text = "root@sys:~$ dream.render --stop --session 0742", style = LogStyle.Dim, delayAfter = 0.15f },
|
||||
new BootLogEntry { text = "[ OK ] Dream renderer stopped.", style = LogStyle.Normal, delayAfter = 0.25f },
|
||||
new BootLogEntry { text = "[ RAW ] Untitled_Greybox_0 exposed.", style = LogStyle.Normal, delayAfter = 0.35f },
|
||||
new BootLogEntry { text = "root@sys:~$ trace --tail /log/dream_0742.rec", style = LogStyle.Dim, delayAfter = 0.15f },
|
||||
new BootLogEntry { text = "[0005] audio.play(\"sea_ambient\", source=door.rear)", style = LogStyle.Dim, delayAfter = 0.1f },
|
||||
new BootLogEntry { text = "[0006] memory.project(\"glass_sea\")", style = LogStyle.Dim, delayAfter = 0.1f },
|
||||
new BootLogEntry { text = "[ WARN ] memory source unresolved; overflow detected.", style = LogStyle.Alert, delayAfter = 0.4f },
|
||||
new BootLogEntry { text = "root@sys:~$ print_string(\"海是存在的吗?\")", style = LogStyle.Highlight, delayAfter = 0.5f },
|
||||
};
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -345,7 +345,7 @@ title: 女孩_已完成
|
||||
position: 743,-1403
|
||||
tags: detour
|
||||
---
|
||||
//girl: <i>女孩一边哼歌一边继续涂画着,<br>没有听到你的声音。</i> #line:01ef1ed
|
||||
girl: <i>女孩一边哼歌一边继续涂画着,<br>没有听到你的声音。</i> #line:01ef1ed
|
||||
===
|
||||
|
||||
title: 天台
|
||||
@@ -606,17 +606,17 @@ tags: linear
|
||||
<<play_sfx "event:/Scriptal/sea_loop">>
|
||||
<<set_global_param prologueDreamStage 1>>
|
||||
|
||||
【星空是模糊的,很难看清】
|
||||
<<starfield_prepare>>
|
||||
|
||||
girl: 怎么还是看不清?
|
||||
|
||||
【调试镜头】
|
||||
<<starfield_focus 1>>
|
||||
|
||||
jj: 这都漏雨了。它太旧了,应该很难修好了。
|
||||
|
||||
girl: 不好!肯定是还有什么地方没弄好…
|
||||
|
||||
【调试镜头】
|
||||
<<starfield_focus 2>>
|
||||
|
||||
jj: 走吧,我们在这里也玩够了。
|
||||
|
||||
@@ -634,10 +634,9 @@ girl: 你刚才还不是这么说的。
|
||||
|
||||
me: 姐姐……
|
||||
|
||||
【镜头变得模糊,下摇】
|
||||
<<starfield_descend>>
|
||||
|
||||
<<play_sfx "event:/Scriptal/sea_loop">>
|
||||
<<play_timeline 星空到海浪>>
|
||||
<<set_global_param dream1Stage 5>>
|
||||
<<wait 2>>
|
||||
|
||||
|
||||
@@ -822,6 +822,7 @@ position: -4,927
|
||||
<<if $gameStage==5>>
|
||||
<<show_large_sprite "全景门乌鸦">>
|
||||
<<else>>
|
||||
<<hide_dream_door>>
|
||||
<<show_large_sprite "D2S门">>
|
||||
<<endif>>
|
||||
一扇紧闭的手术室门。让人感觉很熟悉。 #line:0ba4b43
|
||||
@@ -886,6 +887,8 @@ position: -4,927
|
||||
<<show_door_glass_sea 2>>
|
||||
<<endif>>
|
||||
一种莫名的亲切感。 #line:0dfe59e
|
||||
<<hide_door_glass_sea 0.5>>
|
||||
<<hide_dream_door>>
|
||||
->靠近黑暗<<if $gameStage==5>> #line:02cb5f1
|
||||
// 黑暗中闪烁着无数微弱的绿色光点。那是无数段代码。 #line:0dc92eb
|
||||
// 其中一段正静静地漂浮在你的面前。 #line:07400da
|
||||
@@ -981,6 +984,7 @@ me: 海… #line:00a7bf5
|
||||
<<fade_in 0.5>>
|
||||
<<show_large_sprite "门框特写">>
|
||||
<<show_door 0.1>>
|
||||
<<show_door_glass_sea 0>>
|
||||
<<fade_out 0.5>>
|
||||
<<wait 1>>
|
||||
<<show_door_code_sea 2>>
|
||||
|
||||
Reference in New Issue
Block a user