Merge branch '3.24火山BUG修复和查漏补缺' into 'develop'

fix(huoshan): 修复多轮表达重叠并支持非目标粒子数配置

See merge request aibis-dream/aibis-dream!654
This commit is contained in:
2026-03-27 09:01:14 +00:00
22 changed files with 6527 additions and 2763 deletions
File diff suppressed because it is too large Load Diff
@@ -1891,7 +1891,7 @@ MonoBehaviour:
m_Metadata:
m_Items: []
- m_Id: 669509366218753
m_Localized: "me: \u73B0\u5728\u5230\u60C5\u7EEA\u3002"
m_Localized: "me: \u8C03\u5165\u60C5\u7EEA\u4FE1\u53F7\u5F00\u59CB\u6B65\u8FDB\u68C0\u67E5\u5427\u3002"
m_Metadata:
m_Items: []
- m_Id: 669509366218752
@@ -3855,6 +3855,14 @@ MonoBehaviour:
m_Localized: "\u9000\u51FA\u9500\u552E\u6A21\u5F0F"
m_Metadata:
m_Items: []
- m_Id: 24204794313998336
m_Localized: "Error: \u8868\u8FBE\u6A21\u5757RAM\u6EA2\u51FA\u3002"
m_Metadata:
m_Items: []
- m_Id: 24204794393690112
m_Localized: "Error: \u7CFB\u7EDF\u4FDD\u62A4\u6027\u4E2D\u65AD\u3002"
m_Metadata:
m_Items: []
references:
version: 2
RefIds: []
Binary file not shown.
@@ -0,0 +1,153 @@
fileFormatVersion: 2
guid: aa3541370148cd141bc90f3fe39bded4
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: 0
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: 21.5
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: 0
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:
@@ -12,7 +12,6 @@ Material:
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords:
- _ENABLEINNEROUTLINE_ON
- _SHADERFADING_NONE
- _SHADERSPACE_UV
- _TEXTURELAYER1SHEETTOGGLE_ON
@@ -202,7 +201,7 @@ Material:
- _EnableHologram: 0
- _EnableHue: 0
- _EnableInkSpread: 0
- _EnableInnerOutline: 1
- _EnableInnerOutline: 0
- _EnableMetal: 0
- _EnableNegative: 0
- _EnableOuterOutline: 0
@@ -0,0 +1,49 @@
%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: SpriteInteractionHint
m_Shader: {fileID: 4800000, guid: a34fe9b6eef27da488f084be707ba0e9, 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: _PulseSteps
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:
- _AlphaThreshold: 0.051
- _EdgeSoftness: 0.095
- _FillPulseStrength: 1
- _InnerEdgeBias: 0.227
- _Intensity: 1
- _OutlineWidth: 1
- _PulseMin: 0.172
- _PulseSpeed: 2.2
- _PulseSteps: 4
- _SweepAngle: 0.35
- _SweepDuration: 1.5
- _SweepInterval: 1.8
- _SweepStrength: 0.12
- _SweepWidth: 0.1
m_Colors:
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _OutlineColor: {r: 1, g: 1, b: 1, a: 1}
m_BuildTextureStacks: []
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3b28880567b674e40bcfab56af27c232
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,618 @@
%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: SpriteInteractionHint2
m_Shader: {fileID: 4800000, guid: da8efd605fdd20949a21be6242000625, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords:
- _ENABLEINNEROUTLINE_ON
- _SHADERFADING_NONE
- _SHADERSPACE_UV
- _TEXTURELAYER1SHEETTOGGLE_ON
- _TEXTURELAYER2SHEETTOGGLE_ON
m_InvalidKeywords: []
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _AddColorMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _AddHueMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _CustomFadeFadeMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _FadingMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _InnerOutlineTintTexture:
m_Texture: {fileID: 2800000, guid: 5af9a397a8643994c829e696a24a7845, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MaskMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetalMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _NormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OuterOutlineTintTexture:
m_Texture: {fileID: 2800000, guid: 5af9a397a8643994c829e696a24a7845, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _PixelOutlineTintTexture:
m_Texture: {fileID: 2800000, guid: 5af9a397a8643994c829e696a24a7845, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _RecolorRGBTexture:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _RecolorRGBYCPTexture:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ShineMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _SineGlowMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _StrongTintMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _TextureLayer1Texture:
m_Texture: {fileID: 2800000, guid: 9685c3a024e22a946a7e8c2ce3542300, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _TextureLayer2Texture:
m_Texture: {fileID: 2800000, guid: 9685c3a024e22a946a7e8c2ce3542300, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _UVDistortMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _UberNoiseTexture:
m_Texture: {fileID: 2800000, guid: b8d18cd117976254d94a812a0bfc336e, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _texcoord:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- unity_Lightmaps:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- unity_LightmapsInd:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- unity_ShadowMasks:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Ints: []
m_Floats:
- _AddColorContrast: 0.5
- _AddColorContrastToggle: 0
- _AddColorFade: 1
- _AddColorMaskToggle: 0
- _AddHueBrightness: 2
- _AddHueContrast: 0.5
- _AddHueFade: 1
- _AddHueMaskToggle: 0
- _AddHueSaturation: 1
- _AddHueSpeed: 1
- _AlphaCutoff: 0.5
- _AlphaTintFade: 1
- _AlphaTintMinAlpha: 0.02
- _BakedMaterial: 0
- _BlackTintFade: 1
- _BlackTintPower: 4
- _Brightness: 1
- _BurnEdgeNoiseFactor: 0.5
- _BurnFade: 1
- _BurnInsideContrast: 2
- _BurnInsideNoiseFactor: 0.2
- _BurnRadius: 5
- _BurnSwirlFactor: 1
- _BurnWidth: 0.1
- _CamouflageAnimationToggle: 0
- _CamouflageContrast: 1
- _CamouflageDensityA: 0.4
- _CamouflageDensityB: 0.4
- _CamouflageFade: 1
- _CamouflageSmoothnessA: 0.2
- _CamouflageSmoothnessB: 0.2
- _CheckerboardDarken: 0.5
- _CheckerboardTiling: 1
- _ColorReplaceContrast: 1
- _ColorReplaceFade: 1
- _ColorReplaceRange: 0.05
- _ColorReplaceSmoothness: 0.1
- _Contrast: 1
- _CustomFadeAlpha: 1
- _CustomFadeNoiseFactor: 0
- _CustomFadeSmoothness: 2
- _DirectionalAlphaFadeFade: 0
- _DirectionalAlphaFadeInvert: 0
- _DirectionalAlphaFadeNoiseFactor: 0.2
- _DirectionalAlphaFadeRotation: 0
- _DirectionalAlphaFadeWidth: 0.2
- _DirectionalDistortionFade: 0
- _DirectionalDistortionInvert: 0
- _DirectionalDistortionNoiseFactor: 0.2
- _DirectionalDistortionRandomDirection: 0.1
- _DirectionalDistortionRotation: 0
- _DirectionalDistortionWidth: 0.5
- _DirectionalGlowFadeFade: 0
- _DirectionalGlowFadeInvert: 0
- _DirectionalGlowFadeNoiseFactor: 0.2
- _DirectionalGlowFadeRotation: 0
- _DirectionalGlowFadeWidth: 0.1
- _EnableAddColor: 0
- _EnableAddHue: 0
- _EnableAlphaTint: 0
- _EnableBlackTint: 0
- _EnableBrightness: 0
- _EnableBurn: 0
- _EnableCamouflage: 0
- _EnableCheckerboard: 0
- _EnableColorReplace: 0
- _EnableContrast: 0
- _EnableCustomFade: 0
- _EnableDirectionalAlphaFade: 0
- _EnableDirectionalDistortion: 0
- _EnableDirectionalGlowFade: 0
- _EnableEnchanted: 0
- _EnableFlame: 0
- _EnableFrozen: 0
- _EnableFullAlphaDissolve: 0
- _EnableFullDistortion: 0
- _EnableFullGlowDissolve: 0
- _EnableGaussianBlur: 0
- _EnableGlitch: 0
- _EnableHalftone: 0
- _EnableHologram: 0
- _EnableHue: 0
- _EnableInkSpread: 0
- _EnableInnerOutline: 1
- _EnableMetal: 0
- _EnableNegative: 0
- _EnableOuterOutline: 0
- _EnablePingPongGlow: 0
- _EnablePixelOutline: 0
- _EnablePixelate: 0
- _EnablePoison: 0
- _EnableRainbow: 0
- _EnableRecolorRGB: 0
- _EnableRecolorRGBYCP: 0
- _EnableSaturation: 0
- _EnableScreenTiling: 0
- _EnableShadow: 0
- _EnableSharpen: 0
- _EnableShiftHue: 0
- _EnableShifting: 0
- _EnableShine: 0
- _EnableSineGlow: 0
- _EnableSineMove: 0
- _EnableSineRotate: 0
- _EnableSineScale: 0
- _EnableSmoke: 0
- _EnableSmoothPixelArt: 0
- _EnableSourceAlphaDissolve: 0
- _EnableSourceGlowDissolve: 0
- _EnableSplitToning: 0
- _EnableSqueeze: 0
- _EnableSquish: 0
- _EnableStrongTint: 0
- _EnableTextureLayer1: 0
- _EnableTextureLayer2: 0
- _EnableUVDistort: 0
- _EnableUVRotate: 0
- _EnableUVScale: 0
- _EnableUVScroll: 0
- _EnableVibrate: 0
- _EnableWiggle: 0
- _EnableWind: 0
- _EnableWorldTiling: 0
- _EnchantedBrightness: 1
- _EnchantedContrast: 0.5
- _EnchantedFade: 1
- _EnchantedLerpToggle: 0
- _EnchantedRainbowDensity: 0.5
- _EnchantedRainbowSaturation: 0.8
- _EnchantedRainbowSpeed: 0.5
- _EnchantedRainbowToggle: 0
- _EnchantedReduce: 0
- _FadingFade: 1
- _FadingNoiseFactor: 0.2
- _FadingWidth: 0.3
- _FlameBrightness: 10
- _FlameNoiseFactor: 2.5
- _FlameNoiseHeightFactor: 1.5
- _FlameRadius: 0.2
- _FlameSmooth: 2
- _FrozenContrast: 2
- _FrozenFade: 1
- _FrozenHighlightContrast: 2
- _FrozenHighlightDensity: 1
- _FrozenSnowContrast: 1
- _FrozenSnowDensity: 0.25
- _FullAlphaDissolveFade: 0.5
- _FullAlphaDissolveWidth: 0.5
- _FullDistortionFade: 1
- _FullGlowDissolveFade: 0.5
- _FullGlowDissolveWidth: 0.5
- _GaussianBlurFade: 1
- _GaussianBlurOffset: 0.5
- _GlitchBrightness: 4
- _GlitchFade: 1
- _GlitchHueSpeed: 1
- _GlitchMaskMin: 0.4
- _HalftoneFade: 1
- _HalftoneFadeWidth: 1.5
- _HalftoneInvert: 0
- _HalftoneTiling: 4
- _HologramContrast: 1
- _HologramDistortionDensity: 0.5
- _HologramDistortionOffset: 0.5
- _HologramDistortionScale: 10
- _HologramDistortionSpeed: 2
- _HologramFade: 1
- _HologramLineFrequency: 500
- _HologramLineGap: 3
- _HologramLineSpeed: 0.01
- _HologramMinAlpha: 0.2
- _Hue: 0
- _InkSpreadContrast: 2
- _InkSpreadDistance: 3
- _InkSpreadFade: 1
- _InkSpreadNoiseFactor: 0.5
- _InkSpreadWidth: 0.2
- _InnerOutlineDistortionToggle: 0
- _InnerOutlineFade: 1
- _InnerOutlineOutlineOnlyToggle: 0
- _InnerOutlineTextureToggle: 0
- _InnerOutlineWidth: 0.01
- _MetalContrast: 2
- _MetalFade: 1
- _MetalHighlightContrast: 2
- _MetalHighlightDensity: 1
- _MetalMaskToggle: 0
- _NegativeFade: 1
- _NormalIntensity: 1
- _OuterOutlineDistortionToggle: 0
- _OuterOutlineFade: 1
- _OuterOutlineOutlineOnlyToggle: 0
- _OuterOutlineTextureToggle: 0
- _OuterOutlineWidth: 0.01
- _PingPongGlowContrast: 1
- _PingPongGlowFade: 1
- _PingPongGlowFrequency: 3
- _PixelOutlineFade: 1
- _PixelOutlineOutlineOnlyToggle: 0
- _PixelOutlineTextureToggle: 0
- _PixelOutlineWidth: 1
- _PixelPerfectSpace: 0
- _PixelPerfectUV: 0
- _PixelateFade: 1
- _PixelatePixelDensity: 16
- _PixelatePixelsPerUnit: 100
- _PixelsPerUnit: 100
- _PoisonDensity: 3
- _PoisonFade: 1
- _PoisonNoiseBrightness: 2
- _PoisonRecolorFactor: 0.5
- _PoisonShiftSpeed: 0.2
- _RainbowBrightness: 2
- _RainbowContrast: 1
- _RainbowDensity: 0.5
- _RainbowFade: 1
- _RainbowNoiseFactor: 0.2
- _RainbowSaturation: 1
- _RainbowSpeed: 1
- _RecolorRGBFade: 1
- _RecolorRGBTextureToggle: 0
- _RecolorRGBYCPFade: 1
- _RecolorRGBYCPTextureToggle: 0
- _RectHeight: 100
- _RectWidth: 100
- _Saturation: 1
- _ScreenTilingPixelsPerUnit: 100
- _ScreenWidthUnits: 10
- _ShaderFading: 0
- _ShaderSpace: 0
- _ShadowFade: 1
- _SharpenFactor: 4
- _SharpenFade: 1
- _SharpenOffset: 2
- _ShiftHueSpeed: 0.5
- _ShiftingBrightness: 1
- _ShiftingContrast: 0.5
- _ShiftingDensity: 1.5
- _ShiftingFade: 1
- _ShiftingRainbowToggle: 0
- _ShiftingSaturation: 0.8
- _ShiftingSpeed: 0.5
- _ShineContrast: 2
- _ShineFade: 1
- _ShineFrequency: 0.3
- _ShineMaskToggle: 0
- _ShineRotation: 276
- _ShineSaturation: 0.5
- _ShineSmooth: 1
- _ShineSpeed: 5
- _ShineWidth: 0.1
- _SineGlowContrast: 1
- _SineGlowFade: 1
- _SineGlowFrequency: 4
- _SineGlowMaskToggle: 0
- _SineGlowMax: 1
- _SineGlowMin: 0
- _SineMoveFade: 1
- _SineRotateAngle: 15
- _SineRotateFade: 1
- _SineRotateFrequency: 1
- _SineScaleFrequency: 2
- _SmokeAlpha: 1
- _SmokeDarkEdge: 1
- _SmokeNoiseFactor: 0.4
- _SmokeNoiseScale: 0.5
- _SmokeSmoothness: 1
- _SmokeVertexSeed: 0
- _SourceAlphaDissolveFade: 1
- _SourceAlphaDissolveInvert: 0
- _SourceAlphaDissolveNoiseFactor: 0.2
- _SourceAlphaDissolveWidth: 0.2
- _SourceGlowDissolveFade: 1
- _SourceGlowDissolveInvert: 0
- _SourceGlowDissolveNoiseFactor: 0.2
- _SourceGlowDissolveWidth: 0.1
- _SplitToningBalance: 1
- _SplitToningContrast: 1
- _SplitToningFade: 1
- _SplitToningShift: 0
- _SpriteSheetFix: 0
- _SqueezeFade: 1
- _SqueezePower: 1
- _SquishFade: 1
- _SquishFlip: 0
- _SquishSquish: 0.1
- _SquishStretch: 0.1
- _StrongTintContrast: 0
- _StrongTintContrastToggle: 0
- _StrongTintFade: 1
- _StrongTintMaskToggle: 0
- _TextureLayer1Columns: 3
- _TextureLayer1Contrast: 1
- _TextureLayer1ContrastToggle: 0
- _TextureLayer1EdgeClip: 0.005
- _TextureLayer1Fade: 1
- _TextureLayer1Rows: 3
- _TextureLayer1ScrollToggle: 0
- _TextureLayer1SheetToggle: 1
- _TextureLayer1Speed: 20
- _TextureLayer1StartFrame: 0
- _TextureLayer2Columns: 3
- _TextureLayer2Contrast: 1
- _TextureLayer2ContrastToggle: 0
- _TextureLayer2EdgeClip: 0.005
- _TextureLayer2Fade: 1
- _TextureLayer2Rows: 3
- _TextureLayer2ScrollToggle: 0
- _TextureLayer2SheetToggle: 1
- _TextureLayer2Speed: 20
- _TextureLayer2StartFrame: 0
- _TilingFix: 0
- _TimeFPS: 5
- _TimeFrequency: 2
- _TimeRange: 0.5
- _TimeSpeed: 1
- _TimeValue: 0
- _ToggleCustomTime: 0
- _ToggleTimeFPS: 0
- _ToggleTimeFrequency: 0
- _ToggleTimeSpeed: 0
- _ToggleUnscaledTime: 0
- _UVDistortFade: 1
- _UVDistortMaskToggle: 0
- _UVRotateSpeed: 1
- _VertexTintFirst: 0
- _VibrateFade: 1
- _VibrateFrequency: 100
- _VibrateOffset: 0.04
- _VibrateRotation: 4
- _WiggleFade: 1
- _WiggleFixedGroundToggle: 0
- _WiggleFrequency: 2
- _WiggleOffset: 0.02
- _WiggleSpeed: 2
- _WindFlip: 0
- _WindHighQualityNoise: 0
- _WindIsParallax: 0
- _WindLocalWind: 0
- _WindMaxIntensity: 0.4
- _WindMaxRotation: 2
- _WindMinIntensity: -0.4
- _WindNoiseScale: 0.1
- _WindNoiseSpeed: 1
- _WindRotation: 0
- _WindRotationWindFactor: 1
- _WindSquishFactor: 0.3
- _WindSquishWindFactor: 0
- _WindXPosition: 0
- _WorldTilingPixelsPerUnit: 100
m_Colors:
- _AddColorColor: {r: 2.996078, g: 0, b: 0, a: 0}
- _AlphaTintColor: {r: 95.87451, g: 5.019608, b: 95.87451, a: 0}
- _BlackTintColor: {r: 0, g: 0, b: 1, a: 0}
- _BurnEdgeColor: {r: 11.98431, g: 1.129412, b: 0.1254902, a: 0}
- _BurnEdgeNoiseScale: {r: 0.3, g: 0.3, b: 0, a: 0}
- _BurnInsideColor: {r: 0.75, g: 0.5625, b: 0.525, a: 0}
- _BurnInsideNoiseColor: {r: 3084.047, g: 257.0039, b: 0, a: 0}
- _BurnInsideNoiseScale: {r: 0.5, g: 0.5, b: 0, a: 0}
- _BurnPosition: {r: 0, g: 5, b: 0, a: 0}
- _BurnSwirlNoiseScale: {r: 0.1, g: 0.1, b: 0, a: 0}
- _CamouflageBaseColor: {r: 0.7450981, g: 0.7254902, b: 0.5686274, a: 0}
- _CamouflageColorA: {r: 0.62745106, g: 0.5882353, b: 0.43137258, a: 0}
- _CamouflageColorB: {r: 0.47058815, g: 0.43137258, b: 0.31372547, a: 0}
- _CamouflageDistortionIntensity: {r: 0.1, g: 0.1, b: 0, a: 0}
- _CamouflageDistortionScale: {r: 0.5, g: 0.5, b: 0, a: 0}
- _CamouflageDistortionSpeed: {r: 0.1, g: 0.1, b: 0, a: 0}
- _CamouflageNoiseScaleA: {r: 0.25, g: 0.25, b: 0, a: 0}
- _CamouflageNoiseScaleB: {r: 0.25, g: 0.25, b: 0, a: 0}
- _ColorReplaceFromColor: {r: 0, g: 0, b: 0, a: 0}
- _ColorReplaceToColor: {r: 0, g: 0, b: 0.2, a: 0}
- _CustomFadeNoiseScale: {r: 1, g: 1, b: 0, a: 0}
- _DirectionalAlphaFadeNoiseScale: {r: 0.3, g: 0.3, b: 0, a: 0}
- _DirectionalDistortionDistortion: {r: 0, g: 0.1, b: 0, a: 0}
- _DirectionalDistortionDistortionScale: {r: 1, g: 1, b: 0, a: 0}
- _DirectionalDistortionNoiseScale: {r: 0.4, g: 0.4, b: 0, a: 0}
- _DirectionalGlowFadeEdgeColor: {r: 11.98431, g: 0.6901961, b: 0.6901961, a: 0}
- _DirectionalGlowFadeNoiseScale: {r: 0.4, g: 0.4, b: 0, a: 0}
- _EmissionColor: {r: 1, g: 1, b: 1, a: 1}
- _EnchantedHighColor: {r: 0, g: 0.7098798, b: 4.237095, a: 0}
- _EnchantedLowColor: {r: 2.996078, g: 0, b: 0, a: 0}
- _EnchantedScale: {r: 0.1, g: 0.1, b: 0, a: 0}
- _EnchantedSpeed: {r: 0, g: 1, b: 0, a: 0}
- _FadingNoiseScale: {r: 0.2, g: 0.2, b: 0, a: 0}
- _FadingPosition: {r: 0, g: 0, b: 0, a: 0}
- _FlameNoiseScale: {r: 1.2, g: 0.8, b: 0, a: 0}
- _FlameSpeed: {r: 0, g: -0.5, b: 0, a: 0}
- _FrozenHighlightColor: {r: 1.797647, g: 4.604501, b: 5.992157, a: 1}
- _FrozenHighlightDistortion: {r: 0.5, g: 0.5, b: 0, a: 0}
- _FrozenHighlightDistortionScale: {r: 0.2, g: 0.2, b: 0, a: 0}
- _FrozenHighlightDistortionSpeed: {r: -0.05, g: -0.05, b: 0, a: 0}
- _FrozenHighlightScale: {r: 0.2, g: 0.2, b: 0, a: 0}
- _FrozenHighlightSpeed: {r: 0.1, g: 0.1, b: 0, a: 0}
- _FrozenSnowColor: {r: 1.123529, g: 1.373203, b: 1.498039, a: 0}
- _FrozenSnowScale: {r: 0.1, g: 0.1, b: 0, a: 0}
- _FrozenTint: {r: 1.819608, g: 4.611765, b: 5.992157, a: 0}
- _FullAlphaDissolveNoiseScale: {r: 0.1, g: 0.1, b: 0, a: 0}
- _FullDistortionDistortion: {r: 0.2, g: 0.2, b: 0, a: 0}
- _FullDistortionNoiseScale: {r: 0.5, g: 0.5, b: 0, a: 0}
- _FullGlowDissolveEdgeColor: {r: 11.98431, g: 0.627451, b: 0.627451, a: 0}
- _FullGlowDissolveNoiseScale: {r: 0.1, g: 0.1, b: 0, a: 0}
- _GlitchDistortion: {r: 0.1, g: 0, b: 0, a: 0}
- _GlitchDistortionScale: {r: 0, g: 3, b: 0, a: 0}
- _GlitchDistortionSpeed: {r: 0, g: 1, b: 0, a: 0}
- _GlitchMaskScale: {r: 0, g: 0.2, b: 0, a: 0}
- _GlitchMaskSpeed: {r: 0, g: 4, b: 0, a: 0}
- _GlitchNoiseScale: {r: 0, g: 3, b: 0, a: 0}
- _GlitchNoiseSpeed: {r: 0, g: 1, b: 0, a: 0}
- _HalftonePosition: {r: 0, g: 0, b: 0, a: 0}
- _HologramTint: {r: 0.3137255, g: 1.662745, b: 2.996078, a: 1}
- _InkSpreadColor: {r: 8.47419, g: 5.013525, b: 0.08873497, a: 0}
- _InkSpreadNoiseScale: {r: 0.4, g: 0.4, b: 0, a: 0}
- _InkSpreadPosition: {r: 0.5, g: -1, b: 0, a: 0}
- _InnerOutlineColor: {r: 15.999997, g: 15.999997, b: 15.999997, a: 1}
- _InnerOutlineDistortionIntensity: {r: 0.01, g: 0.01, b: 0, a: 0}
- _InnerOutlineNoiseScale: {r: 4, g: 4, b: 0, a: 0}
- _InnerOutlineNoiseSpeed: {r: 0, g: 0.1, b: 0, a: 0}
- _InnerOutlineTextureSpeed: {r: 0.5, g: 0, b: 0, a: 0}
- _MetalColor: {r: 5.992157, g: 3.639216, b: 0.3137255, a: 1}
- _MetalHighlightColor: {r: 5.992157, g: 3.796078, b: 0.6588235, a: 1}
- _MetalNoiseDistortion: {r: 0.5, g: 0.5, b: 0, a: 0}
- _MetalNoiseDistortionScale: {r: 0.2, g: 0.2, b: 0, a: 0}
- _MetalNoiseDistortionSpeed: {r: -0.05, g: -0.05, b: 0, a: 0}
- _MetalNoiseScale: {r: 0.25, g: 0.25, b: 0, a: 0}
- _MetalNoiseSpeed: {r: 0.05, g: 0.05, b: 0, a: 0}
- _OuterOutlineColor: {r: 1, g: 1, b: 1, a: 1}
- _OuterOutlineDistortionIntensity: {r: 0.01, g: 0.01, b: 0, a: 0}
- _OuterOutlineNoiseScale: {r: 4, g: 4, b: 0, a: 0}
- _OuterOutlineNoiseSpeed: {r: 0, g: 0.1, b: 0, a: 0}
- _OuterOutlineTextureSpeed: {r: 0.5, g: 0, b: 0, a: 0}
- _PingPongGlowFrom: {r: 5.992157, g: 0.1882353, b: 0.1882353, a: 0}
- _PingPongGlowTo: {r: 0.1882353, g: 0.1882353, b: 5.992157, a: 0}
- _PixelOutlineColor: {r: 0, g: 0, b: 0, a: 1}
- _PixelOutlineTextureSpeed: {r: 0.5, g: 0, b: 0, a: 0}
- _PoisonColor: {r: 0.3137255, g: 2.996078, b: 0.3137255, a: 0}
- _PoisonNoiseScale: {r: 0.2, g: 0.2, b: 0, a: 0}
- _PoisonNoiseSpeed: {r: 0, g: -0.2, b: 0, a: 0}
- _RainbowCenter: {r: 0, g: 0, b: 0, a: 0}
- _RainbowNoiseScale: {r: 0.2, g: 0.2, b: 0, a: 0}
- _RecolorRGBBlueTint: {r: 1, g: 1, b: 1, a: 0.5019608}
- _RecolorRGBGreenTint: {r: 1, g: 1, b: 1, a: 0.5019608}
- _RecolorRGBRedTint: {r: 1, g: 1, b: 1, a: 0.5019608}
- _RecolorRGBYCPBlueTint: {r: 1, g: 1, b: 1, a: 0.5019608}
- _RecolorRGBYCPCyanTint: {r: 1, g: 1, b: 1, a: 0.5019608}
- _RecolorRGBYCPGreenTint: {r: 1, g: 1, b: 1, a: 0.5019608}
- _RecolorRGBYCPPurpleTint: {r: 1, g: 1, b: 1, a: 0.5019608}
- _RecolorRGBYCPRedTint: {r: 1, g: 1, b: 1, a: 0.5019608}
- _RecolorRGBYCPYellowTint: {r: 1, g: 1, b: 1, a: 0.5019608}
- _ScreenTilingOffset: {r: 0, g: 0, b: 0, a: 0}
- _ScreenTilingScale: {r: 1, g: 1, b: 0, a: 0}
- _ShadowColor: {r: 0, g: 0, b: 0, a: 0}
- _ShadowOffset: {r: 0.05, g: -0.05, b: 0, a: 0}
- _ShiftingColorA: {r: 1.498039, g: 0, b: 0, a: 0}
- _ShiftingColorB: {r: 1.498039, g: 0.7490196, b: 0, a: 0}
- _ShineColor: {r: 11.98431, g: 11.98431, b: 11.98431, a: 0}
- _SineGlowColor: {r: 0, g: 2.007843, b: 2.996078, a: 0}
- _SineMoveFrequency: {r: 1, g: 1, b: 0, a: 0}
- _SineMoveOffset: {r: 0, g: 0.5, b: 0, a: 0}
- _SineRotatePivot: {r: 0.5, g: 0.5, b: 0, a: 0}
- _SineScaleFactor: {r: 0.2, g: 0.2, b: 0, a: 0}
- _SourceAlphaDissolveNoiseScale: {r: 0.3, g: 0.3, b: 0, a: 0}
- _SourceAlphaDissolvePosition: {r: 0, g: 0, b: 0, a: 0}
- _SourceGlowDissolveEdgeColor: {r: 11.98431, g: 0.627451, b: 0.627451, a: 0}
- _SourceGlowDissolveNoiseScale: {r: 0.3, g: 0.3, b: 0, a: 0}
- _SourceGlowDissolvePosition: {r: 0, g: 0, b: 0, a: 0}
- _SplitToningHighlightsColor: {r: 1, g: 0.1, b: 0.1, a: 0}
- _SplitToningShadowsColor: {r: 0.1, g: 0.4000002, b: 1, a: 0}
- _SpriteSheetRect: {r: 0, g: 0, b: 1, a: 1}
- _SqueezeCenter: {r: 0.5, g: 0.5, b: 0, a: 0}
- _SqueezeScale: {r: 2, g: 0, b: 0, a: 0}
- _StrongTintTint: {r: 1, g: 1, b: 1, a: 1}
- _TextureLayer1Color: {r: 0.4494117, g: 1.298301, b: 2.996079, a: 1}
- _TextureLayer1Offset: {r: 0, g: 0, b: 0, a: 0}
- _TextureLayer1Scale: {r: 1, g: 1, b: 0, a: 0}
- _TextureLayer1ScrollSpeed: {r: 0, g: 1, b: 0, a: 0}
- _TextureLayer2Color: {r: 0.4494117, g: 1.298301, b: 2.996079, a: 1}
- _TextureLayer2Offset: {r: 0, g: 0, b: 0, a: 0}
- _TextureLayer2Scale: {r: 1, g: 1, b: 0, a: 0}
- _TextureLayer2ScrollSpeed: {r: 0, g: 1, b: 0, a: 0}
- _UVDistortFrom: {r: -0.02, g: -0.02, b: 0, a: 0}
- _UVDistortNoiseScale: {r: 0.1, g: 0.1, b: 0, a: 0}
- _UVDistortSpeed: {r: 2, g: 2, b: 0, a: 0}
- _UVDistortTo: {r: 0.02, g: 0.02, b: 0, a: 0}
- _UVRotatePivot: {r: 0.5, g: 0.5, b: 0, a: 0}
- _UVScalePivot: {r: 0.5, g: 0.5, b: 0, a: 0}
- _UVScaleScale: {r: 1, g: 1, b: 0, a: 0}
- _UVScrollSpeed: {r: 0.2, g: 0, b: 0, a: 0}
- _WorldTilingOffset: {r: 0, g: 0, b: 0, a: 0}
- _WorldTilingScale: {r: 1, g: 1, b: 0, a: 0}
m_BuildTextureStacks: []
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ed23ebedc9a6ba6438b415c33c5af650
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,389 @@
Shader "AibisDream/SpriteInteractionHint"
{
Properties
{
[PerRendererData] _MainTex("Sprite Texture", 2D) = "white" {}
_Color("Tint", Color) = (1,1,1,1)
[Header(Edge)]
[HDR] _OutlineColor("Hint Color", Color) = (1.0, 1.0, 1.0, 1.0)
_OutlineWidth("Edge Width (px)", Range(0.5, 4)) = 1.0
_EdgeSoftness("Edge Softness", Range(0, 1)) = 0.05
_InnerEdgeBias("Inner Edge Bias", Range(0, 1)) = 0.9
_AlphaThreshold("Alpha Threshold", Range(0, 1)) = 0.1
[Header(Pulse)]
_PulseSpeed("Pulse Speed", Float) = 2.5
_PulseMin("Pulse Min Brightness", Range(0, 1)) = 0.45
_PulseSteps("Pulse Steps", Range(1, 8)) = 4
_FillPulseStrength("Edge Glow Strength", Range(0, 1)) = 0.12
[Header(Sweep)]
_SweepStrength("Sweep Strength", Range(0, 1)) = 0.25
_SweepWidth("Sweep Width", Range(0.02, 0.5)) = 0.14
_SweepDuration("Sweep Duration", Float) = 0.55
_SweepInterval("Sweep Interval", Float) = 1.8
_SweepAngle("Sweep Angle", Range(-1, 1)) = 0.35
[Header(Control)]
_Intensity("Intensity (0=off)", Range(0, 1)) = 1.0
}
SubShader
{
Tags
{
"Queue" = "Transparent"
"RenderType" = "Transparent"
"RenderPipeline" = "UniversalPipeline"
"IgnoreProjector" = "True"
"CanUseSpriteAtlas" = "True"
}
Cull Off
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
Pass
{
Name "SpriteInteractionHint"
Tags { "LightMode" = "Universal2D" }
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 3.0
#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;
};
TEXTURE2D(_MainTex);
SAMPLER(sampler_MainTex);
CBUFFER_START(UnityPerMaterial)
float4 _MainTex_ST;
float4 _MainTex_TexelSize;
float4 _Color;
float4 _OutlineColor;
float _OutlineWidth;
float _EdgeSoftness;
float _InnerEdgeBias;
float _AlphaThreshold;
float _PulseSpeed;
float _PulseMin;
float _PulseSteps;
float _FillPulseStrength;
float _SweepStrength;
float _SweepWidth;
float _SweepDuration;
float _SweepInterval;
float _SweepAngle;
float _Intensity;
CBUFFER_END
float GetPulse(float minBrightness, float speed, float steps)
{
float pulse = sin(_Time.y * speed) * 0.5 + 0.5;
float discreteSteps = max(1.0, round(steps));
if (discreteSteps > 1.0)
{
pulse = round(pulse * (discreteSteps - 1.0)) / (discreteSteps - 1.0);
}
return lerp(minBrightness, 1.0, pulse);
}
float GetEdgeMask(float rawValue, float softness)
{
float hardMask = step(0.001, rawValue);
float softMask = smoothstep(0.001, 0.45, rawValue);
return lerp(hardMask, softMask, softness);
}
float GetBinaryAlpha(float alpha, float threshold)
{
return step(threshold, alpha);
}
float GetSweepMask(float2 uv, float strength, float width, float duration, float interval, float angle)
{
float cycleLength = max(0.01, duration + interval);
float cycleTime = fmod(_Time.y, cycleLength);
float active = step(cycleTime, duration);
if (active < 0.5)
{
return 0.0;
}
float sweepProgress = saturate(cycleTime / max(0.01, duration));
float2 sweepDir = normalize(float2(1.0, angle));
float sweepCoord = dot(uv - 0.5, sweepDir) + 0.5;
float band = 1.0 - smoothstep(0.0, width, abs(sweepCoord - sweepProgress));
return band * strength;
}
Varyings vert(Attributes input)
{
Varyings output;
output.positionHCS = TransformObjectToHClip(input.positionOS.xyz);
output.uv = TRANSFORM_TEX(input.uv, _MainTex);
output.color = input.color * _Color;
return output;
}
half4 frag(Varyings input) : SV_Target
{
float2 uv = input.uv;
half4 spriteColor = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv);
spriteColor *= input.color;
float currentAlpha = spriteColor.a;
if (_Intensity < 0.001)
return spriteColor;
float2 texel = _MainTex_TexelSize.xy * _OutlineWidth;
// 8-direction neighbor alpha sampling
float a1 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv + float2( texel.x, 0 )).a;
float a2 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv + float2(-texel.x, 0 )).a;
float a3 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv + float2( 0, texel.y )).a;
float a4 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv + float2( 0, -texel.y )).a;
float a5 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv + float2( texel.x, texel.y )).a;
float a6 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv + float2(-texel.x, texel.y )).a;
float a7 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv + float2( texel.x, -texel.y )).a;
float a8 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv + float2(-texel.x, -texel.y )).a;
float currentMask = GetBinaryAlpha(currentAlpha, _AlphaThreshold);
float b1 = GetBinaryAlpha(a1, _AlphaThreshold);
float b2 = GetBinaryAlpha(a2, _AlphaThreshold);
float b3 = GetBinaryAlpha(a3, _AlphaThreshold);
float b4 = GetBinaryAlpha(a4, _AlphaThreshold);
float b5 = GetBinaryAlpha(a5, _AlphaThreshold);
float b6 = GetBinaryAlpha(a6, _AlphaThreshold);
float b7 = GetBinaryAlpha(a7, _AlphaThreshold);
float b8 = GetBinaryAlpha(a8, _AlphaThreshold);
float maxNeighbor = max(max(max(b1, b2), max(b3, b4)),
max(max(b5, b6), max(b7, b8)));
float minNeighbor = min(min(min(b1, b2), min(b3, b4)),
min(min(b5, b6), min(b7, b8)));
float maxNeighborAlpha = max(max(max(a1, a2), max(a3, a4)),
max(max(a5, a6), max(a7, a8)));
float outerEdgeRaw = saturate(maxNeighbor - currentMask);
float innerEdgeRaw = saturate(currentMask - minNeighbor);
float outerEdgeMask = GetEdgeMask(outerEdgeRaw, _EdgeSoftness);
float innerEdgeMask = GetEdgeMask(innerEdgeRaw, _EdgeSoftness * 0.6);
float pulse = GetPulse(_PulseMin, _PulseSpeed, _PulseSteps);
float pulseStrength = pulse * _Intensity;
float sweepMask = GetSweepMask(uv, _SweepStrength, _SweepWidth, _SweepDuration, _SweepInterval, _SweepAngle) * _Intensity;
// Use silhouette-driven masks so sprites with different interior colors behave more consistently.
float innerSupport = innerEdgeMask * _InnerEdgeBias * 0.1;
float edgeMask = saturate(max(outerEdgeMask, innerSupport));
float edgeGlowMask = outerEdgeMask * smoothstep(_AlphaThreshold, 1.0, maxNeighborAlpha) * _FillPulseStrength;
float sweepBodyMask = currentMask * sweepMask;
float edgeTint = saturate(edgeMask * pulseStrength);
float glowTint = edgeGlowMask * pulseStrength;
float bodyTint = saturate(sweepBodyMask);
half3 edgeTargetColor = _OutlineColor.rgb;
half3 sweepTargetColor = lerp(spriteColor.rgb, _OutlineColor.rgb, 0.75);
half3 outColor = lerp(spriteColor.rgb, edgeTargetColor, edgeTint);
outColor += _OutlineColor.rgb * glowTint * 0.25;
outColor = lerp(outColor, sweepTargetColor, bodyTint);
float outAlpha = saturate(currentAlpha + (outerEdgeMask * 0.18 + glowTint + bodyTint * 0.12) * _OutlineColor.a);
return half4(outColor, outAlpha);
}
ENDHLSL
}
Pass
{
Name "SpriteInteractionHintUnlit"
Tags { "LightMode" = "SRPDefaultUnlit" }
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 3.0
#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;
};
TEXTURE2D(_MainTex);
SAMPLER(sampler_MainTex);
CBUFFER_START(UnityPerMaterial)
float4 _MainTex_ST;
float4 _MainTex_TexelSize;
float4 _Color;
float4 _OutlineColor;
float _OutlineWidth;
float _EdgeSoftness;
float _InnerEdgeBias;
float _AlphaThreshold;
float _PulseSpeed;
float _PulseMin;
float _PulseSteps;
float _FillPulseStrength;
float _SweepStrength;
float _SweepWidth;
float _SweepDuration;
float _SweepInterval;
float _SweepAngle;
float _Intensity;
CBUFFER_END
float GetPulse(float minBrightness, float speed, float steps)
{
float pulse = sin(_Time.y * speed) * 0.5 + 0.5;
float discreteSteps = max(1.0, round(steps));
if (discreteSteps > 1.0)
{
pulse = round(pulse * (discreteSteps - 1.0)) / (discreteSteps - 1.0);
}
return lerp(minBrightness, 1.0, pulse);
}
float GetEdgeMask(float rawValue, float softness)
{
float hardMask = step(0.001, rawValue);
float softMask = smoothstep(0.001, 0.45, rawValue);
return lerp(hardMask, softMask, softness);
}
float GetBinaryAlpha(float alpha, float threshold)
{
return step(threshold, alpha);
}
float GetSweepMask(float2 uv, float strength, float width, float duration, float interval, float angle)
{
float cycleLength = max(0.01, duration + interval);
float cycleTime = fmod(_Time.y, cycleLength);
float active = step(cycleTime, duration);
if (active < 0.5)
{
return 0.0;
}
float sweepProgress = saturate(cycleTime / max(0.01, duration));
float2 sweepDir = normalize(float2(1.0, angle));
float sweepCoord = dot(uv - 0.5, sweepDir) + 0.5;
float band = 1.0 - smoothstep(0.0, width, abs(sweepCoord - sweepProgress));
return band * strength;
}
Varyings vert(Attributes input)
{
Varyings output;
output.positionHCS = TransformObjectToHClip(input.positionOS.xyz);
output.uv = TRANSFORM_TEX(input.uv, _MainTex);
output.color = input.color * _Color;
return output;
}
half4 frag(Varyings input) : SV_Target
{
float2 uv = input.uv;
half4 spriteColor = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv);
spriteColor *= input.color;
float currentAlpha = spriteColor.a;
if (_Intensity < 0.001)
return spriteColor;
float2 texel = _MainTex_TexelSize.xy * _OutlineWidth;
float a1 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv + float2( texel.x, 0 )).a;
float a2 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv + float2(-texel.x, 0 )).a;
float a3 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv + float2( 0, texel.y )).a;
float a4 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv + float2( 0, -texel.y )).a;
float a5 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv + float2( texel.x, texel.y )).a;
float a6 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv + float2(-texel.x, texel.y )).a;
float a7 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv + float2( texel.x, -texel.y )).a;
float a8 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv + float2(-texel.x, -texel.y )).a;
float currentMask = GetBinaryAlpha(currentAlpha, _AlphaThreshold);
float b1 = GetBinaryAlpha(a1, _AlphaThreshold);
float b2 = GetBinaryAlpha(a2, _AlphaThreshold);
float b3 = GetBinaryAlpha(a3, _AlphaThreshold);
float b4 = GetBinaryAlpha(a4, _AlphaThreshold);
float b5 = GetBinaryAlpha(a5, _AlphaThreshold);
float b6 = GetBinaryAlpha(a6, _AlphaThreshold);
float b7 = GetBinaryAlpha(a7, _AlphaThreshold);
float b8 = GetBinaryAlpha(a8, _AlphaThreshold);
float maxNeighbor = max(max(max(b1, b2), max(b3, b4)),
max(max(b5, b6), max(b7, b8)));
float minNeighbor = min(min(min(b1, b2), min(b3, b4)),
min(min(b5, b6), min(b7, b8)));
float maxNeighborAlpha = max(max(max(a1, a2), max(a3, a4)),
max(max(a5, a6), max(a7, a8)));
float outerEdgeRaw = saturate(maxNeighbor - currentMask);
float innerEdgeRaw = saturate(currentMask - minNeighbor);
float outerEdgeMask = GetEdgeMask(outerEdgeRaw, _EdgeSoftness);
float innerEdgeMask = GetEdgeMask(innerEdgeRaw, _EdgeSoftness * 0.6);
float pulse = GetPulse(_PulseMin, _PulseSpeed, _PulseSteps);
float pulseStrength = pulse * _Intensity;
float sweepMask = GetSweepMask(uv, _SweepStrength, _SweepWidth, _SweepDuration, _SweepInterval, _SweepAngle) * _Intensity;
float innerSupport = innerEdgeMask * _InnerEdgeBias * 0.1;
float edgeMask = saturate(max(outerEdgeMask, innerSupport));
float edgeGlowMask = outerEdgeMask * smoothstep(_AlphaThreshold, 1.0, maxNeighborAlpha) * _FillPulseStrength;
float sweepBodyMask = currentMask * sweepMask;
float edgeTint = saturate(edgeMask * pulseStrength);
float glowTint = edgeGlowMask * pulseStrength;
float bodyTint = saturate(sweepBodyMask);
half3 edgeTargetColor = _OutlineColor.rgb;
half3 sweepTargetColor = lerp(spriteColor.rgb, _OutlineColor.rgb, 0.75);
half3 outColor = lerp(spriteColor.rgb, edgeTargetColor, edgeTint);
outColor += _OutlineColor.rgb * glowTint * 0.25;
outColor = lerp(outColor, sweepTargetColor, bodyTint);
float outAlpha = saturate(currentAlpha + (outerEdgeMask * 0.18 + glowTint + bodyTint * 0.12) * _OutlineColor.a);
return half4(outColor, outAlpha);
}
ENDHLSL
}
}
Fallback "Sprites/Default"
}
@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: a34fe9b6eef27da488f084be707ba0e9
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
userData:
assetBundleName:
assetBundleVariant:
@@ -109,7 +109,7 @@ colorID: 1
<<switch_fix_system_to BodyModule Head>>
<<switch_fix_system_to Expression>>
me: 寻找log #line:07d4d6b
<<start_expression "哈哈|嘿嘿|呵呵" "我很害怕" "LOG1梳理完成">>
<<start_expression "哈哈|嘿嘿|呵呵" "我就是个笑话" "LOG1梳理完成" 16>>
<<wait 1>>
me: 释放log #line:0a96ef0
@@ -82,7 +82,7 @@ colorID: 7
position: 550,2280
---
// 桥接:KnobController 旋钮失败时跳入,分发到 Stage3 旋钮调节失败(内容已合并)
<<jump 旋钮调节失败>>
<<jump 旋钮调节>>
===
// ═══════════════════════════════════════════════════════════════
@@ -82,9 +82,6 @@ EmoModule: 已与情绪模块建立连接! #line:0b19318
me: 难道说问题不在于这个信号的源头…而在于它的处理过程? #line:08eb820
me: 可是均衡器刚才查下来也没有问题啊。一定是漏了什么…让我捋捋。 #line:074c7b2
me: 嗯…有必要在语义均衡器进行一个步进模式。 #line:09151b5
<<hide_emotion_wave 1>>
<<ModuleHightLight Emo false>>
<<ModuleHightLight sale true>>
<<jump 结束Stage2>>
<<endif>>
->结束 #line:006eb35
@@ -283,7 +280,7 @@ SpeakerModule: 已与表达模块建立连接! #line:027b73c
<<complete_task "line:0f2a6c8">>
Task: 检查滤波器 #line:03f59d6
<<ModuleHightLight Speak false>>
<<ModuleHightLight sale true>>
<<ModuleHightLight Sale true>>
<<if $speakerChecked == false>>
<<set $PlugCount=$PlugCount+1>>
<<set $speakerChecked = true>>
@@ -294,7 +291,8 @@ SpeakerModule: 已与表达模块建立连接! #line:027b73c
SpeakerModule:正在读取RAM... #line:0d709ee
<<wait 0.3>>
// 显示报错弹窗效果 - 体现RAM堆积导致系统卡死
<<open_warning_window "[ERROR] 表达模块RAM溢出">>
// <<open_warning_window "[ERROR] 表达模块RAM溢出">>
Error: 表达模块RAM溢出。
hs: 啊…我的头…好痒…… #line:08d534b
SpeakerModule:══════ 未释放log列表 ══════ #line:0ea046c
SpeakerModule:未释放log1:悲伤单元 [7年累积] #line:0d0f078
@@ -303,7 +301,8 @@ SpeakerModule: 已与表达模块建立连接! #line:027b73c
SpeakerModule:...... #line:03c9006
SpeakerModule:[警告] 积压log过多,RAM即将溢出 #line:061f0f5
SpeakerModule:[警告] 悲伤表达通道已闭锁 #line:02bdf53
<<open_warning_window "[ERROR] 系统保护性中断">>
// <<open_warning_window "[ERROR] 系统保护性中断">>
Error: 系统保护性中断。
<<clear_errors>>
me:看到了么。这7年那些被均衡器压缩掉的情绪log,其实依然存在这里。 #line:049696d
//me:只是表达被替换成了笑话,真实的情绪log却一直堆积在这里 #line:07c2eb4
@@ -398,7 +397,7 @@ SaleModule: 已与销售模块建立连接! #line:0448f12
hs: 好的医生。 #line:0b2645b
me: 总之去情绪模块查一下这个信号来源吧。 #line:035c378
<<complete_task "line:03f59d6">>
<<ModuleHightLight sale false>>
<<ModuleHightLight Sale false>>
<<ModuleHightLight Emo true>>
<<hide_emotion_wave 1>>
Task: 检查情绪模块 #line:0c51688
+20 -16
View File
@@ -1,24 +1,19 @@
title: Stage3
tags: Stage 入口 滤波器深入
colorID: 2
position: 100,1200
---
// ═══════════════════════════════════════════════════════════════
// ═══════════════════════════════════════════════════════════════
// Stage3: 滤波器深入检查
// 目标:1.进入步进查看模式,显示情绪输入波形
// 2.语义合成/语言审查/语气调整 由【销售模块转动完成】监听驱动(转1/2/3)
// 3.转3检测到异常 → 进入子处理 → 先调取安装日志 → 解锁旋钮 → 监听旋钮调节
// 4.旋钮尝试代表对modify的调节(失败由 处理器单次调节失败/处理器功率调节失败 处理)
// ═══════════════════════════════════════════════════════════════
<<show_task_panel>>
hs: 好痒啊医生。 #line:05f43d7
me: 我正在给你上调试器,会有点静电。 #line:09cce79
<<DropCable>>
Task: 检查滤波器处理链路 #line:018dc78
<<ModuleHightLight sale true>>
me: 现在,看看情绪信号在均衡器链里发生了什么吧… #line:046cf9e
me: 连接【滤波器】,进入“逐帧回放”式的步进查看MARK:这一步具体是要做什么?看了之后再改文本 #line:092be7d
title: Stage3
tags: Stage 入口 滤波器深入
colorID: 2
position: 100,1200
---
<<hide_emotion_wave 1>>
<<ModuleHightLight Emo false>>
<<ModuleHightLight Sale true>>
===
@@ -33,8 +28,9 @@ position: 100,1350
// ═══════════════════════════════════════════════════════════════
<<switch_fix_system_to "Sales">>
<<switch_emotion_wave_config "normal">>
<<ModuleHightLight sale false>>
me: 逻辑效果器组的表现不错。基础波形很稳。 #line:047d241
me: 现在到情绪。 #line:047d242
me: 调入情绪信号开始步进检查吧。 #line:047d242
->步进情绪效果器组 #line:0443e38
<<enter_step_mode>>
<<jump 步进_情绪输入>>
@@ -54,6 +50,13 @@ position: 100,1500
<<switch_emotion_wave_config "normal">>
<<set_emotion_wave 0>>
<<show_emotion_wave 1.5>>
<<show_task_panel>>
hs: 好痒啊医生。 #line:05f43d7
me: 我正在给你上调试器,会有点静电。 #line:09cce79
<<DropCable>>
Task: 检查滤波器处理链路 #line:018dc78
me: 现在,看看情绪信号在均衡器链里发生了什么吧… #line:046cf9e
me: 连接【滤波器】,进入“逐帧回放”式的步进查看MARK:这一步具体是要做什么?看了之后再改文本 #line:092be7d
SaleModule: ▸情绪模块信号接收 #line:00a336c
SaleModule: 信号类型:低频波形 #line:00a336d
@@ -175,7 +178,8 @@ hs: 什么东西?医生,我听不懂。 #line:05aeda6
me: 无论如何,这就是让火山无法停止说笑话的原因。 #line:0680a40
me: 我先帮你关掉吧。 #line:066ae42
<<unlock_knob>>
<<jump 旋钮调节>>
<<open_knob_lid 0.5>>
// <<jump 旋钮调节>>
===
@@ -51,11 +51,11 @@ me: 简而言之,这些是你想说却一直没说出口的话… #line:08a128
// LOG1: 简单 - 4个目标粒子
// 主题:火山的恐惧
// 干扰词:笑话碎片(短小,2字)
// 难度:简单 - 干扰少,粒子少
// 难度:简单 - 干扰少,粒子少(非目标 16
// ═══════════════════════════════════════════════════════════════
me: 这一条log是一个焦虑情绪的记录。 #line:046ab93d
me: NOTE:或许能找合适的方式让这句话的上下文融进来 #line:05217f0
<<start_expression "哈哈|嘿嘿|呵呵" "我就是个笑话..." "LOG1梳理完成">>
<<start_expression "哈哈|嘿嘿|呵呵" "我就是个笑话" "LOG1梳理完成" 16>>
===
@@ -93,11 +93,11 @@ hs: 他们都说我是…… #line:0a8663b
// LOG2: 中等 - 6个目标粒子
// 主题:关于英里的事
// 干扰词:更多笑话碎片(3字)
// 难度:中等 - 干扰增加,粒子增加
// 难度:中等 - 干扰增加,粒子增加(非目标 28
// ═══════════════════════════════════════════════════════════════
<<wait 0.3>>
me: 这里又有一条阻塞的log,是一个恐惧情绪。 #line:03bf85f
<<start_expression "哈哈哈|嘿嘿嘿|呵呵呵|笑死了|好好笑" "不要离开我" "LOG2梳理完成">>
<<start_expression "哈哈哈|嘿嘿嘿|呵呵呵|笑死了|好好笑" "不要离开我" "LOG2梳理完成" 28>>
===
@@ -135,11 +135,11 @@ me: 对不起…火山。 #line:03686b2a
// LOG3: 困难 - 8个目标粒子
// 主题:自责与释放
// 干扰词:更多更长的笑话碎片(4-5字),干扰更强
// 难度:困难 - 最多干扰,最多粒子
// 难度:困难 - 最多干扰,最多粒子(非目标 40
// ═══════════════════════════════════════════════════════════════
<<wait 0.3>>
me: 最后一个log……这是…关于愤怒的。 #line:052abcd
<<start_expression "哈哈哈哈|笑死我了|太好笑了|绷不住了|笑不活了|真的太搞笑" "不要那样看我" "LOG疏通全部完成">>
<<start_expression "哈哈哈哈|笑死我了|太好笑了|绷不住了|笑不活了|真的太搞笑" "不要那样看我" "LOG疏通全部完成" 38>>
===
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: a3a9a798c1467f049a932a0857ee1dfb
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -100,7 +100,8 @@ namespace AibisDream
/// <param name="anxietyPhrases">干扰短句列表(笑话等,非目标粒子从中随机取字符)</param>
/// <param name="targetSentence">目标句子</param>
/// <param name="completionNodeName">完成时触发的对话节点名称(可选)</param>
public void StartSystem(List<string> anxietyPhrases, string targetSentence, string completionNodeName = null)
/// <param name="nonTargetParticleTotal">非目标候选粒子总数;&lt;0 时使用 Inspector 默认候选池大小</param>
public void StartSystem(List<string> anxietyPhrases, string targetSentence, string completionNodeName = null, int nonTargetParticleTotal = -1)
{
if (particleManager != null)
{
@@ -108,17 +109,17 @@ namespace AibisDream
var phrases = anxietyPhrases ?? defaultAnxietyPhrases;
var sentence = targetSentence ?? defaultTargetSentence;
particleManager.InitializeSystem(phrases, sentence, completionNodeName);
particleManager.InitializeSystem(phrases, sentence, completionNodeName, nonTargetParticleTotal);
}
}
/// <summary>
/// 启动粒子系统(字符串数组版本,方便 Yarn 调用)
/// </summary>
public void StartSystem(string[] anxietyPhrases, string targetSentence, string completionNodeName = null)
public void StartSystem(string[] anxietyPhrases, string targetSentence, string completionNodeName = null, int nonTargetParticleTotal = -1)
{
List<string> phrasesList = anxietyPhrases != null ? new List<string>(anxietyPhrases) : null;
StartSystem(phrasesList, targetSentence, completionNodeName);
StartSystem(phrasesList, targetSentence, completionNodeName, nonTargetParticleTotal);
}
/// <summary>
@@ -131,6 +132,16 @@ namespace AibisDream
yield return particleManager.FadeInReleaseLogIfNeeded(duration);
}
/// <summary>
/// 再次 <c>start_expression</c> 前淡出上一轮粒子与连线(若尚未初始化则立即结束)。
/// duration≤0 时使用 LanguageParticleManager 上的默认时长。
/// </summary>
public IEnumerator FadeOutParticlesBeforeNewRound(float duration = 0f)
{
if (particleManager == null) yield break;
yield return StartCoroutine(particleManager.FadeOutBeforeNewExpressionRound(duration));
}
/// <summary>
/// 等待表达流程就绪(开场表现 + 火山表达panel 播完)
/// </summary>
@@ -113,6 +113,16 @@ namespace AibisDream.MiniGame.Language
[SerializeField] private TMP_Text integrationProgressText;
[SerializeField] private TMP_Text interferenceCountText;
[Header("完成/确认阶段 — 屏幕内显示范围")]
[Tooltip("为真时,完成连线后(含确认按钮、聚焦、稳定化)目标字符位置会被限制在裁剪区域内,避免超出电视机屏幕可视区")]
[SerializeField] private bool clampCompletionPhasePositions = true;
[Tooltip("可选:场景中一块与屏幕内框对齐的 RectTransformWorld Space Canvas 子物体即可)。不指定则用粒子用的 movementBoundscanvasSize - textMargin")]
[SerializeField] private RectTransform completionScreenClipRect;
[Tooltip("在裁剪区基础上再向内缩进的世界单位距离,避免放大后的字半个挂在边外")]
[SerializeField] private float completionClipEdgePadding = 0.2f;
[Tooltip("将目标粒子拉回屏幕裁剪区时的平滑时间(越大越柔和,略增加拖尾感)")]
[SerializeField, Range(0.02f, 0.55f)] private float completionPositionSmoothTime = 0.2f;
[Header("完成阶段 UI")]
[SerializeField] private GameObject languageDeepPanel1;
[SerializeField] private GameObject languageDeepPanel2;
@@ -126,6 +136,8 @@ namespace AibisDream.MiniGame.Language
[SerializeField] private float focusZoomScale = 1.6f;
[SerializeField] private float focusMoveDuration = 1.2f;
[SerializeField] private float focusFadeDuration = 1f;
[Tooltip("再次 start_expression 时,若上一轮粒子/UI 仍在,先淡出再重开;协程 duration≤0 时用此值(秒)")]
[SerializeField] private float restartExpressionFadeDuration = 0.55f;
[SerializeField] private float probabilityDuration = 3.5f;
[SerializeField] private float predictionSequenceGap = 0.4f;
[SerializeField] private float spreadDistance = 0.35f;
@@ -187,6 +199,8 @@ namespace AibisDream.MiniGame.Language
private bool allowInput = true;
private float focusTimer = 0f;
private Dictionary<CandidateParticle, TargetFocusVisual> focusVisuals = new Dictionary<CandidateParticle, TargetFocusVisual>();
/// <summary>完成阶段屏幕钳制用 SmoothDamp 速度缓存(按粒子)</summary>
private readonly Dictionary<CandidateParticle, Vector3> completionClampSmoothVelocity = new Dictionary<CandidateParticle, Vector3>();
private Vector3 focusCentroid;
private List<string> finalTargetCharacters = new List<string>();
private List<Vector3> finalTargetPositions = new List<Vector3>();
@@ -236,6 +250,17 @@ namespace AibisDream.MiniGame.Language
// 是否已经初始化
private bool isInitialized = false;
/// <summary>Inspector 中的候选粒子总数,用于未在 Yarn 中指定非目标数量时恢复默认</summary>
private int defaultCandidateCountFromInspector;
private bool hasCapturedDefaultCandidateCount;
private void CaptureDefaultCandidateCountFromInspector()
{
if (hasCapturedDefaultCandidateCount) return;
defaultCandidateCountFromInspector = candidateCount;
hasCapturedDefaultCandidateCount = true;
}
private void Start()
{
// Start 中不再自动初始化,等待外部调用 InitializeSystem
@@ -247,8 +272,24 @@ namespace AibisDream.MiniGame.Language
/// <param name="phrases">焦虑短句列表</param>
/// <param name="sentence">目标句子</param>
/// <param name="dialogNode">完成时触发的对话节点</param>
public void InitializeSystem(List<string> phrases, string sentence, string dialogNode = null)
/// <param name="nonTargetParticleTotal">
/// 非目标候选粒子总数(蓝/干扰侧可交互粒子数量)。≥0 时候选池大小 = 目标句字数 + 该值;&lt;0 时使用 Inspector 的 Candidate Count。
/// </param>
public void InitializeSystem(List<string> phrases, string sentence, string dialogNode = null, int nonTargetParticleTotal = -1)
{
CaptureDefaultCandidateCountFromInspector();
string useSentence = string.IsNullOrEmpty(sentence) ? "这是一个测试示例" : sentence;
if (nonTargetParticleTotal >= 0)
{
candidateCount = Mathf.Max(useSentence.Length + nonTargetParticleTotal, useSentence.Length);
}
else
{
candidateCount = defaultCandidateCountFromInspector;
}
// 如果是第一次初始化,先执行基础初始化
if (!isInitialized)
{
@@ -280,22 +321,120 @@ namespace AibisDream.MiniGame.Language
isInitialized = true;
}
else
{
EnsureCandidatePoolSize(candidateCount);
}
// 设置游戏配置
anxietyPhrases = phrases ?? new List<string>();
targetSentence = sentence ?? "这是一个测试示例";
targetSentence = useSentence;
completionDialogNode = dialogNode ?? "";
// 设置全局焦虑短句配置
TextParticle.SetAnxietyPhrases(anxietyPhrases);
// 根据目标句子更新目标粒子数量
redParticleCount = Mathf.Min(sentence.Length, candidateCount);
redParticleCount = Mathf.Min(targetSentence.Length, candidateCount);
// 重新初始化游戏状态并播放入场动画
ResetGame(true);
}
/// <summary>
/// 在再次 <c>start_expression</c> 前调用:若系统已初始化过,则淡出当前粒子、连线与相关 UI,避免与新一轮重叠。
/// duration≤0 时使用 <see cref="restartExpressionFadeDuration"/>。
/// </summary>
public IEnumerator FadeOutBeforeNewExpressionRound(float duration)
{
if (!isInitialized)
yield break;
float d = duration > 0f ? duration : restartExpressionFadeDuration;
// 火山释放 log 与文字同时叠在屏幕上时,先把 log 藏起来,等文字淡出结束后再由 FadeInReleaseLogIfNeeded 出现
HideReleaseLogImmediate();
if (entranceRoutine != null)
{
StopCoroutine(entranceRoutine);
entranceRoutine = null;
}
if (expressionPanelRoutine != null)
{
StopCoroutine(expressionPanelRoutine);
expressionPanelRoutine = null;
}
if (confirmTimelineRoutine != null)
{
StopCoroutine(confirmTimelineRoutine);
confirmTimelineRoutine = null;
}
DOTween.Kill(this);
foreach (var p in candidateParticles)
{
if (p != null)
{
DOTween.Kill(p);
p.transform.DOKill();
p.velocity = Vector2.zero;
p.isStatic = true;
}
}
foreach (var f in floatingParticles)
{
if (f != null)
{
DOTween.Kill(f);
f.transform.DOKill();
f.velocity = Vector2.zero;
f.isCalmed = true;
}
}
interferenceLogicSuspended = true;
allowInput = false;
isCompleted = false;
completionPhase = CompletionPhase.None;
DestroyFocusVisualDecorationsAndClear();
DOTween.To(() => fadeOutAlpha, v => fadeOutAlpha = v, 0f, d)
.SetEase(Ease.OutQuad)
.SetTarget(this);
if (connectionRenderer != null)
{
DOTween.To(() => connectionRenderer.NonTargetAlphaScale, v => connectionRenderer.NonTargetAlphaScale = v, 0f, d)
.SetEase(Ease.OutQuad)
.SetTarget(this);
DOTween.To(() => connectionRenderer.TargetAlphaScale, v => connectionRenderer.TargetAlphaScale = v, 0f, d)
.SetEase(Ease.OutQuad)
.SetTarget(this);
}
foreach (var p in candidateParticles)
{
if (p != null)
FadeOutTextParticle(p, d);
}
foreach (var f in floatingParticles)
{
if (f != null)
FadeOutTextParticle(f, d);
}
SetStatusUIVisibility(false, d);
if (focusSequenceButton != null && focusSequenceButton.gameObject.activeSelf)
FadeOutUIElement(focusSequenceButton.gameObject, d);
FadeOutUIElement(languageDeepPanel1, d);
FadeOutUIElement(languageDeepPanel2, d);
yield return new WaitForSeconds(d);
fadeOutAlpha = 0f;
}
/// <summary>
/// 在打开视图前设置所有初始状态(panels、button 等不激活)
/// </summary>
@@ -378,6 +517,7 @@ namespace AibisDream.MiniGame.Language
isCompleted = false;
completionPhase = CompletionPhase.None;
allowInput = false;
ClearCompletionClampSmoothVelocity();
}
private void InitializeCanvas()
@@ -463,23 +603,7 @@ namespace AibisDream.MiniGame.Language
// 创建候选粒子
for (int i = 0; i < candidateCount; i++)
{
Vector3 pos = GetRandomPositionInBounds();
GameObject obj = CreateParticleObject(pos, $"CandidateParticle_{i}");
CandidateParticle particle = obj.AddComponent<CandidateParticle>();
particle.SetFont(chineseFontAsset);
particle.SetColors(targetParticleColor, nonTargetParticleColor, nonTargetParticleColor, targetCalmColor);
particle.SetFontStyles(targetParticleFontSize, nonTargetParticleFontSize, targetParticleBold, nonTargetParticleBold);
particle.SetInterferenceParams(nonTargetShakeIntensity, nonTargetShakeSpeed, nonTargetChangeInterval, nonTargetFloatAmplitude);
SetParticleBounds(particle);
// 设置发光效果(目标粒子和非目标粒子使用不同强度)
if (enableBloomGlow)
{
particle.SetGlowSettings(true, textGlowIntensity, nonTargetParticleColor);
particle.SetUnderlaySettings(glowDilate, glowSoftness);
}
candidateParticles.Add(particle);
AddOneCandidateParticle(i);
}
// 选择红色粒子
@@ -501,6 +625,52 @@ namespace AibisDream.MiniGame.Language
return obj;
}
private void AddOneCandidateParticle(int index)
{
Vector3 pos = GetRandomPositionInBounds();
GameObject obj = CreateParticleObject(pos, $"CandidateParticle_{index}");
CandidateParticle particle = obj.AddComponent<CandidateParticle>();
particle.SetFont(chineseFontAsset);
particle.SetColors(targetParticleColor, nonTargetParticleColor, nonTargetParticleColor, targetCalmColor);
particle.SetFontStyles(targetParticleFontSize, nonTargetParticleFontSize, targetParticleBold, nonTargetParticleBold);
particle.SetInterferenceParams(nonTargetShakeIntensity, nonTargetShakeSpeed, nonTargetChangeInterval, nonTargetFloatAmplitude);
SetParticleBounds(particle);
if (enableBloomGlow)
{
particle.SetGlowSettings(true, textGlowIntensity, nonTargetParticleColor);
particle.SetUnderlaySettings(glowDilate, glowSoftness);
}
candidateParticles.Add(particle);
}
/// <summary>
/// 增删候选粒子以匹配目标数量(用于 Yarn 动态指定非目标粒子总数后复用同一视图)
/// </summary>
private void EnsureCandidatePoolSize(int targetSize)
{
if (targetSize < 0) targetSize = 0;
candidateCount = targetSize;
while (candidateParticles.Count < targetSize)
{
AddOneCandidateParticle(candidateParticles.Count);
}
while (candidateParticles.Count > targetSize)
{
int last = candidateParticles.Count - 1;
CandidateParticle p = candidateParticles[last];
candidateParticles.RemoveAt(last);
if (p != null)
{
p.transform.DOKill();
Destroy(p.gameObject);
}
}
}
private Vector3 GetRandomPositionInBounds()
{
if (layoutShape == LayoutShape.Circle)
@@ -686,6 +856,96 @@ namespace AibisDream.MiniGame.Language
UpdateRenderers();
}
private void LateUpdate()
{
if (!isInitialized || !clampCompletionPhasePositions || !isCompleted)
return;
if (completionPhase == CompletionPhase.None)
return;
// 连线刚完成、等待确认时保持粒子当前世界坐标,避免 GetCompletionClipBounds(含 padding/屏幕 Rect
// 比游玩用 movementBounds 更紧时,在 Completed 首帧 LateUpdate 产生生硬瞬移。
if (completionPhase == CompletionPhase.Completed)
return;
Bounds clip = GetCompletionClipBounds();
if (clip.size.x < 0.01f || clip.size.y < 0.01f)
return;
float dt = Time.deltaTime;
if (dt < 1e-6f)
dt = 1e-6f;
float smooth = Mathf.Max(0.0001f, completionPositionSmoothTime);
for (int i = 0; i < targetParticles.Count; i++)
{
var p = targetParticles[i];
if (p == null) continue;
Vector3 cur = p.transform.position;
Vector3 desired = ClampPositionToBounds(cur, clip);
if (!completionClampSmoothVelocity.TryGetValue(p, out Vector3 vel))
vel = Vector3.zero;
Vector3 next = Vector3.SmoothDamp(cur, desired, ref vel, smooth, Mathf.Infinity, dt);
completionClampSmoothVelocity[p] = vel;
p.transform.position = next;
}
}
private void ClearCompletionClampSmoothVelocity()
{
completionClampSmoothVelocity.Clear();
}
/// <summary>
/// 完成阶段使用的裁剪范围:优先用 Inspector 指定的屏幕 Rect,否则与粒子运动边界一致。
/// </summary>
private Bounds GetCompletionClipBounds()
{
Bounds b;
if (completionScreenClipRect != null)
{
var corners = new Vector3[4];
completionScreenClipRect.GetWorldCorners(corners);
float minX = float.MaxValue, maxX = float.MinValue;
float minY = float.MaxValue, maxY = float.MinValue;
for (int c = 0; c < 4; c++)
{
minX = Mathf.Min(minX, corners[c].x);
maxX = Mathf.Max(maxX, corners[c].x);
minY = Mathf.Min(minY, corners[c].y);
maxY = Mathf.Max(maxY, corners[c].y);
}
float z = corners[0].z;
Vector3 center = new Vector3((minX + maxX) * 0.5f, (minY + maxY) * 0.5f, z);
Vector3 size = new Vector3(Mathf.Max(0f, maxX - minX), Mathf.Max(0f, maxY - minY), 0f);
b = new Bounds(center, size);
}
else
{
b = movementBounds;
}
if (completionClipEdgePadding > 0f)
{
Bounds shrunk = b;
shrunk.Expand(-completionClipEdgePadding);
if (shrunk.size.x >= 0.01f && shrunk.size.y >= 0.01f)
{
b = shrunk;
}
}
return b;
}
private static Vector3 ClampPositionToBounds(Vector3 worldPos, Bounds b)
{
return new Vector3(
Mathf.Clamp(worldPos.x, b.min.x, b.max.x),
Mathf.Clamp(worldPos.y, b.min.y, b.max.y),
worldPos.z
);
}
private void UpdateRenderers()
{
// 更新连接线渲染器
@@ -833,7 +1093,7 @@ namespace AibisDream.MiniGame.Language
focusTimer = 0f;
fadeOutAlpha = 1f;
allowInput = false;
focusVisuals.Clear();
DestroyFocusVisualDecorationsAndClear();
finalTargetCharacters.Clear();
finalTargetPositions.Clear();
focusTweensCompleted = false;
@@ -860,9 +1120,11 @@ namespace AibisDream.MiniGame.Language
float totalWidth = spacing * Mathf.Max(0, finalTargetCharacters.Count - 1);
float startX = -totalWidth / 2f;
finalTargetPositions.Clear();
Bounds clip = GetCompletionClipBounds();
for (int i = 0; i < finalTargetCharacters.Count; i++)
{
finalTargetPositions.Add(displayCenter + new Vector3(startX + i * spacing, 0f, 0f));
Vector3 pos = displayCenter + new Vector3(startX + i * spacing, 0f, 0f);
finalTargetPositions.Add(ClampPositionToBounds(pos, clip));
}
}
@@ -968,6 +1230,8 @@ namespace AibisDream.MiniGame.Language
focusSequenceButton.interactable = false;
}
ClearCompletionClampSmoothVelocity();
completionPhase = CompletionPhase.Focusing;
focusTimer = 0f;
focusTweensCompleted = false;
@@ -1018,8 +1282,9 @@ namespace AibisDream.MiniGame.Language
focusCentroid = ComputeCentroid(orderedRedParticles);
Vector3 focusTargetCenter = worldCanvas != null ? worldCanvas.transform.position : Vector3.zero;
Bounds focusClipBounds = GetCompletionClipBounds();
focusVisuals.Clear();
DestroyFocusVisualDecorationsAndClear();
int tweenTargetCount = orderedRedParticles.Count;
int completedTweens = 0;
@@ -1031,6 +1296,8 @@ namespace AibisDream.MiniGame.Language
Vector3 spreadOffset = new Vector3((i - indexCenter) * spreadDistance, Mathf.Sin(i * 1.4f) * spreadDistance * 0.6f, 0f);
Vector3 focusPosition = focusTargetCenter + offset * focusZoomScale + spreadOffset;
Vector3 finalPosition = finalTargetPositions.Count > i ? finalTargetPositions[i] : focusTargetCenter;
focusPosition = ClampPositionToBounds(focusPosition, focusClipBounds);
finalPosition = ClampPositionToBounds(finalPosition, focusClipBounds);
particle.transform.DOKill();
particle.transform.DOMove(focusPosition, focusMoveDuration)
@@ -1213,29 +1480,35 @@ namespace AibisDream.MiniGame.Language
}
}
private void CompleteFocusSequence()
private void DestroyFocusVisualDecorationsAndClear()
{
foreach (var visual in focusVisuals.Values)
{
if (visual == null)
continue;
if (visual.ringObject != null)
{
Destroy(visual.ringObject);
}
if (visual.probabilityLabel != null)
{
Destroy(visual.probabilityLabel.gameObject);
}
if (visual.particle != null)
{
visual.particle.transform.DOScale(Vector3.one * focusZoomScale, 0.3f).SetEase(Ease.OutQuad);
visual.particle.isStatic = true;
visual.particle.changeSpeedMultiplier = 1f;
}
}
focusVisuals.Clear();
}
private void CompleteFocusSequence()
{
var particlesToScale = new List<CandidateParticle>();
foreach (var visual in focusVisuals.Values)
{
if (visual?.particle != null)
particlesToScale.Add(visual.particle);
}
DestroyFocusVisualDecorationsAndClear();
foreach (var p in particlesToScale)
{
p.transform.DOScale(Vector3.one * focusZoomScale, 0.3f).SetEase(Ease.OutQuad);
p.isStatic = true;
p.changeSpeedMultiplier = 1f;
}
if (connectionRenderer != null)
{
@@ -1330,6 +1603,21 @@ namespace AibisDream.MiniGame.Language
});
}
/// <summary>
/// 立即隐藏火山释放 log(无动画),用于新一轮 start 前先淡出文字、再单独淡入 log。
/// </summary>
private void HideReleaseLogImmediate()
{
if (releaseLogSpriteRenderer == null)
return;
DOTween.Kill(releaseLogSpriteRenderer);
releaseLogSpriteRenderer.enabled = false;
releaseLogSpriteRenderer.gameObject.SetActive(false);
Color c = releaseLogSpriteRenderer.color;
c.a = 0f;
releaseLogSpriteRenderer.color = c;
}
/// <summary>
/// 若火山释放 log 界面已淡出,则淡入显示(start_expression 时调用,确保流程开始前界面可见)
/// </summary>
@@ -1441,7 +1729,7 @@ namespace AibisDream.MiniGame.Language
fadeOutAlpha = 1f;
allowInput = !playEntranceEffect;
orderedRedParticles.Clear();
focusVisuals.Clear();
DestroyFocusVisualDecorationsAndClear();
finalTargetCharacters.Clear();
finalTargetPositions.Clear();
previousConnections.Clear();
@@ -1449,6 +1737,7 @@ namespace AibisDream.MiniGame.Language
initializationFrames = 0;
focusTweensCompleted = false;
interferenceLogicSuspended = false;
ClearCompletionClampSmoothVelocity();
SetStatusUIVisibility(true, 0f);
if (entranceRoutine != null)
{
@@ -14,14 +14,32 @@ namespace AibisDream.MiniGame.Language
private static AibisDream.ExpressionManager ExpressionManager => FixSystemCenter.SystemDic.Get<AibisDream.ExpressionManager>();
/// <summary>
/// 启动表达粒子系统(在打开视图后调用),等待火山表达panel播完再返回
/// 启动表达粒子系统(在打开视图后调用),等待火山表达panel播完再返回
/// 流程:若有上一轮则先淡出字与连线 → 再淡入火山释放 log → 再启动新一轮并等表达 panel 就绪。
/// 注意:Yarn Spinner 2.x 对同名 <see cref="YarnCommand"/> 重载支持不可靠,只保留一个注册入口,用可选参数区分 3/4 参调用。
/// <<start_expression "哈哈|嘿嘿|呵呵" "我很害怕" "ExpressionCompleted">>
/// <<start_expression "哈哈|嘿嘿|呵呵" "我很害怕" "ExpressionCompleted" 24>>
/// (第四项为「非目标」候选粒子总数,候选池 = 目标句字数 + 该值;不写第四项则用 Inspector 的 Candidate Count
/// </summary>
/// <param name="anxietyPhrasesStr">干扰短句(笑话等),用 | 分隔,用于非目标粒子字符池,如:"哈哈|嘿嘿|呵呵"</param>
/// <param name="targetSentence">目标句子</param>
/// <param name="completionNode">完成时触发的对话节点(可</param>
/// <param name="completionNode">完成时触发的对话节点(可空字符串</param>
/// <param name="nonTargetParticleTotal">非目标候选粒子总数;&lt;0 表示使用 Inspector 默认</param>
[YarnCommand("start_expression")]
public static IEnumerator StartExpression(string anxietyPhrasesStr, string targetSentence, string completionNode = "")
public static IEnumerator StartExpression(
string anxietyPhrasesStr,
string targetSentence,
string completionNode = "",
float nonTargetParticleTotal = -1f)
{
return RunStartExpression(
anxietyPhrasesStr,
targetSentence,
completionNode ?? "",
UnityEngine.Mathf.RoundToInt(nonTargetParticleTotal));
}
private static IEnumerator RunStartExpression(string anxietyPhrasesStr, string targetSentence, string completionNode, int nonTargetParticleTotal)
{
if (ExpressionManager == null)
{
@@ -29,7 +47,6 @@ namespace AibisDream.MiniGame.Language
yield break;
}
// 解析干扰短句(用 | 分隔)
string[] phrases = null;
if (!string.IsNullOrEmpty(anxietyPhrasesStr))
{
@@ -40,9 +57,10 @@ namespace AibisDream.MiniGame.Language
}
}
// 若火山释放 log 界面已淡出,先淡入再开始流程
// 先淡出上一轮文字/连线等,再淡入火山释放 log,最后开新一轮粒子(避免 log 与旧字叠在一起)
yield return ExpressionManager.FadeOutParticlesBeforeNewRound(0f);
yield return ExpressionManager.EnsureReleaseLogFadedIn(1f);
ExpressionManager.StartSystem(phrases, targetSentence, completionNode);
ExpressionManager.StartSystem(phrases, targetSentence, completionNode, nonTargetParticleTotal);
yield return ExpressionManager.WaitUntilExpressionFlowReady();
}