跑通一个版本

This commit is contained in:
2026-03-06 18:09:15 +08:00
parent 0275ecea18
commit 3fdca23cd3
15 changed files with 4648 additions and 3051 deletions
File diff suppressed because it is too large Load Diff
@@ -3341,6 +3341,14 @@ MonoBehaviour:
m_Localized: "\u5B83\u62AC\u8D77\u624B\uFF0C\u76D6\u4E0B\u4E86\u5370\u7AE0\u3002"
m_Metadata:
m_Items: []
- m_Id: 18838449003069440
m_Localized: "\u9ED1\u6697\u4E2D\u95EA\u70C1\u7740\u65E0\u6570\u5FAE\u5F31\u7684\u7EFF\u8272\u5149\u70B9\u3002\u90A3\u662F\u65E0\u6570\u6BB5\u4EE3\u7801\u3002"
m_Metadata:
m_Items: []
- m_Id: 18838449045012480
m_Localized: "\u5176\u4E2D\u4E00\u6BB5\u6B63\u9759\u9759\u5730\u6F02\u6D6E\u5728\u4F60\u7684\u9762\u524D\u3002"
m_Metadata:
m_Items: []
references:
version: 2
RefIds: []
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 559c26ebe66467c419a37ade105a84f1
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.
@@ -0,0 +1,153 @@
fileFormatVersion: 2
guid: 1b578f08ade58004eadbd22363f79662
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: 1
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: WebGL
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
- serializedVersion: 3
buildTarget: Android
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: Server
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:
@@ -458,6 +458,7 @@ position: 0,580
title: 门
position: 0,740
---
<<show_door>>
一扇门突兀地伫立在纯白空间中。白色的碎屑正从门缝中涌出,飘散在整个空间中。 #line:0aedfb4
一种强烈的感觉告诉你,你见过这扇门很多次,你知道门后面是哪里。 #line:0edf9aa
<<if $consciousness==0>>
@@ -510,13 +511,13 @@ position: 0,740
<<if $doorListen==false>>
你好像回忆起了什么。 #line:066b60f
<<set $dooListen=true>>
<<show_door_glass_sea 2>>
<<set $consciousness=$consciousness+1>>
<<endif>>
你对这种声音感到很熟悉。 #line:0585cfe
->靠近黑暗<<if $gameStage==5>> #line:0ad2d5f
// 黑暗中闪烁着无数微弱的绿色光点。那是无数段代码。 #line:0dc92eb
// 其中一段正静静地漂浮在你的面前。 #line:07400da
//命令行终端输入,玩家自由输入字符串,提交后跳转到苏醒节点
<<hide_dialog>>
<<show_dream_terminal>>
->后退 #line:0d563fe
@@ -592,9 +593,9 @@ me: 海… #line:0619044
//me: 它们? #line:00f56e5
乌鸦飞到了门把手上,在上面啄了几下,然后看向了你。 #line:023d173
乌鸦: 眨眨眼睛。场景只能在她停止观察的时候发生变化。 #line:014c7e2
<<show_sprite "D2S门2">>
// <<show_sprite "D2S门2">>
<<show_door_code_sea 2>>
(眨眼之间,场景发生了变化。门变成了一个黑漆漆的矩形。乌鸦扑腾着飞了起来,站在矩形的上面。) #line:0724abb
乌鸦: 这就是Validation_Gate_03真实的样子。 #line:0f245fb
乌鸦: 我也可以把Untitled_Geybox_0真实样子给她看。不过她不会喜欢的。 #line:063c34f
你靠近矩形仔细观察。矩形的正中央是一段代码。光标正在右侧闪动。 #line:00522fc
+1 -1
View File
@@ -12434,7 +12434,7 @@ MonoBehaviour:
m_EditorClassIdentifier:
runMode: 1
firstTalkSo: {fileID: 11400000, guid: 8ce86974047bb404c9096e70a606355a, type: 2}
testTalkSo: {fileID: 11400000, guid: 8ce86974047bb404c9096e70a606355a, type: 2}
testTalkSo: {fileID: 11400000, guid: aaef579ad8bdda542b503b40ce6773a8, type: 2}
saveFileName: "20250901_204445_PeipeiDay1_\u8BB0\u5FC6\u68C0\u67E5"
--- !u!1 &719273460
GameObject:
+352 -111
View File
@@ -123,6 +123,90 @@ NavMeshSettings:
debug:
m_Flags: 0
m_NavMeshData: {fileID: 0}
--- !u!1 &8430223
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8430224}
- component: {fileID: 8430225}
m_Layer: 0
m_Name: background
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &8430224
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8430223}
serializedVersion: 2
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 0.7987307, y: 0.7987307, z: 0.7987307}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 450371655}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!212 &8430225
SpriteRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8430223}
m_Enabled: 1
m_CastShadows: 0
m_ReceiveShadows: 0
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 0
m_RayTraceProcedural: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: a97c105638bdf8b4a8650670310a4cd3, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 0
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 844151739
m_SortingLayer: 1
m_SortingOrder: 5
m_Sprite: {fileID: 21300000, guid: 65581c14d5b5dad4e991ee88882656de, type: 3}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_FlipX: 0
m_FlipY: 0
m_DrawMode: 0
m_Size: {x: 1, y: 1}
m_AdaptiveModeThreshold: 0.5
m_SpriteTileMode: 0
m_WasSpriteAssigned: 1
m_MaskInteraction: 0
m_SpriteSortPoint: 0
--- !u!1 &132823522
GameObject:
m_ObjectHideFlags: 0
@@ -306,6 +390,7 @@ GameObject:
serializedVersion: 6
m_Component:
- component: {fileID: 383939068}
- component: {fileID: 383939069}
m_Layer: 0
m_Name: Door
m_TagString: Untagged
@@ -313,24 +398,86 @@ GameObject:
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &383939068
Transform:
--- !u!224 &383939068
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 383939067}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0.1, y: -0.33, z: 0}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1.2519865, y: 1.2519865, z: 1.2519865}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 450371655}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 100, y: 100}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &383939069
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 383939067}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5da7fe5bad47f764bb5ce8a12e59ec2c, type: 3}
m_Name:
m_EditorClassIdentifier:
doorRoot: {fileID: 450371655}
glassSea: {fileID: 444731254618205655}
codeSea: {fileID: 6341161960392504824}
flashOverlay: {fileID: 1373573734}
terminalUI: {fileID: 1195418928}
seaCollapseScale: {x: 0.9, y: 0.84, z: 1}
morphEase: 10
--- !u!1 &450371654
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 450371655}
m_Layer: 0
m_Name: Doorvisual
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &450371655
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 450371654}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 8430224}
- {fileID: 1373573735}
- {fileID: 1847534533}
- {fileID: 871445756458438719}
- {fileID: 1798110989954288715}
m_Father: {fileID: 861686055}
- {fileID: 1195418929}
m_Father: {fileID: 383939068}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 100, y: 100}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!1 &676277670
GameObject:
m_ObjectHideFlags: 0
@@ -397,7 +544,7 @@ GameObject:
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
m_IsActive: 0
--- !u!81 &754616037
AudioListener:
m_ObjectHideFlags: 0
@@ -546,8 +693,6 @@ Transform:
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 1665718542}
- {fileID: 383939068}
- {fileID: 132823523}
- {fileID: 1424643109}
- {fileID: 969796817}
@@ -720,6 +865,185 @@ Transform:
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1195418927
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1195418929}
- component: {fileID: 1195418928}
m_Layer: 0
m_Name: terminal
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &1195418928
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1195418927}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: df85ec8ec1f91ba4a94b313b13053046, type: 3}
m_Name:
m_EditorClassIdentifier:
useCullingMasks: 0
terminalSize: {x: 5, y: 3.5}
morphStartSize: {x: 8.6, y: 5.6}
colAmberMain: {r: 1, g: 0.69, b: 0, a: 1}
colAmberDim: {r: 0.72, g: 0.52, b: 0.04, a: 1}
colWhiteGlow: {r: 1, g: 1, b: 1, a: 1}
colBg: {r: 0.02, g: 0.02, b: 0.02, a: 0.96}
borderThickness: 0.04
padding: 0.22
lineHeight: 0.22
fontSize: 1.35
inputAreaHeight: 0.42
maxVisibleLines: 12
scanlineSpacing: 0.055
scanlineAlpha: 0.12
cursorBlinkRate: 0.5
cursorSize: {x: 0.1, y: 0.18}
morphProgress: 1
previewInEditor: 1
previewAlpha: 1
previewMorphProgress: 1
previewStage: 3
animatePreviewCursor: 1
previewInputBuffer: false
previewLines: ">> WARNING: TRAP DETECTED.\n>> SYSTEM: Reality_Engine.sys stopped.\n>>
SYSTEM: Rendering underlying code...\n>> LOADING: Ocean_Simulation.sh ... OK\nroot@sys:~$
print_string(\"\u6D77\u662F\u5B58\u5728\u7684\u5417?\")"
previewTypingLine:
maxInputLength: 20
promptString: '> bit seaExists = '
onCompleteNode: "\u82CF\u9192"
bootSequence:
- text: '>> WARNING: TRAP DETECTED.'
style: 1
delayAfter: 0.5
- text: '>> SYSTEM: Reality_Engine.sys stopped.'
style: 3
delayAfter: 0.2
- text: '>> SYSTEM: Rendering underlying code...'
style: 3
delayAfter: 0.2
- text: '>> LOADING: Ocean_Simulation.sh ... OK'
style: 3
delayAfter: 0.8
- text: "root@sys:~$ print_string(\"\u6D77\u662F\u5B58\u5728\u7684\u5417?\")"
style: 2
delayAfter: 0.5
--- !u!224 &1195418929
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1195418927}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 450371655}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 100, y: 100}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!1 &1373573733
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1373573735}
- component: {fileID: 1373573734}
m_Layer: 0
m_Name: flash
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!212 &1373573734
SpriteRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1373573733}
m_Enabled: 1
m_CastShadows: 0
m_ReceiveShadows: 0
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 0
m_RayTraceProcedural: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: a97c105638bdf8b4a8650670310a4cd3, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 0
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 844151739
m_SortingLayer: 1
m_SortingOrder: 20
m_Sprite: {fileID: 21300000, guid: 65581c14d5b5dad4e991ee88882656de, type: 3}
m_Color: {r: 1, g: 1, b: 1, a: 0}
m_FlipX: 0
m_FlipY: 0
m_DrawMode: 0
m_Size: {x: 1, y: 1}
m_AdaptiveModeThreshold: 0.5
m_SpriteTileMode: 0
m_WasSpriteAssigned: 1
m_MaskInteraction: 0
m_SpriteSortPoint: 0
--- !u!4 &1373573735
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1373573733}
serializedVersion: 2
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 0.7987307, y: 0.7987307, z: 0.7987307}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 450371655}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1420961917
GameObject:
m_ObjectHideFlags: 0
@@ -1107,104 +1431,20 @@ Material:
m_Ints: []
m_Floats:
- PixelSnap: 0
- _BlurRadius: 6.1
- _BlurSamples: 16
- _Brightness: 1
- _BlurRadius: 0
- _BlurSamples: 32
- _Brightness: 1.24
- _EnableExternalAlpha: 0
- _FrostIntensity: 0.005
- _FrostScale: 100
- _Saturation: 0.85
- _TintStrength: 0.15
- _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 &1665718541
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1665718542}
- component: {fileID: 1665718543}
m_Layer: 0
m_Name: Square
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &1665718542
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1665718541}
serializedVersion: 2
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 861686055}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!212 &1665718543
SpriteRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1665718541}
m_Enabled: 1
m_CastShadows: 0
m_ReceiveShadows: 0
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 0
m_RayTraceProcedural: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: a97c105638bdf8b4a8650670310a4cd3, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 0
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 844151739
m_SortingLayer: 1
m_SortingOrder: 4
m_Sprite: {fileID: 21300000, guid: 65581c14d5b5dad4e991ee88882656de, type: 3}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_FlipX: 0
m_FlipY: 0
m_DrawMode: 0
m_Size: {x: 1, y: 1}
m_AdaptiveModeThreshold: 0.5
m_SpriteTileMode: 0
m_WasSpriteAssigned: 1
m_MaskInteraction: 0
m_SpriteSortPoint: 0
--- !u!1 &1784701441
GameObject:
m_ObjectHideFlags: 0
@@ -1277,11 +1517,11 @@ Transform:
m_GameObject: {fileID: 1847534532}
serializedVersion: 2
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: -0.56, y: 0.78, z: 0}
m_LocalScale: {x: 1.2659231, y: 1.2659231, z: 1.2659231}
m_LocalPosition: {x: -0.09, y: 0.32, z: 0}
m_LocalScale: {x: 0.72805655, y: 0.72805655, z: 0.72805655}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 383939068}
m_Father: {fileID: 450371655}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!212 &1847534534
SpriteRenderer:
@@ -1324,7 +1564,7 @@ SpriteRenderer:
m_SortingLayerID: 844151739
m_SortingLayer: 1
m_SortingOrder: 9
m_Sprite: {fileID: 21300000, guid: cae13c4075c3f5943acd79c393d7dc93, type: 3}
m_Sprite: {fileID: 21300000, guid: 1b578f08ade58004eadbd22363f79662, type: 3}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_FlipX: 0
m_FlipY: 0
@@ -1396,11 +1636,11 @@ Transform:
m_GameObject: {fileID: 1961593256904873106}
serializedVersion: 2
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0.36, z: 0}
m_LocalScale: {x: 0.5816116, y: 0.6470429, z: 0.96935266}
m_LocalPosition: {x: -0.07, y: 0.24, z: 0}
m_LocalScale: {x: 0.48998493, y: 0.54510826, z: 0.8065596}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 383939068}
m_Father: {fileID: 450371655}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!4 &1798110989954288715
Transform:
@@ -1411,11 +1651,11 @@ Transform:
m_GameObject: {fileID: 5724422998448711206}
serializedVersion: 2
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: -0.73, y: 0.42, z: 0}
m_LocalScale: {x: 6.4114747, y: 9.576583, z: 0.76267165}
m_LocalPosition: {x: -0.08, y: 0.28, z: 0}
m_LocalScale: {x: 3.6999986, y: 7.331499, z: 0.4458426}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 383939068}
m_Father: {fileID: 450371655}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1961593256904873106
GameObject:
@@ -1445,7 +1685,7 @@ GameObject:
- component: {fileID: 1798110989954288715}
- component: {fileID: 6341161960392504824}
m_Layer: 0
m_Name: Door_CodeSea
m_Name: DoorCodeSea
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
@@ -1512,3 +1752,4 @@ SceneRoots:
- {fileID: 1784701442}
- {fileID: 861686055}
- {fileID: 1116970090}
- {fileID: 383939068}
@@ -0,0 +1,316 @@
using System.Collections;
using AibisDream.Kit;
using AibisDream.UI;
using AibisDream.Utility;
using DG.Tweening;
using UnityEngine;
namespace AibisDream
{
public class DreamDoorSystem : Singleton<DreamDoorSystem>
{
[Header("Door Root")]
[Tooltip("Door 根节点。默认仅 background 和 Frame 显示,整个 Door 初始隐藏。show_door 命令激活后显示。")]
[SerializeField] private Transform doorRoot;
[Header("Door Sprites")]
[SerializeField] private SpriteRenderer glassSea;
[SerializeField] private SpriteRenderer codeSea;
[SerializeField] private SpriteRenderer flashOverlay;
[Header("Terminal(挂在 Door 子节点上即可,无需 Canvas")]
[SerializeField] private DreamTerminalUI terminalUI;
[Header("Morph Settings")]
[SerializeField] private Vector3 seaCollapseScale = new(0.9f, 0.84f, 1f);
[SerializeField] private Ease morphEase = Ease.InOutCubic;
private Transform _codeSeaTransform;
private Vector3 _codeSeaOriginalScale;
private Color _codeSeaOriginalColor;
private Transform _terminalUiTransform;
private Vector3 _terminalUiOriginalScale;
public override void OnSingletonInit()
{
if (doorRoot != null)
doorRoot.gameObject.SetActive(false);
if (glassSea != null)
{
glassSea.SetAlpha(0);
glassSea.gameObject.SetActive(false);
}
if (codeSea != null)
{
codeSea.SetAlpha(0);
codeSea.gameObject.SetActive(false);
_codeSeaTransform = codeSea.transform;
_codeSeaOriginalScale = _codeSeaTransform.localScale;
_codeSeaOriginalColor = codeSea.color;
}
if (flashOverlay != null)
{
flashOverlay.SetAlpha(0);
flashOverlay.gameObject.SetActive(true);
}
if (terminalUI != null)
{
terminalUI.ResetVisualState();
terminalUI.Alpha = 0f;
_terminalUiTransform = terminalUI.transform;
_terminalUiOriginalScale = _terminalUiTransform.localScale;
}
}
/// <summary>
/// 显示整个门(仅 background + FrameGlassSea/CodeSea 保持隐藏直到各自命令调用)
/// </summary>
public IEnumerator ShowDoor(float duration = 0f)
{
if (doorRoot != null)
doorRoot.gameObject.SetActive(true);
if (duration > 0f)
yield return new WaitForSeconds(duration);
}
/// <summary>
/// 隐藏整个门
/// </summary>
public void HideDoor()
{
if (doorRoot != null)
doorRoot.gameObject.SetActive(false);
}
#region Phase 1: GlassSea
public IEnumerator ShowGlassSea(float duration = 2f)
{
glassSea.gameObject.SetActive(true);
yield return glassSea.DOFade(1f, duration)
.SetEase(Ease.InOutSine)
.WaitForCompletion();
}
public IEnumerator HideGlassSea(float duration = 1f)
{
yield return glassSea.DOFade(0f, duration)
.SetEase(Ease.InOutSine)
.WaitForCompletion();
glassSea.gameObject.SetActive(false);
}
#endregion
#region Phase 2: CodeSea (GlassSea )
public IEnumerator ShowCodeSea(float duration = 2f)
{
codeSea.gameObject.SetActive(true);
var seq = DOTween.Sequence();
seq.Append(codeSea.DOFade(1f, duration).SetEase(Ease.InOutSine));
if (glassSea != null && glassSea.gameObject.activeSelf)
{
seq.Join(glassSea.DOFade(0f, duration * 0.7f).SetEase(Ease.InSine));
}
yield return seq.WaitForCompletion();
if (glassSea != null)
glassSea.gameObject.SetActive(false);
}
#endregion
#region Phase 3: CodeSea
public IEnumerator ShowTerminal()
{
yield return AnimateDoorToTerminal();
if (terminalUI != null)
terminalUI.Begin();
}
private IEnumerator AnimateDoorToTerminal()
{
if (terminalUI != null)
{
terminalUI.ResetVisualState();
terminalUI.Alpha = 0f;
terminalUI.MorphProgress = 0f;
}
if (_terminalUiTransform != null)
_terminalUiTransform.localScale = Vector3.Scale(_terminalUiOriginalScale, new Vector3(1.04f, 1.04f, 1f));
var seq = DOTween.Sequence();
// Step 1: 短暂闪白(CRT 切换感)
if (flashOverlay != null)
{
seq.Append(flashOverlay.DOFade(0.8f, 0.05f));
seq.Append(flashOverlay.DOFade(0f, 0.12f));
}
// Step 2: 海浪内容退场,终端框架在门内成型
if (codeSea != null)
{
codeSea.gameObject.SetActive(true);
seq.Append(codeSea.DOColor(new Color(0.04f, 0.04f, 0.04f, 1f), 0.3f)
.SetEase(Ease.OutSine));
seq.Join(codeSea.DOFade(0f, 0.78f).SetEase(Ease.InSine));
}
if (_codeSeaTransform != null)
{
seq.Join(_codeSeaTransform.DOScale(Vector3.Scale(_codeSeaOriginalScale, seaCollapseScale), 0.78f)
.SetEase(morphEase));
}
if (terminalUI != null)
{
float uiAlpha = 0f;
float morph = 0f;
seq.Join(DOTween.To(() => uiAlpha, v =>
{
uiAlpha = v;
terminalUI.Alpha = v;
}, 1f, 0.24f).SetEase(Ease.OutQuad));
seq.Join(DOTween.To(() => morph, v =>
{
morph = v;
terminalUI.MorphProgress = v;
}, 1f, 0.82f).SetEase(morphEase));
}
if (_terminalUiTransform != null)
{
seq.Join(_terminalUiTransform.DOScale(_terminalUiOriginalScale, 0.82f)
.SetEase(Ease.OutCubic));
}
// Step 3: 第二次微闪(终端稳定)
if (flashOverlay != null)
{
seq.Append(flashOverlay.DOFade(0.5f, 0.03f));
seq.Append(flashOverlay.DOFade(0f, 0.15f));
}
yield return seq.WaitForCompletion();
if (codeSea != null)
codeSea.gameObject.SetActive(false);
}
#endregion
#region
public IEnumerator PlayShutdownEffect()
{
var target = _terminalUiTransform != null ? _terminalUiTransform : _codeSeaTransform;
if (target == null) yield break;
var seq = DOTween.Sequence();
if (flashOverlay != null)
seq.Append(flashOverlay.DOFade(0.6f, 0.15f));
// 压扁成白线
float scaleY = _terminalUiTransform != null ? _terminalUiOriginalScale.y * 0.02f : 0.005f;
seq.Join(target.DOScaleY(scaleY, 0.35f).SetEase(Ease.OutQuad));
// 横向收缩消失
seq.Append(target.DOScaleX(0f, 0.3f).SetEase(Ease.InQuad));
if (flashOverlay != null)
seq.Join(flashOverlay.DOFade(0f, 0.5f));
// 同步淡出 Shapes 终端
if (terminalUI != null)
{
float a = terminalUI.Alpha;
seq.Join(DOTween.To(() => a, v => { a = v; terminalUI.Alpha = v; }, 0f, 0.4f));
}
yield return seq.WaitForCompletion();
}
public void PlayCrashEffect()
{
var target = _terminalUiTransform != null ? _terminalUiTransform : _codeSeaTransform;
if (target != null)
target.DOShakePosition(1.2f, 0.08f, 35, fadeOut: false);
}
public void StopAllEffects()
{
DOTween.Kill(_codeSeaTransform);
DOTween.Kill(codeSea);
DOTween.Kill(_terminalUiTransform);
DOTween.Kill(flashOverlay);
}
#endregion
#region
public void HideAll()
{
StopAllEffects();
HideDoor();
if (glassSea != null)
{
glassSea.SetAlpha(0);
glassSea.gameObject.SetActive(false);
}
if (codeSea != null)
{
codeSea.color = _codeSeaOriginalColor;
codeSea.SetAlpha(0);
codeSea.gameObject.SetActive(false);
if (_codeSeaTransform != null)
_codeSeaTransform.localScale = _codeSeaOriginalScale;
}
if (terminalUI != null)
{
terminalUI.Alpha = 0f;
terminalUI.ResetVisualState();
}
if (_terminalUiTransform != null)
_terminalUiTransform.localScale = _terminalUiOriginalScale;
if (flashOverlay != null)
flashOverlay.SetAlpha(0);
}
#endregion
#if UNITY_EDITOR
private void OnDrawGizmosSelected()
{
if (codeSea == null) return;
Gizmos.color = new Color(1f, 0.7f, 0f, 0.4f);
var bounds = codeSea.bounds;
Gizmos.DrawWireCube(bounds.center, bounds.size);
Gizmos.color = new Color(0f, 1f, 1f, 0.3f);
Vector3 termSize = new(
bounds.size.x * seaCollapseScale.x,
bounds.size.y * seaCollapseScale.y,
bounds.size.z
);
Gizmos.DrawWireCube(bounds.center, termSize);
}
#endif
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5da7fe5bad47f764bb5ce8a12e59ec2c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,47 @@
using System.Collections;
using Yarn.Unity;
namespace AibisDream
{
public static class DreamDoorYarnCommand
{
/// <summary>
/// 显示整个门(仅 background + Frame)。默认门是隐藏的,需先调用此命令。
/// </summary>
[YarnCommand("show_door")]
public static IEnumerator ShowDoor(float duration = 0f)
{
yield return DreamDoorSystem.Instance.ShowDoor(duration);
}
[YarnCommand("show_door_glass_sea")]
public static IEnumerator ShowDoorGlassSea(float duration = 2f)
{
yield return DreamDoorSystem.Instance.ShowGlassSea(duration);
}
[YarnCommand("hide_door_glass_sea")]
public static IEnumerator HideDoorGlassSea(float duration = 1f)
{
yield return DreamDoorSystem.Instance.HideGlassSea(duration);
}
[YarnCommand("show_door_code_sea")]
public static IEnumerator ShowDoorCodeSea(float duration = 2f)
{
yield return DreamDoorSystem.Instance.ShowCodeSea(duration);
}
[YarnCommand("show_dream_terminal")]
public static IEnumerator ShowDreamTerminal()
{
yield return DreamDoorSystem.Instance.ShowTerminal();
}
[YarnCommand("hide_dream_door")]
public static void HideDreamDoor()
{
DreamDoorSystem.Instance.HideAll();
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: aa28f05af98b0f94d9979fb91ace8e7f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,756 @@
using System;
using System.Collections;
using System.Collections.Generic;
using DG.Tweening;
using Shapes;
using TMPro;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace AibisDream.UI
{
/// <summary>
/// 梦境命令窗口:全部用 Shapes 即时模式绘制,无需手动配置任何 Canvas 或 UI 组件。
/// 挂在 Door 节点(或其子节点)上即可。
/// </summary>
[ExecuteAlways]
public class DreamTerminalUI : ImmediateModeShapeDrawer
{
#region
[Header("尺寸(世界单位)")]
[SerializeField] private Vector2 terminalSize = new(6.8f, 4.2f);
[SerializeField] private Vector2 morphStartSize = new(8.6f, 5.6f);
[Header("琥珀色调色盘")]
[SerializeField] private Color colAmberMain = new(1f, 0.69f, 0f, 1f); // #ffb000
[SerializeField] private Color colAmberDim = new(0.72f, 0.52f, 0.04f, 1f); // #b8860b
[SerializeField] private Color colWhiteGlow = new(1f, 1f, 1f, 1f);
[SerializeField] private Color colBg = new(0.02f, 0.02f, 0.02f, 0.96f);
[Header("布局")]
[SerializeField] private float borderThickness = 0.05f;
[SerializeField] private float padding = 0.3f;
[SerializeField] private float lineHeight = 0.3f;
[SerializeField] private float fontSize = 0.24f;
[SerializeField] private float inputAreaHeight = 0.58f;
[SerializeField] private int maxVisibleLines = 9;
[Header("扫描线")]
[SerializeField] private float scanlineSpacing = 0.07f;
[SerializeField] private float scanlineAlpha = 0.08f;
[Header("光标")]
[SerializeField] private float cursorBlinkRate = 0.5f;
[SerializeField] private Vector2 cursorSize = new(0.14f, 0.24f);
[Header("形变")]
[Range(0f, 1f)]
[SerializeField] private float morphProgress = 0f;
[Header("编辑器预览")]
[SerializeField] private bool previewInEditor = true;
[Range(0f, 1f)]
[SerializeField] private float previewAlpha = 1f;
[Range(0f, 1f)]
[SerializeField] private float previewMorphProgress = 1f;
[SerializeField] private PreviewStage previewStage = PreviewStage.WaitingInput;
[SerializeField] private bool animatePreviewCursor = true;
[SerializeField] private string previewInputBuffer = "false";
[TextArea(3, 8)]
[SerializeField] private string previewLines =
">> WARNING: TRAP DETECTED.\n" +
">> SYSTEM: Reality_Engine.sys stopped.\n" +
">> SYSTEM: Rendering underlying code...\n" +
">> LOADING: Ocean_Simulation.sh ... OK\n" +
"root@sys:~$ print_string(\"海是存在的吗?\")";
[SerializeField] private string previewTypingLine = "";
[Header("交互")]
[SerializeField] private int maxInputLength = 20;
[SerializeField] private string promptString = "> bit seaExists = ";
[SerializeField] private string onCompleteNode = "苏醒";
[Header("启动日志")]
[SerializeField] private List<BootLogEntry> bootSequence = new()
{
new BootLogEntry { text = ">> WARNING: TRAP DETECTED.", style = LogStyle.Alert, delayAfter = 0.5f },
new BootLogEntry { text = ">> SYSTEM: Reality_Engine.sys stopped.", style = LogStyle.Dim, delayAfter = 0.2f },
new BootLogEntry { text = ">> SYSTEM: Rendering underlying code...", style = LogStyle.Dim, delayAfter = 0.2f },
new BootLogEntry { text = ">> LOADING: Ocean_Simulation.sh ... OK", style = LogStyle.Dim, delayAfter = 0.8f },
new BootLogEntry { text = "root@sys:~$ print_string(\"海是存在的吗?\")", style = LogStyle.Highlight, delayAfter = 0.5f },
};
#endregion
#region
private enum TerminalPhase { Idle, BootSequence, WaitingInput, Confirming, EndAnimation, Done }
private TerminalPhase _phase = TerminalPhase.Idle;
// 可见文本行及其颜色
private readonly List<string> _lines = new();
private readonly List<Color> _lineColors = new();
// 打字机
private string _typingTarget = "";
private string _typingCurrent = "";
private bool _typingDone = false;
private Color _typingColor;
private Coroutine _typewriterCoroutine;
// 输入
private string _inputBuffer = "";
private bool _cursorVisible = true;
private Coroutine _cursorBlinkCoroutine;
private Coroutine _crashSpamCoroutine;
private double _editorLastRepaintTime;
// 全局 alpha(用于 DreamDoorSystem 淡入淡出)
public float Alpha { get; set; } = 0f;
public float MorphProgress
{
get => morphProgress;
set => morphProgress = Mathf.Clamp01(value);
}
#endregion
#region
private void Awake()
{
Alpha = 0f;
MorphProgress = 0f;
_phase = TerminalPhase.Idle;
}
private void Update()
{
if (!Application.isPlaying)
{
UpdateEditorPreview();
return;
}
if (_phase == TerminalPhase.WaitingInput)
HandleTypingInput();
else if (_phase == TerminalPhase.Confirming)
HandleConfirmInput();
}
public override void OnDisable()
{
base.OnDisable();
_phase = TerminalPhase.Idle;
StopAllCoroutines();
}
public override void OnEnable()
{
base.OnEnable();
if (!Application.isPlaying)
ApplyEditorPreviewState();
}
private void OnValidate()
{
MorphProgress = morphProgress;
if (!Application.isPlaying)
ApplyEditorPreviewState();
}
#endregion
#region
public void Begin()
{
if (_phase != TerminalPhase.Idle) return;
_lines.Clear();
_lineColors.Clear();
_inputBuffer = "";
MorphProgress = 1f;
StartCoroutine(RunBootSequence());
}
public void ForceEnd()
{
StopAllCoroutines();
_phase = TerminalPhase.Done;
}
public void ResetVisualState()
{
StopAllCoroutines();
_phase = TerminalPhase.Idle;
_lines.Clear();
_lineColors.Clear();
_typingTarget = "";
_typingCurrent = "";
_typingDone = false;
_inputBuffer = "";
_cursorVisible = false;
MorphProgress = 0f;
}
[ContextMenu("Preview/Frame Only")]
private void PreviewFrameOnly()
{
previewInEditor = true;
previewStage = PreviewStage.FrameOnly;
previewAlpha = 1f;
previewMorphProgress = 0.65f;
ApplyEditorPreviewState();
}
[ContextMenu("Preview/Waiting Input")]
private void PreviewWaitingInput()
{
previewInEditor = true;
previewStage = PreviewStage.WaitingInput;
previewAlpha = 1f;
previewMorphProgress = 1f;
ApplyEditorPreviewState();
}
[ContextMenu("Preview/Clear")]
private void ClearPreview()
{
previewInEditor = false;
ApplyEditorPreviewState();
}
#endregion
#region Shapes DrawShapes
public override void DrawShapes(Camera cam)
{
if (Alpha <= 0.01f) return;
float frameProgress = Mathf.SmoothStep(0f, 1f, MorphProgress);
float textReveal = Mathf.InverseLerp(0.78f, 1f, frameProgress);
Vector2 currentSize = Vector2.Lerp(morphStartSize, terminalSize, frameProgress);
using (Draw.Command(cam))
{
Draw.BlendMode = ShapesBlendMode.Transparent;
Draw.ZTest = UnityEngine.Rendering.CompareFunction.Always;
using (Draw.MatrixScope)
{
Draw.Matrix = transform.localToWorldMatrix;
DrawBackground(currentSize, frameProgress);
DrawScanlines(currentSize, frameProgress);
DrawBorder(currentSize, frameProgress);
DrawLogLines(currentSize, textReveal);
DrawInputArea(currentSize, textReveal);
}
}
}
// ----- 背景 -----
private void DrawBackground(Vector2 currentSize, float frameProgress)
{
Color bg = colBg;
bg.a *= Alpha * Mathf.Lerp(0.18f, 1f, frameProgress);
Draw.Rectangle(Vector3.zero, Quaternion.identity, currentSize, bg);
}
// ----- CRT 扫描线 -----
private void DrawScanlines(Vector2 currentSize, float frameProgress)
{
float scanReveal = Mathf.InverseLerp(0.35f, 1f, frameProgress);
if (scanReveal <= 0f) return;
float halfH = currentSize.y * 0.5f;
float halfW = currentSize.x * 0.5f;
Color scanCol = new Color(0f, 0f, 0f, scanlineAlpha * Alpha * scanReveal);
Draw.Thickness = scanlineSpacing * 0.5f;
Draw.LineGeometry = LineGeometry.Flat2D;
// 横向扫描线(每隔 spacing 画一条暗线)
float y = -halfH + scanlineSpacing;
while (y < halfH)
{
Draw.Line(new Vector3(-halfW, y, 0f), new Vector3(halfW, y, 0f), scanCol);
y += scanlineSpacing * 2f;
}
}
// ----- 琥珀色边框 -----
private void DrawBorder(Vector2 currentSize, float frameProgress)
{
float borderReveal = Mathf.InverseLerp(0.15f, 0.78f, frameProgress);
if (borderReveal <= 0f) return;
Color borderCol = colAmberMain;
borderCol.a *= Alpha * borderReveal;
Draw.RectangleBorder(Vector3.zero, Quaternion.identity, currentSize, borderThickness, borderCol);
float halfW = currentSize.x * 0.5f;
float halfH = currentSize.y * 0.5f;
float cornerLen = Mathf.Lerp(0.25f, 0.6f, borderReveal);
float inset = borderThickness * 0.6f;
Draw.Thickness = borderThickness * 0.75f;
Draw.LineGeometry = LineGeometry.Flat2D;
DrawCorner(new Vector2(-halfW + inset, halfH - inset), Vector2.right, Vector2.down, cornerLen, borderCol);
DrawCorner(new Vector2( halfW - inset, halfH - inset), Vector2.left, Vector2.down, cornerLen, borderCol);
DrawCorner(new Vector2(-halfW + inset, -halfH + inset), Vector2.right, Vector2.up, cornerLen, borderCol);
DrawCorner(new Vector2( halfW - inset, -halfH + inset), Vector2.left, Vector2.up, cornerLen, borderCol);
float separatorReveal = Mathf.InverseLerp(0.45f, 0.95f, frameProgress);
if (separatorReveal > 0f)
{
Color divCol = colAmberDim;
divCol.a *= Alpha * separatorReveal;
float botY = -currentSize.y * 0.5f + inputAreaHeight;
float lineHalfWidth = (halfW - padding) * separatorReveal;
Draw.Thickness = 0.015f;
Draw.Line(
new Vector3(-lineHalfWidth, botY, 0f),
new Vector3(lineHalfWidth, botY, 0f),
divCol
);
}
}
// ----- 日志文本区 -----
private void DrawLogLines(Vector2 currentSize, float textReveal)
{
if (textReveal <= 0f) return;
float halfW = currentSize.x * 0.5f;
float topY = currentSize.y * 0.5f - padding;
// 最多显示 maxVisibleLines 行
int startIdx = Mathf.Max(0, _lines.Count - maxVisibleLines);
for (int i = startIdx; i < _lines.Count; i++)
{
int row = i - startIdx;
float y = topY - row * lineHeight;
Color c = _lineColors.Count > i ? _lineColors[i] : colAmberMain;
c.a *= Alpha * textReveal;
Draw.FontSize = fontSize;
Draw.Text(
new Vector3(-halfW + padding, y, 0f),
Quaternion.identity,
_lines[i],
TextAlign.TopLeft,
c
);
}
// 正在打字的当前行
if (!string.IsNullOrEmpty(_typingCurrent))
{
int row = Mathf.Min(_lines.Count - startIdx, maxVisibleLines - 1);
float y = topY - row * lineHeight;
Color c = _typingColor;
c.a *= Alpha * textReveal;
Draw.FontSize = fontSize;
Draw.Text(
new Vector3(-halfW + padding, y, 0f),
Quaternion.identity,
_typingCurrent,
TextAlign.TopLeft,
c
);
}
}
// ----- 输入区 -----
private void DrawInputArea(Vector2 currentSize, float textReveal)
{
if (textReveal <= 0f)
return;
if (_phase != TerminalPhase.WaitingInput && _phase != TerminalPhase.Confirming)
return;
float halfW = currentSize.x * 0.5f;
float botY = -currentSize.y * 0.5f + inputAreaHeight;
// Prompt + 用户输入
string display = promptString + _inputBuffer;
Color promptCol = colAmberMain;
promptCol.a *= Alpha * textReveal;
float textY = botY - lineHeight * 0.6f;
Draw.FontSize = fontSize;
Draw.Text(
new Vector3(-halfW + padding, textY, 0f),
Quaternion.identity,
display,
TextAlign.TopLeft,
promptCol
);
// 闪烁光标
if (_cursorVisible && _phase == TerminalPhase.WaitingInput)
{
// 估算文本宽度(粗略按字符数 × fontSize × 0.6
float textWidth = display.Length * fontSize * 0.6f;
Vector3 cursorPos = new Vector3(-halfW + padding + textWidth, textY - cursorSize.y * 0.3f, 0f);
Color cursorCol = colAmberMain;
cursorCol.a *= Alpha * textReveal;
Draw.Rectangle(cursorPos, Quaternion.identity, cursorSize, cursorCol);
}
}
private static void DrawCorner(Vector2 pivot, Vector2 horizontalDir, Vector2 verticalDir, float length, Color color)
{
Draw.Line(
new Vector3(pivot.x, pivot.y, 0f),
new Vector3(pivot.x + horizontalDir.x * length, pivot.y + horizontalDir.y * length, 0f),
color
);
Draw.Line(
new Vector3(pivot.x, pivot.y, 0f),
new Vector3(pivot.x + verticalDir.x * length, pivot.y + verticalDir.y * length, 0f),
color
);
}
#endregion
#region
private void AddLine(string text, Color color)
{
_lines.Add(text);
_lineColors.Add(color);
}
private void AppendToLastLine(string text)
{
if (_lines.Count > 0)
_lines[^1] += text;
}
private IEnumerator TypewriterLine(string text, Color color, float charDelay = 0.025f)
{
_typingTarget = text;
_typingCurrent = "";
_typingColor = color;
_typingDone = false;
foreach (char c in text)
{
_typingCurrent += c;
yield return new WaitForSeconds(charDelay);
}
// 提交为已完成行
AddLine(_typingCurrent, color);
_typingCurrent = "";
_typingTarget = "";
_typingDone = true;
}
private IEnumerator WaitForTypewriter()
{
while (!_typingDone)
yield return null;
}
#endregion
#region Boot Sequence
private IEnumerator RunBootSequence()
{
_phase = TerminalPhase.BootSequence;
yield return new WaitForSeconds(0.3f);
foreach (var entry in bootSequence)
{
Color c = StyleToColor(entry.style);
_typewriterCoroutine = StartCoroutine(TypewriterLine(entry.text, c));
yield return WaitForTypewriter();
if (entry.delayAfter > 0f)
yield return new WaitForSeconds(entry.delayAfter);
}
yield return new WaitForSeconds(0.3f);
EnterInputPhase();
}
private Color StyleToColor(LogStyle style) => style switch
{
LogStyle.Alert => colWhiteGlow,
LogStyle.Highlight => colWhiteGlow,
LogStyle.Dim => colAmberDim,
_ => colAmberMain
};
#endregion
#region Input Phase
private void EnterInputPhase()
{
_phase = TerminalPhase.WaitingInput;
_inputBuffer = "";
StartCursorBlink();
}
private void HandleTypingInput()
{
foreach (char c in Input.inputString)
{
if (c == '\b')
{
if (_inputBuffer.Length > 0)
_inputBuffer = _inputBuffer[..^1];
}
else if (c == '\n' || c == '\r')
{
if (_inputBuffer.Length > 0)
EnterConfirmPhase();
return;
}
else if (!char.IsControl(c) && _inputBuffer.Length < maxInputLength)
{
_inputBuffer += c;
}
}
}
#endregion
#region Confirm Phase
private void EnterConfirmPhase()
{
_phase = TerminalPhase.Confirming;
StopCursorBlink();
AddLine(">> Submit Reality Check? (Y/N)", colWhiteGlow);
}
private void HandleConfirmInput()
{
if (Input.GetKeyDown(KeyCode.Y))
{
_phase = TerminalPhase.EndAnimation;
StartCoroutine(HandleSubmission(_inputBuffer));
}
else if (Input.GetKeyDown(KeyCode.N))
{
_phase = TerminalPhase.WaitingInput;
StartCursorBlink();
}
}
#endregion
#region End Animation
private IEnumerator HandleSubmission(string input)
{
string val = input.Trim().ToLower();
bool isFalse = val is "false" or "0" or "no" or "不存在";
if (isFalse)
yield return PlayShutdownEnding();
else
yield return PlayCrashEnding();
_phase = TerminalPhase.Done;
yield return new WaitForSeconds(1f);
DialogController.Instance.StartDialogNode(onCompleteNode);
}
private IEnumerator PlayShutdownEnding()
{
AddLine(">> FALSE. SHUTTING DOWN...", colWhiteGlow);
yield return new WaitForSeconds(1.5f);
yield return DreamDoorSystem.Instance.PlayShutdownEffect();
}
private IEnumerator PlayCrashEnding()
{
AddLine(">> TRUE. ERROR: OVERFLOW.", colWhiteGlow);
yield return new WaitForSeconds(0.8f);
DreamDoorSystem.Instance.PlayCrashEffect();
_crashSpamCoroutine = StartCoroutine(SpamErrorLines());
yield return new WaitForSeconds(3f);
if (_crashSpamCoroutine != null)
StopCoroutine(_crashSpamCoroutine);
DreamDoorSystem.Instance.StopAllEffects();
}
private IEnumerator SpamErrorLines()
{
while (true)
{
string hex = UnityEngine.Random.Range(0, 0xFFFF).ToString("x4");
AddLine($"0x{hex} SYSTEM FAILURE", colAmberDim);
yield return new WaitForSeconds(0.05f);
}
}
#endregion
#region
private void StartCursorBlink()
{
_cursorVisible = true;
_cursorBlinkCoroutine = StartCoroutine(BlinkCursor());
}
private void StopCursorBlink()
{
if (_cursorBlinkCoroutine != null)
StopCoroutine(_cursorBlinkCoroutine);
_cursorVisible = false;
}
private IEnumerator BlinkCursor()
{
while (true)
{
_cursorVisible = !_cursorVisible;
yield return new WaitForSeconds(cursorBlinkRate);
}
}
#endregion
#region
[Serializable]
public class BootLogEntry
{
public string text;
public LogStyle style;
public float delayAfter;
}
private enum PreviewStage
{
Hidden,
FrameOnly,
BootText,
WaitingInput,
Confirming
}
public enum LogStyle { Normal, Alert, Highlight, Dim }
#endregion
#if UNITY_EDITOR
private void UpdateEditorPreview()
{
ApplyEditorPreviewState();
if (previewInEditor)
{
EditorApplication.QueuePlayerLoopUpdate();
double now = EditorApplication.timeSinceStartup;
if (now - _editorLastRepaintTime > 0.08d)
{
_editorLastRepaintTime = now;
SceneView.RepaintAll();
}
}
}
private void ApplyEditorPreviewState()
{
if (Application.isPlaying)
return;
if (!previewInEditor)
{
Alpha = 0f;
MorphProgress = 0f;
_phase = TerminalPhase.Idle;
_lines.Clear();
_lineColors.Clear();
_typingCurrent = "";
_inputBuffer = "";
_cursorVisible = false;
return;
}
Alpha = previewAlpha;
MorphProgress = previewMorphProgress;
_lines.Clear();
_lineColors.Clear();
if (!string.IsNullOrWhiteSpace(previewLines))
{
var previewEntries = previewLines.Replace("\r\n", "\n").Split('\n', StringSplitOptions.RemoveEmptyEntries);
foreach (var line in previewEntries)
AddPreviewLine(line);
}
_typingCurrent = previewTypingLine ?? "";
_typingColor = colAmberMain;
_inputBuffer = previewInputBuffer ?? "";
switch (previewStage)
{
case PreviewStage.Hidden:
Alpha = 0f;
MorphProgress = 0f;
_phase = TerminalPhase.Idle;
_cursorVisible = false;
break;
case PreviewStage.FrameOnly:
_phase = TerminalPhase.Idle;
_typingCurrent = "";
_cursorVisible = false;
break;
case PreviewStage.BootText:
_phase = TerminalPhase.BootSequence;
_cursorVisible = false;
break;
case PreviewStage.WaitingInput:
_phase = TerminalPhase.WaitingInput;
_cursorVisible = animatePreviewCursor
? ((EditorApplication.timeSinceStartup % (cursorBlinkRate * 2f)) < cursorBlinkRate)
: true;
break;
case PreviewStage.Confirming:
_phase = TerminalPhase.Confirming;
_cursorVisible = false;
AddPreviewLine(">> Submit Reality Check? (Y/N)");
break;
}
}
private void AddPreviewLine(string text)
{
Color color = text.Contains("WARNING") || text.Contains("FALSE") || text.Contains("ERROR")
? colWhiteGlow
: text.Contains("SYSTEM") || text.Contains("LOADING")
? colAmberDim
: colAmberMain;
_lines.Add(text);
_lineColors.Add(color);
}
#endif
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: df85ec8ec1f91ba4a94b313b13053046
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: