diff --git a/Assets/GameContent/Scene_Dream/Materials.meta b/Assets/GameContent/Scene_Dream/Materials.meta new file mode 100644 index 000000000..802236d6d --- /dev/null +++ b/Assets/GameContent/Scene_Dream/Materials.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 65a0de17c7fc4cc39ae305f6bb18ac77 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameContent/Scene_Dream/Materials/DreamDataOverflow.mat b/Assets/GameContent/Scene_Dream/Materials/DreamDataOverflow.mat new file mode 100644 index 000000000..89cc8cc8d --- /dev/null +++ b/Assets/GameContent/Scene_Dream/Materials/DreamDataOverflow.mat @@ -0,0 +1,39 @@ +%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.mat.meta b/Assets/GameContent/Scene_Dream/Materials/DreamDataOverflow.mat.meta new file mode 100644 index 000000000..5f9152ca1 --- /dev/null +++ b/Assets/GameContent/Scene_Dream/Materials/DreamDataOverflow.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: db54ed6c97bf4f05a79f53b268f0c52a +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameContent/Scene_Dream/Materials/DreamDataOverflow.shader b/Assets/GameContent/Scene_Dream/Materials/DreamDataOverflow.shader new file mode 100644 index 000000000..d274de458 --- /dev/null +++ b/Assets/GameContent/Scene_Dream/Materials/DreamDataOverflow.shader @@ -0,0 +1,154 @@ +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 new file mode 100644 index 000000000..a2f307aeb --- /dev/null +++ b/Assets/GameContent/Scene_Dream/Materials/DreamDataOverflow.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 6c30d8e44b1b4b4ab9414a90e069f290 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes/梦境.unity b/Assets/Scenes/梦境.unity index aaa0635f8..cdb494efa 100644 --- a/Assets/Scenes/梦境.unity +++ b/Assets/Scenes/梦境.unity @@ -325,6 +325,7 @@ GameObject: - component: {fileID: 132823524} - component: {fileID: 132823525} - component: {fileID: 132823526} + - component: {fileID: 132823527} m_Layer: 0 m_Name: "\u573A\u666F\u52A8\u753B" m_TagString: Untagged @@ -406,6 +407,36 @@ MonoBehaviour: autoBindCinemachineBrain: 0 resetToStartWhenFinished: 0 resetToStartDelay: 0 +--- !u!114 &132823527 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 132823522} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: c0c737b07db74d53bd47f7b140346ad4, type: 3} + m_Name: + m_EditorClassIdentifier: + director: {fileID: 132823524} + starfieldRenderer: {fileID: 1420961919} + initialBlur: 0.78 + blurSize: 0.009 + 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 + blurFadeStart: 4 + blurFadeDuration: 3.2 --- !u!1 &218986882 GameObject: m_ObjectHideFlags: 0 @@ -458,7 +489,7 @@ SpriteRenderer: m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: a97c105638bdf8b4a8650670310a4cd3, type: 2} + - {fileID: 2100000, guid: db54ed6c97bf4f05a79f53b268f0c52a, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -1036,7 +1067,7 @@ SpriteRenderer: m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: a97c105638bdf8b4a8650670310a4cd3, type: 2} + - {fileID: 2100000, guid: db54ed6c97bf4f05a79f53b268f0c52a, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 diff --git a/Assets/Scripts/Dialog System/BaseYarnCommand.cs b/Assets/Scripts/Dialog System/BaseYarnCommand.cs index a300f15dc..4f4c24820 100644 --- a/Assets/Scripts/Dialog System/BaseYarnCommand.cs +++ b/Assets/Scripts/Dialog System/BaseYarnCommand.cs @@ -92,6 +92,22 @@ 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/SpriteShowcase.cs b/Assets/Scripts/SceneManagement/SpriteShowcase.cs index 3979e0ab1..96e8ad112 100644 --- a/Assets/Scripts/SceneManagement/SpriteShowcase.cs +++ b/Assets/Scripts/SceneManagement/SpriteShowcase.cs @@ -20,6 +20,33 @@ 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; @@ -35,6 +62,8 @@ namespace AibisDream public override void OnSingletonInit() { + _dreamOverflowSettings = EntryOverflowSettings(); + ResetDreamOverflow(); CaptureSmallBaseTransform(); // 初始状态:隐藏 @@ -49,6 +78,131 @@ namespace AibisDream } } + private void OnDisable() + { + ResetDreamOverflow(); + } + + 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(); + } + private void CaptureSmallBaseTransform() { if (_spriteRenderer == null) return; @@ -88,6 +242,7 @@ 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) diff --git a/Assets/Scripts/SceneManagement/TimelineKit/StarfieldDefocusController.cs b/Assets/Scripts/SceneManagement/TimelineKit/StarfieldDefocusController.cs new file mode 100644 index 000000000..e11595444 --- /dev/null +++ b/Assets/Scripts/SceneManagement/TimelineKit/StarfieldDefocusController.cs @@ -0,0 +1,174 @@ +using UnityEngine; +using UnityEngine.Playables; + +namespace AibisDream +{ + /// + /// Drives the deliberately unsuccessful focus pulls at the start of the + /// starfield-to-sea Timeline. The effect is evaluated from Timeline time so + /// pausing, frame drops and repeated playback remain deterministic. + /// + public sealed class StarfieldDefocusController : MonoBehaviour + { + private static readonly int BlurAmountId = Shader.PropertyToID("_BlurAmount"); + private static readonly int BlurSizeId = Shader.PropertyToID("_BlurSize"); + + [Header("References")] + [SerializeField] private PlayableDirector director; + [SerializeField] private SpriteRenderer starfieldRenderer; + + [Header("Defocus Look")] + [Range(0f, 1f)] + [SerializeField] private float initialBlur = 0.78f; + [Range(0f, 0.05f)] + [SerializeField] private float blurSize = 0.009f; + + [Header("Focus Attempt 1")] + [Min(0f)] + [SerializeField] private float firstAttemptStart = 0.45f; + [Min(0.01f)] + [SerializeField] private float firstFocusDuration = 0.48f; + [Range(0f, 1f)] + [SerializeField] private float firstNearFocusBlur = 0.38f; + [Min(0f)] + [SerializeField] private float firstHoldDuration = 0.14f; + [Min(0.01f)] + [SerializeField] private float firstSlipDuration = 0.38f; + [Range(0f, 1f)] + [SerializeField] private float firstSlipBlur = 0.72f; + + [Header("Focus Attempt 2")] + [Min(0f)] + [SerializeField] private float secondAttemptStart = 1.72f; + [Min(0.01f)] + [SerializeField] private float secondFocusDuration = 0.55f; + [Range(0f, 1f)] + [SerializeField] private float secondNearFocusBlur = 0.28f; + [Min(0f)] + [SerializeField] private float secondHoldDuration = 0.18f; + [Min(0.01f)] + [SerializeField] private float secondSlipDuration = 0.46f; + [Range(0f, 1f)] + [SerializeField] private float unresolvedBlur = 0.62f; + + [Header("Downward Pan")] + [Tooltip("Timeline time at which the starfield starts moving down toward the sea.")] + [Min(0f)] + [SerializeField] private float blurFadeStart = 4f; + [Min(0.01f)] + [SerializeField] private float blurFadeDuration = 3.2f; + + private MaterialPropertyBlock propertyBlock; + + private void Reset() + { + director = GetComponent(); + starfieldRenderer = GetComponentInChildren(true); + } + + private void Awake() + { + propertyBlock = new MaterialPropertyBlock(); + ApplyAtTime(director != null ? (float)director.time : 0f); + } + + private void OnEnable() + { + ApplyAtTime(director != null ? (float)director.time : 0f); + } + + private void LateUpdate() + { + if (director == null || starfieldRenderer == null) + { + return; + } + + ApplyAtTime((float)director.time); + } + + private void ApplyAtTime(float time) + { + if (starfieldRenderer == null) + { + return; + } + + propertyBlock ??= new MaterialPropertyBlock(); + starfieldRenderer.GetPropertyBlock(propertyBlock); + propertyBlock.SetFloat(BlurAmountId, EvaluateBlur(time)); + propertyBlock.SetFloat(BlurSizeId, blurSize); + starfieldRenderer.SetPropertyBlock(propertyBlock); + } + + private float EvaluateBlur(float time) + { + float firstFocusEnd = firstAttemptStart + firstFocusDuration; + float firstHoldEnd = firstFocusEnd + firstHoldDuration; + float firstSlipEnd = firstHoldEnd + firstSlipDuration; + + float secondFocusEnd = secondAttemptStart + secondFocusDuration; + float secondHoldEnd = secondFocusEnd + secondHoldDuration; + float secondSlipEnd = secondHoldEnd + secondSlipDuration; + + if (time < firstAttemptStart) + { + return initialBlur; + } + + if (time < firstFocusEnd) + { + return SmoothLerp(initialBlur, firstNearFocusBlur, InverseLerp(firstAttemptStart, firstFocusEnd, time)); + } + + if (time < firstHoldEnd) + { + return firstNearFocusBlur; + } + + if (time < firstSlipEnd) + { + return SmoothLerp(firstNearFocusBlur, firstSlipBlur, InverseLerp(firstHoldEnd, firstSlipEnd, time)); + } + + if (time < secondAttemptStart) + { + return firstSlipBlur; + } + + if (time < secondFocusEnd) + { + return SmoothLerp(firstSlipBlur, secondNearFocusBlur, InverseLerp(secondAttemptStart, secondFocusEnd, time)); + } + + if (time < secondHoldEnd) + { + return secondNearFocusBlur; + } + + if (time < secondSlipEnd) + { + return SmoothLerp(secondNearFocusBlur, unresolvedBlur, InverseLerp(secondHoldEnd, secondSlipEnd, time)); + } + + if (time < blurFadeStart) + { + return unresolvedBlur; + } + + return SmoothLerp(unresolvedBlur, 0f, InverseLerp(blurFadeStart, blurFadeStart + blurFadeDuration, time)); + } + + private static float InverseLerp(float from, float to, float value) + { + return Mathf.Clamp01((value - from) / Mathf.Max(0.0001f, to - from)); + } + + private static float SmoothLerp(float from, float to, float t) + { + t = Mathf.Clamp01(t); + t = t * t * (3f - 2f * t); + return Mathf.LerpUnclamped(from, to, t); + } + } +} diff --git a/Assets/Scripts/SceneManagement/TimelineKit/StarfieldDefocusController.cs.meta b/Assets/Scripts/SceneManagement/TimelineKit/StarfieldDefocusController.cs.meta new file mode 100644 index 000000000..c2b938490 --- /dev/null +++ b/Assets/Scripts/SceneManagement/TimelineKit/StarfieldDefocusController.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c0c737b07db74d53bd47f7b140346ad4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Yarn/FP/FP_Day2_sleep/FP_Day2_sleep.yarn b/Assets/Yarn/FP/FP_Day2_sleep/FP_Day2_sleep.yarn index 346f5ad27..25c56e748 100644 --- a/Assets/Yarn/FP/FP_Day2_sleep/FP_Day2_sleep.yarn +++ b/Assets/Yarn/FP/FP_Day2_sleep/FP_Day2_sleep.yarn @@ -20,11 +20,13 @@ position: 2,-331 <> +<> +<> jg: 数据溢出:未知来源的记忆… #line:09952c6 jg: VERYFYING…bool seaExists = false; waiting for imput… #auto_next #line:05a8257 <> +<> // <> -<> ???: …下来… #line:0c8c60b ???: 下来…下来。 #line:07bfa4b <> @@ -43,8 +45,10 @@ me: 这到底是… #line:0ef08ad jg: 数据溢出:未知来源的记忆… #line:007d96c me: 啊…又来了… #line:0b0acd0 jg: VERYFYING…bool seaExists = waiting f 【WARNING: UNEXP #auto_next #line:07f7aba -<> -<> +<> +<> +<> +<> // 场景闪白 #line:0d8d75a // <> 你感到一阵眩晕。 #line:0ebd65e