Add focused word scale-down and smooth camera shake + unfocus words scribble
This commit is contained in:
@@ -13,6 +13,7 @@ MonoBehaviour:
|
|||||||
m_Name: NPCDialogueAnimation
|
m_Name: NPCDialogueAnimation
|
||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
SpawnMode: 0
|
SpawnMode: 0
|
||||||
|
DefaultScaleMultiplier: 1.2
|
||||||
SpawnRadius: 100
|
SpawnRadius: 100
|
||||||
SpawnHeightOffset: 0
|
SpawnHeightOffset: 0
|
||||||
FacePlayer: 1
|
FacePlayer: 1
|
||||||
@@ -48,6 +49,7 @@ MonoBehaviour:
|
|||||||
ShakeRadius: 10
|
ShakeRadius: 10
|
||||||
ShakeSpeed: 20
|
ShakeSpeed: 20
|
||||||
ShakeSmoothness: 20
|
ShakeSmoothness: 20
|
||||||
|
UnfocusedShakeSpeedMultiplier: 0.2
|
||||||
EnableGhostTrail: 1
|
EnableGhostTrail: 1
|
||||||
GhostTrailDelay: 0.08
|
GhostTrailDelay: 0.08
|
||||||
GhostTrailAlpha: 0.3
|
GhostTrailAlpha: 0.3
|
||||||
@@ -61,6 +63,18 @@ MonoBehaviour:
|
|||||||
MaxDistance: 10
|
MaxDistance: 10
|
||||||
MinScaleMultiplier: 1
|
MinScaleMultiplier: 1
|
||||||
MaxScaleMultiplier: 2
|
MaxScaleMultiplier: 2
|
||||||
MoveTowardPlayerOnFocus: 1
|
MoveTowardPlayerOnFocus: 0
|
||||||
FocusDistanceFromPlayer: 1.5
|
FocusDistanceFromPlayer: 1.5
|
||||||
FocusRotationSpeed: 10
|
FocusRotationSpeed: 10
|
||||||
|
EnableCameraShakeOnFocus: 0
|
||||||
|
CameraShakeIntensity: 5
|
||||||
|
CameraShakeSmoothness: 10
|
||||||
|
FocusedTextScaleMultiplier: 0.85
|
||||||
|
FocusedTextScaleDuration: 1
|
||||||
|
UnfocusedTextScaleDuration: 0.5
|
||||||
|
EnableSketchFadeOnFocus: 1
|
||||||
|
SketchMaterial: {fileID: 2100000, guid: 99ea3f23aff6ad849bb065a69a016520, type: 2}
|
||||||
|
SketchDuration: 1
|
||||||
|
FadeOutDuration: 0.4
|
||||||
|
SketchIntensity: 0.8
|
||||||
|
FinalFadeAlpha: 0.4
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 7be34619def8beb4dac18417794d4fe2
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
Shader "Unheimlich/UI/ScribbleEffect"
|
||||||
|
{
|
||||||
|
Properties
|
||||||
|
{
|
||||||
|
_Color("Scribble Color", Color) = (0.2, 0.2, 0.2, 1)
|
||||||
|
_Progress("Draw Progress", Range(0, 1)) = 0
|
||||||
|
_LineThickness("Thickness", Range(0.005, 0.25)) = 0.02
|
||||||
|
_ZigzagFreq("Zigzag Frequency", Float) = 10
|
||||||
|
_ZigzagAmp("Zigzag Amplitude", Range(0, 0.3)) = 0.1
|
||||||
|
_DiagonalSlant("Diagonal Slant", Range(-1, 1)) = 0.4
|
||||||
|
_NumPasses("Number of Passes", Range(1, 4)) = 2
|
||||||
|
_Roundness("Roundness", Range(0, 1)) = 0.6
|
||||||
|
}
|
||||||
|
|
||||||
|
SubShader
|
||||||
|
{
|
||||||
|
Tags { "Queue" = "Transparent" "RenderType" = "Transparent" }
|
||||||
|
Blend SrcAlpha OneMinusSrcAlpha
|
||||||
|
ZWrite Off
|
||||||
|
Cull Off
|
||||||
|
|
||||||
|
Pass
|
||||||
|
{
|
||||||
|
HLSLPROGRAM
|
||||||
|
#pragma vertex vert
|
||||||
|
#pragma fragment frag
|
||||||
|
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
|
||||||
|
|
||||||
|
struct Attributes
|
||||||
|
{
|
||||||
|
float4 positionOS : POSITION;
|
||||||
|
float2 uv : TEXCOORD0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Varyings
|
||||||
|
{
|
||||||
|
float4 positionCS : SV_POSITION;
|
||||||
|
float2 uv : TEXCOORD0;
|
||||||
|
};
|
||||||
|
|
||||||
|
CBUFFER_START(UnityPerMaterial)
|
||||||
|
half4 _Color;
|
||||||
|
half _Progress;
|
||||||
|
half _LineThickness;
|
||||||
|
half _ZigzagFreq;
|
||||||
|
half _ZigzagAmp;
|
||||||
|
half _DiagonalSlant;
|
||||||
|
int _NumPasses;
|
||||||
|
half _Roundness;
|
||||||
|
CBUFFER_END
|
||||||
|
|
||||||
|
Varyings vert(Attributes input)
|
||||||
|
{
|
||||||
|
Varyings output;
|
||||||
|
output.positionCS = TransformObjectToHClip(input.positionOS.xyz);
|
||||||
|
output.uv = input.uv;
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
float DrawSlantedZigzag(float2 uv, float yOffset, float passProgress)
|
||||||
|
{
|
||||||
|
float diagonalProgress = uv.x + uv.y * _DiagonalSlant;
|
||||||
|
|
||||||
|
float zigzagCenter = yOffset + sin(diagonalProgress * _ZigzagFreq * 6.28318) * _ZigzagAmp;
|
||||||
|
|
||||||
|
float progressEnd = passProgress * 1.6;
|
||||||
|
float progressMask = smoothstep(progressEnd + 0.15, progressEnd - 0.05, diagonalProgress);
|
||||||
|
|
||||||
|
float fadeIn = smoothstep(-0.1, 0.2, diagonalProgress);
|
||||||
|
float capMask = fadeIn * progressMask;
|
||||||
|
|
||||||
|
float distanceToCenter = abs(uv.y - zigzagCenter);
|
||||||
|
|
||||||
|
float edgeSoftness = _LineThickness * (1.0 - _Roundness * 0.7);
|
||||||
|
float zigzagStrength = 1.0 - smoothstep(edgeSoftness, _LineThickness, distanceToCenter);
|
||||||
|
|
||||||
|
zigzagStrength = pow(zigzagStrength, 1.0 + _Roundness * 3.5);
|
||||||
|
|
||||||
|
return zigzagStrength * capMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
half4 frag(Varyings input) : SV_Target
|
||||||
|
{
|
||||||
|
float totalMask = 0.0;
|
||||||
|
|
||||||
|
totalMask += DrawSlantedZigzag(input.uv, 0.5, _Progress);
|
||||||
|
|
||||||
|
if (_NumPasses >= 2)
|
||||||
|
totalMask += DrawSlantedZigzag(input.uv, 0.52, _Progress * 0.95);
|
||||||
|
|
||||||
|
if (_NumPasses >= 3)
|
||||||
|
totalMask += DrawSlantedZigzag(input.uv, 0.48, _Progress * 0.9);
|
||||||
|
|
||||||
|
if (_NumPasses >= 4)
|
||||||
|
totalMask += DrawSlantedZigzag(input.uv, 0.54, _Progress * 0.85);
|
||||||
|
|
||||||
|
totalMask = saturate(totalMask);
|
||||||
|
|
||||||
|
half4 result = _Color;
|
||||||
|
result.a *= totalMask;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
ENDHLSL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 10b6f40fb2f72a942a493008573d70d3
|
||||||
|
ShaderImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
defaultTextures: []
|
||||||
|
nonModifiableTextures: []
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: ad07d82f93823d34782937b358daafde
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,167 @@
|
|||||||
|
%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: ScribbleMaterial
|
||||||
|
m_Shader: {fileID: 4800000, guid: 10b6f40fb2f72a942a493008573d70d3, 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:
|
||||||
|
- MOTIONVECTORS
|
||||||
|
m_LockedProperties:
|
||||||
|
m_SavedProperties:
|
||||||
|
serializedVersion: 3
|
||||||
|
m_TexEnvs:
|
||||||
|
- _BaseMap:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _BumpMap:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _DetailAlbedoMap:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _DetailMask:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _DetailNormalMap:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _EmissionMap:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _FaceTex:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _MainTex:
|
||||||
|
m_Texture: {fileID: 28684132378477856, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _MetallicGlossMap:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _OcclusionMap:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _ParallaxMap:
|
||||||
|
m_Texture: {fileID: 0}
|
||||||
|
m_Scale: {x: 1, y: 1}
|
||||||
|
m_Offset: {x: 0, y: 0}
|
||||||
|
- _SpecGlossMap:
|
||||||
|
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:
|
||||||
|
- _AddPrecomputedVelocity: 0
|
||||||
|
- _AlphaClip: 0
|
||||||
|
- _AlphaToMask: 0
|
||||||
|
- _Blend: 0
|
||||||
|
- _BlendModePreserveSpecular: 1
|
||||||
|
- _BumpScale: 1
|
||||||
|
- _ClearCoatMask: 0
|
||||||
|
- _ClearCoatSmoothness: 0
|
||||||
|
- _ColorMask: 15
|
||||||
|
- _Cull: 2
|
||||||
|
- _Cutoff: 0.5
|
||||||
|
- _DetailAlbedoMapScale: 1
|
||||||
|
- _DetailNormalMapScale: 1
|
||||||
|
- _DiagonalAngle: 0.33
|
||||||
|
- _DiagonalSlant: -0.22
|
||||||
|
- _DistortionStrength: 0.01
|
||||||
|
- _DstBlend: 0
|
||||||
|
- _DstBlendAlpha: 0
|
||||||
|
- _EnvironmentReflections: 1
|
||||||
|
- _FaceDilate: 0
|
||||||
|
- _FadeAlpha: 1
|
||||||
|
- _GlossMapScale: 0
|
||||||
|
- _Glossiness: 0
|
||||||
|
- _GlossyReflections: 0
|
||||||
|
- _LineThickness: 0.25
|
||||||
|
- _Metallic: 0
|
||||||
|
- _NoiseScale: 50
|
||||||
|
- _NumLines: 1
|
||||||
|
- _NumPasses: 4
|
||||||
|
- _OcclusionStrength: 1
|
||||||
|
- _OutlineWidth: 0
|
||||||
|
- _Parallax: 0.005
|
||||||
|
- _Progress: 1
|
||||||
|
- _QueueOffset: 0
|
||||||
|
- _ReceiveShadows: 1
|
||||||
|
- _Roundness: 1
|
||||||
|
- _SketchIntensity: 1
|
||||||
|
- _SketchLineWidth: 0.02
|
||||||
|
- _SketchNoiseScale: 20
|
||||||
|
- _Smoothness: 0.5
|
||||||
|
- _SmoothnessTextureChannel: 0
|
||||||
|
- _SpecularHighlights: 1
|
||||||
|
- _SrcBlend: 1
|
||||||
|
- _SrcBlendAlpha: 1
|
||||||
|
- _Stencil: 0
|
||||||
|
- _StencilComp: 8
|
||||||
|
- _StencilOp: 0
|
||||||
|
- _StencilReadMask: 255
|
||||||
|
- _StencilWriteMask: 255
|
||||||
|
- _Surface: 0
|
||||||
|
- _WeightBold: 0.5
|
||||||
|
- _WeightNormal: 0
|
||||||
|
- _WorkflowMode: 1
|
||||||
|
- _XRMotionVectorsPass: 1
|
||||||
|
- _ZWrite: 1
|
||||||
|
- _ZigzagAmp: 0.167
|
||||||
|
- _ZigzagFreq: 6
|
||||||
|
m_Colors:
|
||||||
|
- _BaseColor: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
- _Color: {r: 1, g: 0.03459108, b: 0.03459108, a: 1}
|
||||||
|
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||||
|
- _FaceColor: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
- _OutlineColor: {r: 0, g: 0, b: 0, a: 1}
|
||||||
|
- _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1}
|
||||||
|
m_BuildTextureStacks: []
|
||||||
|
m_AllowLocking: 1
|
||||||
|
--- !u!114 &2128116555526520463
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 11
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Editor::UnityEditor.Rendering.Universal.AssetVersion
|
||||||
|
version: 10
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 99ea3f23aff6ad849bb065a69a016520
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 2100000
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -1963,7 +1963,7 @@ PrefabInstance:
|
|||||||
objectReference: {fileID: 1871114643}
|
objectReference: {fileID: 1871114643}
|
||||||
- target: {fileID: 5019363637456399335, guid: 204c7983537bb6c44a8ecafa782fca99, type: 3}
|
- target: {fileID: 5019363637456399335, guid: 204c7983537bb6c44a8ecafa782fca99, type: 3}
|
||||||
propertyPath: m_VersionIndex
|
propertyPath: m_VersionIndex
|
||||||
value: 10300
|
value: 10303
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 6096226974748024133, guid: 204c7983537bb6c44a8ecafa782fca99, type: 3}
|
- target: {fileID: 6096226974748024133, guid: 204c7983537bb6c44a8ecafa782fca99, type: 3}
|
||||||
propertyPath: m_Mesh
|
propertyPath: m_Mesh
|
||||||
@@ -2023,7 +2023,7 @@ PrefabInstance:
|
|||||||
objectReference: {fileID: 183470776}
|
objectReference: {fileID: 183470776}
|
||||||
- target: {fileID: 8474092010221730167, guid: 204c7983537bb6c44a8ecafa782fca99, type: 3}
|
- target: {fileID: 8474092010221730167, guid: 204c7983537bb6c44a8ecafa782fca99, type: 3}
|
||||||
propertyPath: m_VersionIndex
|
propertyPath: m_VersionIndex
|
||||||
value: 25624
|
value: 25627
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 9107982868375055835, guid: 204c7983537bb6c44a8ecafa782fca99, type: 3}
|
- target: {fileID: 9107982868375055835, guid: 204c7983537bb6c44a8ecafa782fca99, type: 3}
|
||||||
propertyPath: m_Mesh
|
propertyPath: m_Mesh
|
||||||
|
|||||||
@@ -13,6 +13,9 @@ namespace Unheimlich.Data.Dialogues
|
|||||||
[Tooltip("How choices appear in the world")]
|
[Tooltip("How choices appear in the world")]
|
||||||
public ChoiceSpawnMode SpawnMode = ChoiceSpawnMode.AroundAnchor;
|
public ChoiceSpawnMode SpawnMode = ChoiceSpawnMode.AroundAnchor;
|
||||||
|
|
||||||
|
[Tooltip("Default scale multiplier for spawned choices (1.0 = normal size)")]
|
||||||
|
public float DefaultScaleMultiplier = 1.0f;
|
||||||
|
|
||||||
[Header("Spawn Settings")]
|
[Header("Spawn Settings")]
|
||||||
[Tooltip("Radius around anchor where choices spawn")]
|
[Tooltip("Radius around anchor where choices spawn")]
|
||||||
public float SpawnRadius = 2f;
|
public float SpawnRadius = 2f;
|
||||||
@@ -53,6 +56,10 @@ namespace Unheimlich.Data.Dialogues
|
|||||||
[Tooltip("Smoothness of shake transitions (higher = smoother)")]
|
[Tooltip("Smoothness of shake transitions (higher = smoother)")]
|
||||||
public float ShakeSmoothness = 2f;
|
public float ShakeSmoothness = 2f;
|
||||||
|
|
||||||
|
[Tooltip("Shake speed multiplier for unfocused choices when one is focused (0.3 = 30% speed)")]
|
||||||
|
[Range(0f, 1f)]
|
||||||
|
public float UnfocusedShakeSpeedMultiplier = 0.3f;
|
||||||
|
|
||||||
[Header("Ghost Trail Effect")]
|
[Header("Ghost Trail Effect")]
|
||||||
[Tooltip("Enable ghost/shadow trail effect behind text (Heavy Rain style)")]
|
[Tooltip("Enable ghost/shadow trail effect behind text (Heavy Rain style)")]
|
||||||
public bool EnableGhostTrail = false;
|
public bool EnableGhostTrail = false;
|
||||||
@@ -105,6 +112,46 @@ namespace Unheimlich.Data.Dialogues
|
|||||||
|
|
||||||
[Tooltip("Rotation speed when a choice is focused (degrees per second). Higher = faster rotation.")]
|
[Tooltip("Rotation speed when a choice is focused (degrees per second). Higher = faster rotation.")]
|
||||||
public float FocusRotationSpeed = 60f;
|
public float FocusRotationSpeed = 60f;
|
||||||
|
|
||||||
|
[Tooltip("Enable camera shake when focusing on a choice")]
|
||||||
|
public bool EnableCameraShakeOnFocus = true;
|
||||||
|
|
||||||
|
[Tooltip("Camera shake intensity when focusing (higher = less shake, lower = more shake)")]
|
||||||
|
public float CameraShakeIntensity = 30f;
|
||||||
|
|
||||||
|
[Tooltip("Camera shake smoothness (0 = instant/jarring, higher = smoother). Controls how fast the camera moves to shake position.")]
|
||||||
|
public float CameraShakeSmoothness = 10f;
|
||||||
|
|
||||||
|
[Tooltip("Scale down multiplier for the FOCUSED choice text (0.9 = 90% size)")]
|
||||||
|
[Range(0f, 1f)]
|
||||||
|
public float FocusedTextScaleMultiplier = 0.9f;
|
||||||
|
|
||||||
|
[Tooltip("Duration of the text scale animation when focusing (in seconds)")]
|
||||||
|
public float FocusedTextScaleDuration = 0.3f;
|
||||||
|
|
||||||
|
[Tooltip("Duration of the text scale reset animation when unfocusing (in seconds)")]
|
||||||
|
public float UnfocusedTextScaleDuration = 0.3f;
|
||||||
|
|
||||||
|
[Header("Sketch & Fade on Selection")]
|
||||||
|
[Tooltip("Enable sketch and fade effect on non-selected words when a choice is focused")]
|
||||||
|
public bool EnableSketchFadeOnFocus = false;
|
||||||
|
|
||||||
|
[Tooltip("Material with sketch shader for TextMeshPro")]
|
||||||
|
public Material SketchMaterial;
|
||||||
|
|
||||||
|
[Tooltip("Duration of the sketch effect before fade (in seconds)")]
|
||||||
|
public float SketchDuration = 0.3f;
|
||||||
|
|
||||||
|
[Tooltip("Duration of the fade out after sketch (in seconds)")]
|
||||||
|
public float FadeOutDuration = 0.5f;
|
||||||
|
|
||||||
|
[Tooltip("Intensity of the sketch effect (0 = no sketch, 1 = full sketch)")]
|
||||||
|
[Range(0f, 1f)]
|
||||||
|
public float SketchIntensity = 0.8f;
|
||||||
|
|
||||||
|
[Tooltip("Final alpha value after fade (0 = invisible, 1 = opaque)")]
|
||||||
|
[Range(0f, 1f)]
|
||||||
|
public float FinalFadeAlpha = 0.2f;
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum ChoiceSpawnMode
|
public enum ChoiceSpawnMode
|
||||||
|
|||||||
@@ -38,6 +38,9 @@ namespace Unheimlich.Gameplay.Player
|
|||||||
[SerializeField] private float _shakeFrequency = 40f;
|
[SerializeField] private float _shakeFrequency = 40f;
|
||||||
private float _shakeInterval;
|
private float _shakeInterval;
|
||||||
private float _shakeTimer = 0f;
|
private float _shakeTimer = 0f;
|
||||||
|
private Vector3 _shakeTarget = Vector3.zero;
|
||||||
|
private Vector3 _shakeOriginalPos = Vector3.zero;
|
||||||
|
private float _shakeSmoothness = 0f;
|
||||||
|
|
||||||
private float _horizontalRotation;
|
private float _horizontalRotation;
|
||||||
private float _verticalRotation;
|
private float _verticalRotation;
|
||||||
@@ -140,20 +143,31 @@ namespace Unheimlich.Gameplay.Player
|
|||||||
/// Creates a random camera shake effect for feedback (e.g., impacts, events).
|
/// Creates a random camera shake effect for feedback (e.g., impacts, events).
|
||||||
/// Uses a timer-based interval to control shake frequency.
|
/// Uses a timer-based interval to control shake frequency.
|
||||||
/// Amplitude controls both the intensity and duration of the shake.
|
/// Amplitude controls both the intensity and duration of the shake.
|
||||||
|
/// Smoothness controls how quickly the camera interpolates to the shake position (0 = instant, higher = smoother).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Shake(float amplitude)
|
public void Shake(float amplitude, float smoothness = 0f)
|
||||||
{
|
{
|
||||||
|
_shakeSmoothness = smoothness;
|
||||||
_shakeTimer -= Time.deltaTime;
|
_shakeTimer -= Time.deltaTime;
|
||||||
|
|
||||||
if (_shakeTimer <= 0f)
|
if (_shakeTimer <= 0f)
|
||||||
{
|
{
|
||||||
_shakeTimer = _shakeInterval * amplitude;
|
_shakeTimer = _shakeInterval * amplitude;
|
||||||
|
_shakeOriginalPos = _playerCameraPivot.position;
|
||||||
|
|
||||||
float x = Random.Range(-1f, 1f) * amplitude;
|
float x = Random.Range(-1f, 1f) * amplitude;
|
||||||
float y = Random.Range(-1f, 1f) * amplitude;
|
float y = Random.Range(-1f, 1f) * amplitude;
|
||||||
|
|
||||||
Vector3 originalPos = _playerCameraPivot.position;
|
_shakeTarget = _shakeOriginalPos + new Vector3(x, y, 0f);
|
||||||
_playerCameraPivot.position = originalPos + new Vector3(x, y, 0f);
|
}
|
||||||
|
|
||||||
|
if (_shakeSmoothness > 0f)
|
||||||
|
{
|
||||||
|
_playerCameraPivot.position = Vector3.Lerp(_playerCameraPivot.position, _shakeTarget, Time.deltaTime * _shakeSmoothness);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_playerCameraPivot.position = _shakeTarget;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+74
-5
@@ -57,18 +57,23 @@ namespace Unheimlich.Interactions.FloatingWords
|
|||||||
private int _originalSortingOrder;
|
private int _originalSortingOrder;
|
||||||
private Vector3 _startLocalPos;
|
private Vector3 _startLocalPos;
|
||||||
private float _originalScale;
|
private float _originalScale;
|
||||||
|
private float _originalTextScale = 1f;
|
||||||
|
private int _textScaleTweenId = -1;
|
||||||
private bool _positionCaptured = false;
|
private bool _positionCaptured = false;
|
||||||
|
|
||||||
private Vector3 _shakeOffset = Vector3.zero;
|
private Vector3 _shakeOffset = Vector3.zero;
|
||||||
private Vector3 _shakeTarget = Vector3.zero;
|
private Vector3 _shakeTarget = Vector3.zero;
|
||||||
private float _shakeTimer = 0f;
|
private float _shakeTimer = 0f;
|
||||||
private bool _isShaking = false;
|
private bool _isShaking = false;
|
||||||
|
private float _shakeSpeedMultiplier = 1f;
|
||||||
|
|
||||||
private bool _disableFloatingEffects = false;
|
private bool _disableFloatingEffects = false;
|
||||||
|
|
||||||
private Queue<Vector3> _positionHistory = new Queue<Vector3>();
|
private Queue<Vector3> _positionHistory = new Queue<Vector3>();
|
||||||
private float _historyTimer = 0f;
|
private float _historyTimer = 0f;
|
||||||
private const float HISTORY_SAMPLE_RATE = 0.016f;
|
private const float HISTORY_SAMPLE_RATE = 0.016f;
|
||||||
|
|
||||||
|
private SketchFadeEffect _sketchFadeEffect;
|
||||||
|
|
||||||
void Awake()
|
void Awake()
|
||||||
{
|
{
|
||||||
@@ -169,7 +174,7 @@ namespace Unheimlich.Interactions.FloatingWords
|
|||||||
if (!GetEnableOrganicShake())
|
if (!GetEnableOrganicShake())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_shakeTimer += Time.deltaTime * GetShakeSpeed();
|
_shakeTimer += Time.deltaTime * GetShakeSpeed() * _shakeSpeedMultiplier;
|
||||||
|
|
||||||
if (_shakeTimer >= 1f)
|
if (_shakeTimer >= 1f)
|
||||||
{
|
{
|
||||||
@@ -204,6 +209,29 @@ namespace Unheimlich.Interactions.FloatingWords
|
|||||||
_shakeOffset = Vector3.zero;
|
_shakeOffset = Vector3.zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetShakeSpeedMultiplier(float multiplier)
|
||||||
|
{
|
||||||
|
_shakeSpeedMultiplier = Mathf.Max(0f, multiplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetTextScale(float targetScale, float duration = 0.3f)
|
||||||
|
{
|
||||||
|
if (_choiceTextComponent == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_textScaleTweenId >= 0)
|
||||||
|
LeanTween.cancel(_textScaleTweenId);
|
||||||
|
|
||||||
|
_textScaleTweenId = LeanTween.scale(_choiceTextComponent.gameObject, Vector3.one * targetScale, duration)
|
||||||
|
.setEase(LeanTweenType.easeOutQuad)
|
||||||
|
.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ResetTextScale(float duration = 0.3f)
|
||||||
|
{
|
||||||
|
SetTextScale(_originalTextScale, duration);
|
||||||
|
}
|
||||||
|
|
||||||
public void HideGhostTrail()
|
public void HideGhostTrail()
|
||||||
{
|
{
|
||||||
if (_ghostTextComponent != null)
|
if (_ghostTextComponent != null)
|
||||||
@@ -230,6 +258,11 @@ namespace Unheimlich.Interactions.FloatingWords
|
|||||||
|
|
||||||
LeanTween.cancel(gameObject);
|
LeanTween.cancel(gameObject);
|
||||||
StopOrganicShake();
|
StopOrganicShake();
|
||||||
|
|
||||||
|
DialogueAnimationSettings settings = GetAnimationSettings();
|
||||||
|
float textScaleMultiplier = settings != null ? settings.FocusedTextScaleMultiplier : 0.9f;
|
||||||
|
float textScaleDuration = settings != null ? settings.FocusedTextScaleDuration : 0.3f;
|
||||||
|
SetTextScale(textScaleMultiplier, textScaleDuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
transform.localScale = Vector3.one * Mathf.Lerp(_originalScale, MAX_FOCUS_SCALE, progress);
|
transform.localScale = Vector3.one * Mathf.Lerp(_originalScale, MAX_FOCUS_SCALE, progress);
|
||||||
@@ -374,7 +407,10 @@ namespace Unheimlich.Interactions.FloatingWords
|
|||||||
}
|
}
|
||||||
|
|
||||||
_startLocalPos = transform.localPosition;
|
_startLocalPos = transform.localPosition;
|
||||||
_originalScale = transform.localScale.x;
|
_originalScale = transform.localScale.x;
|
||||||
|
|
||||||
|
if (_choiceTextComponent != null)
|
||||||
|
_originalTextScale = _choiceTextComponent.transform.localScale.x;
|
||||||
|
|
||||||
LeanTween.cancel(gameObject);
|
LeanTween.cancel(gameObject);
|
||||||
|
|
||||||
@@ -383,6 +419,13 @@ namespace Unheimlich.Interactions.FloatingWords
|
|||||||
if (_ghostTextComponent != null)
|
if (_ghostTextComponent != null)
|
||||||
_ghostTextComponent.text = GetChoiceText();
|
_ghostTextComponent.text = GetChoiceText();
|
||||||
|
|
||||||
|
DialogueAnimationSettings settings = GetAnimationSettings();
|
||||||
|
if (settings != null && settings.EnableSketchFadeOnFocus && settings.SketchMaterial != null)
|
||||||
|
{
|
||||||
|
_sketchFadeEffect = gameObject.AddComponent<SketchFadeEffect>();
|
||||||
|
_sketchFadeEffect.Initialize(_choiceTextComponent, _ghostTextComponent, settings.SketchMaterial);
|
||||||
|
}
|
||||||
|
|
||||||
StartOrganicShake();
|
StartOrganicShake();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -465,8 +508,14 @@ namespace Unheimlich.Interactions.FloatingWords
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void ResetFeedback(float duration)
|
public void ResetFeedback(float duration)
|
||||||
{
|
{
|
||||||
LeanTween.cancel(gameObject);
|
LeanTween.cancel(gameObject);
|
||||||
|
|
||||||
|
if (_textScaleTweenId >= 0)
|
||||||
|
LeanTween.cancel(_textScaleTweenId);
|
||||||
|
|
||||||
StopOrganicShake();
|
StopOrganicShake();
|
||||||
|
|
||||||
|
ResetSketchFade();
|
||||||
|
|
||||||
LeanTween.moveLocal(gameObject, _startLocalPos, duration)
|
LeanTween.moveLocal(gameObject, _startLocalPos, duration)
|
||||||
.setEase(LeanTweenType.easeOutQuad)
|
.setEase(LeanTweenType.easeOutQuad)
|
||||||
@@ -479,10 +528,11 @@ namespace Unheimlich.Interactions.FloatingWords
|
|||||||
StartOrganicShake();
|
StartOrganicShake();
|
||||||
});
|
});
|
||||||
|
|
||||||
transform.localScale = Vector3.one;
|
transform.localScale = Vector3.one * _originalScale;
|
||||||
|
|
||||||
if (_choiceTextComponent != null)
|
if (_choiceTextComponent != null)
|
||||||
{
|
{
|
||||||
|
_choiceTextComponent.transform.localScale = Vector3.one * _originalTextScale;
|
||||||
_choiceTextComponent.color = Color.white;
|
_choiceTextComponent.color = Color.white;
|
||||||
|
|
||||||
if (_ghostTextComponent != null)
|
if (_ghostTextComponent != null)
|
||||||
@@ -497,5 +547,24 @@ namespace Unheimlich.Interactions.FloatingWords
|
|||||||
if (_canvas != null)
|
if (_canvas != null)
|
||||||
_canvas.sortingOrder = _originalSortingOrder;
|
_canvas.sortingOrder = _originalSortingOrder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ApplySketchFade()
|
||||||
|
{
|
||||||
|
DialogueAnimationSettings settings = GetAnimationSettings();
|
||||||
|
if (settings == null || !settings.EnableSketchFadeOnFocus || _sketchFadeEffect == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_sketchFadeEffect.PlaySketchFadeEffect(
|
||||||
|
settings.SketchDuration,
|
||||||
|
settings.FadeOutDuration,
|
||||||
|
settings.FinalFadeAlpha
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ResetSketchFade()
|
||||||
|
{
|
||||||
|
if (_sketchFadeEffect != null)
|
||||||
|
_sketchFadeEffect.ResetEffect();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+9
-2
@@ -41,6 +41,7 @@ namespace Unheimlich.Interactions.FloatingWords
|
|||||||
public bool MoveTowardPlayerOnFocus;
|
public bool MoveTowardPlayerOnFocus;
|
||||||
public float FocusDistanceFromPlayer;
|
public float FocusDistanceFromPlayer;
|
||||||
public bool DisableFloatingEffects;
|
public bool DisableFloatingEffects;
|
||||||
|
public float DefaultScaleMultiplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static SpawnConfig GetConfig(ObjectDescriptionSettings settings)
|
private static SpawnConfig GetConfig(ObjectDescriptionSettings settings)
|
||||||
@@ -68,7 +69,8 @@ namespace Unheimlich.Interactions.FloatingWords
|
|||||||
ShakeSmoothness = settings.ShakeSmoothness,
|
ShakeSmoothness = settings.ShakeSmoothness,
|
||||||
MoveTowardPlayerOnFocus = false,
|
MoveTowardPlayerOnFocus = false,
|
||||||
FocusDistanceFromPlayer = 1f,
|
FocusDistanceFromPlayer = 1f,
|
||||||
DisableFloatingEffects = true
|
DisableFloatingEffects = true,
|
||||||
|
DefaultScaleMultiplier = 1f
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,7 +99,8 @@ namespace Unheimlich.Interactions.FloatingWords
|
|||||||
ShakeSmoothness = settings.ShakeSmoothness,
|
ShakeSmoothness = settings.ShakeSmoothness,
|
||||||
MoveTowardPlayerOnFocus = settings.MoveTowardPlayerOnFocus,
|
MoveTowardPlayerOnFocus = settings.MoveTowardPlayerOnFocus,
|
||||||
FocusDistanceFromPlayer = settings.FocusDistanceFromPlayer,
|
FocusDistanceFromPlayer = settings.FocusDistanceFromPlayer,
|
||||||
DisableFloatingEffects = false
|
DisableFloatingEffects = false,
|
||||||
|
DefaultScaleMultiplier = settings.DefaultScaleMultiplier
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,6 +148,7 @@ namespace Unheimlich.Interactions.FloatingWords
|
|||||||
ChoiceFocusHandler word = Object.Instantiate(wordPrefab, parent);
|
ChoiceFocusHandler word = Object.Instantiate(wordPrefab, parent);
|
||||||
word.transform.localPosition = localOffset;
|
word.transform.localPosition = localOffset;
|
||||||
word.transform.localRotation = Quaternion.identity;
|
word.transform.localRotation = Quaternion.identity;
|
||||||
|
word.transform.localScale = Vector3.one * config.DefaultScaleMultiplier;
|
||||||
|
|
||||||
CanvasGroup canvasGroup = word.GetComponent<CanvasGroup>();
|
CanvasGroup canvasGroup = word.GetComponent<CanvasGroup>();
|
||||||
if (canvasGroup == null)
|
if (canvasGroup == null)
|
||||||
@@ -170,6 +174,7 @@ namespace Unheimlich.Interactions.FloatingWords
|
|||||||
ChoiceFocusHandler word = Object.Instantiate(prefab, parent);
|
ChoiceFocusHandler word = Object.Instantiate(prefab, parent);
|
||||||
word.transform.localPosition = Vector3.up * i * 50f;
|
word.transform.localPosition = Vector3.up * i * 50f;
|
||||||
word.transform.localRotation = Quaternion.identity;
|
word.transform.localRotation = Quaternion.identity;
|
||||||
|
word.transform.localScale = Vector3.one * config.DefaultScaleMultiplier;
|
||||||
word.Setup(choices[i], config);
|
word.Setup(choices[i], config);
|
||||||
words.Add(word);
|
words.Add(word);
|
||||||
}
|
}
|
||||||
@@ -188,6 +193,7 @@ namespace Unheimlich.Interactions.FloatingWords
|
|||||||
Vector3 offset = playerForward * 2f + Vector3.up * (i - choices.Count / 2f) * (config.SpawnRadius / choices.Count / 100f);
|
Vector3 offset = playerForward * 2f + Vector3.up * (i - choices.Count / 2f) * (config.SpawnRadius / choices.Count / 100f);
|
||||||
word.transform.position = Player.Instance.transform.position + offset;
|
word.transform.position = Player.Instance.transform.position + offset;
|
||||||
word.transform.LookAt(Player.Instance.transform);
|
word.transform.LookAt(Player.Instance.transform);
|
||||||
|
word.transform.localScale = Vector3.one * config.DefaultScaleMultiplier;
|
||||||
word.Setup(choices[i], config);
|
word.Setup(choices[i], config);
|
||||||
words.Add(word);
|
words.Add(word);
|
||||||
}
|
}
|
||||||
@@ -213,6 +219,7 @@ namespace Unheimlich.Interactions.FloatingWords
|
|||||||
ChoiceFocusHandler word = Object.Instantiate(prefab, parent);
|
ChoiceFocusHandler word = Object.Instantiate(prefab, parent);
|
||||||
word.transform.localPosition = localOffset;
|
word.transform.localPosition = localOffset;
|
||||||
word.transform.LookAt(Player.Instance.transform);
|
word.transform.LookAt(Player.Instance.transform);
|
||||||
|
word.transform.localScale = Vector3.one * config.DefaultScaleMultiplier;
|
||||||
word.Setup(choices[i], config);
|
word.Setup(choices[i], config);
|
||||||
words.Add(word);
|
words.Add(word);
|
||||||
}
|
}
|
||||||
|
|||||||
+223
@@ -0,0 +1,223 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
using TMPro;
|
||||||
|
|
||||||
|
namespace Unheimlich.Interactions.FloatingWords
|
||||||
|
{
|
||||||
|
public class SketchFadeEffect : MonoBehaviour
|
||||||
|
{
|
||||||
|
private TextMeshProUGUI _textComponent;
|
||||||
|
private TextMeshProUGUI _ghostTextComponent;
|
||||||
|
private Image _scribbleOverlay;
|
||||||
|
private Material _scribbleMaterialInstance;
|
||||||
|
private Material _scribbleMaterialTemplate;
|
||||||
|
|
||||||
|
private static readonly int ProgressID = Shader.PropertyToID("_Progress");
|
||||||
|
|
||||||
|
private bool _isEffectActive = false;
|
||||||
|
private bool _overlayCreated = false;
|
||||||
|
private Color _originalTextColor;
|
||||||
|
private Color _originalGhostColor;
|
||||||
|
|
||||||
|
private int _scribbleTweenId = -1;
|
||||||
|
private int _fadeTweenId = -1;
|
||||||
|
|
||||||
|
public void Initialize(TextMeshProUGUI textComponent, TextMeshProUGUI ghostComponent, Material scribbleMaterial)
|
||||||
|
{
|
||||||
|
_textComponent = textComponent;
|
||||||
|
_ghostTextComponent = ghostComponent;
|
||||||
|
_scribbleMaterialTemplate = scribbleMaterial;
|
||||||
|
_originalTextColor = _textComponent.color;
|
||||||
|
|
||||||
|
if (_ghostTextComponent != null)
|
||||||
|
_originalGhostColor = _ghostTextComponent.color;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateScribbleOverlay()
|
||||||
|
{
|
||||||
|
if (_overlayCreated || _scribbleMaterialTemplate == null || _textComponent == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
GameObject overlayObject = new GameObject("ScribbleOverlay");
|
||||||
|
overlayObject.transform.SetParent(_textComponent.transform, false);
|
||||||
|
|
||||||
|
_scribbleOverlay = overlayObject.AddComponent<Image>();
|
||||||
|
_scribbleOverlay.raycastTarget = false;
|
||||||
|
|
||||||
|
RectTransform overlayRect = overlayObject.GetComponent<RectTransform>();
|
||||||
|
RectTransform textRect = _textComponent.GetComponent<RectTransform>();
|
||||||
|
|
||||||
|
_textComponent.ForceMeshUpdate();
|
||||||
|
|
||||||
|
Vector2 textSize = _textComponent.GetRenderedValues(false);
|
||||||
|
|
||||||
|
float horizontalPadding = 1.2f;
|
||||||
|
float verticalPadding = 0.8f;
|
||||||
|
Vector2 paddedSize = new Vector2(
|
||||||
|
textSize.x + horizontalPadding,
|
||||||
|
textSize.y + verticalPadding
|
||||||
|
);
|
||||||
|
|
||||||
|
overlayRect.anchorMin = new Vector2(0.5f, 0.5f);
|
||||||
|
overlayRect.anchorMax = new Vector2(0.5f, 0.5f);
|
||||||
|
overlayRect.pivot = new Vector2(0.5f, 0.5f);
|
||||||
|
|
||||||
|
float leftOffset = -horizontalPadding * 0.9f;
|
||||||
|
overlayRect.anchoredPosition = new Vector2(leftOffset, 0f);
|
||||||
|
overlayRect.sizeDelta = paddedSize;
|
||||||
|
|
||||||
|
overlayRect.localScale = Vector3.one;
|
||||||
|
|
||||||
|
_scribbleMaterialInstance = new Material(_scribbleMaterialTemplate);
|
||||||
|
_scribbleMaterialInstance.SetFloat(ProgressID, 0f);
|
||||||
|
_scribbleOverlay.material = _scribbleMaterialInstance;
|
||||||
|
|
||||||
|
_scribbleOverlay.gameObject.SetActive(false);
|
||||||
|
|
||||||
|
_overlayCreated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PlaySketchFadeEffect(float scribbleDuration, float fadeDuration, float finalAlpha)
|
||||||
|
{
|
||||||
|
if (_isEffectActive || _textComponent == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
CancelActiveTweens();
|
||||||
|
|
||||||
|
CreateScribbleOverlay();
|
||||||
|
|
||||||
|
if (_scribbleOverlay == null || _scribbleMaterialInstance == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_scribbleOverlay.gameObject.SetActive(true);
|
||||||
|
|
||||||
|
_isEffectActive = true;
|
||||||
|
|
||||||
|
_scribbleTweenId = LeanTween.value(gameObject, 0f, 1f, scribbleDuration)
|
||||||
|
.setEase(LeanTweenType.easeInOutQuad)
|
||||||
|
.setOnUpdate((float val) => {
|
||||||
|
if (_scribbleMaterialInstance != null)
|
||||||
|
_scribbleMaterialInstance.SetFloat(ProgressID, val);
|
||||||
|
})
|
||||||
|
.setOnComplete(() => {
|
||||||
|
_scribbleTweenId = -1;
|
||||||
|
_fadeTweenId = LeanTween.value(gameObject, _originalTextColor.a, finalAlpha, fadeDuration)
|
||||||
|
.setEase(LeanTweenType.easeInQuad)
|
||||||
|
.setOnUpdate((float val) => {
|
||||||
|
if (_textComponent != null)
|
||||||
|
{
|
||||||
|
Color textColor = _textComponent.color;
|
||||||
|
textColor.a = val;
|
||||||
|
_textComponent.color = textColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_ghostTextComponent != null)
|
||||||
|
{
|
||||||
|
Color ghostColor = _ghostTextComponent.color;
|
||||||
|
ghostColor.a = val * (_originalGhostColor.a / _originalTextColor.a);
|
||||||
|
_ghostTextComponent.color = ghostColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_scribbleOverlay != null)
|
||||||
|
{
|
||||||
|
Color scribbleColor = _scribbleOverlay.color;
|
||||||
|
scribbleColor.a = val;
|
||||||
|
_scribbleOverlay.color = scribbleColor;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setOnComplete(() => {
|
||||||
|
_fadeTweenId = -1;
|
||||||
|
}).id;
|
||||||
|
}).id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ResetEffect()
|
||||||
|
{
|
||||||
|
CancelActiveTweens();
|
||||||
|
|
||||||
|
if (_scribbleMaterialInstance != null)
|
||||||
|
{
|
||||||
|
float currentProgress = _scribbleMaterialInstance.GetFloat(ProgressID);
|
||||||
|
|
||||||
|
if (currentProgress > 0f)
|
||||||
|
{
|
||||||
|
_scribbleTweenId = LeanTween.value(gameObject, currentProgress, 0f, 0.3f)
|
||||||
|
.setEase(LeanTweenType.easeOutQuad)
|
||||||
|
.setOnUpdate((float val) => {
|
||||||
|
if (_scribbleMaterialInstance != null)
|
||||||
|
_scribbleMaterialInstance.SetFloat(ProgressID, val);
|
||||||
|
})
|
||||||
|
.setOnComplete(() => {
|
||||||
|
_scribbleTweenId = -1;
|
||||||
|
if (_scribbleOverlay != null)
|
||||||
|
_scribbleOverlay.gameObject.SetActive(false);
|
||||||
|
}).id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_textComponent != null)
|
||||||
|
{
|
||||||
|
float currentAlpha = _textComponent.color.a;
|
||||||
|
|
||||||
|
if (currentAlpha < _originalTextColor.a)
|
||||||
|
{
|
||||||
|
_fadeTweenId = LeanTween.value(gameObject, currentAlpha, _originalTextColor.a, 0.3f)
|
||||||
|
.setEase(LeanTweenType.easeOutQuad)
|
||||||
|
.setOnUpdate((float val) => {
|
||||||
|
if (_textComponent != null)
|
||||||
|
{
|
||||||
|
Color c = _textComponent.color;
|
||||||
|
c.a = val;
|
||||||
|
_textComponent.color = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_ghostTextComponent != null)
|
||||||
|
{
|
||||||
|
Color c = _ghostTextComponent.color;
|
||||||
|
c.a = val * (_originalGhostColor.a / _originalTextColor.a);
|
||||||
|
_ghostTextComponent.color = c;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setOnComplete(() => {
|
||||||
|
_fadeTweenId = -1;
|
||||||
|
}).id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_scribbleOverlay != null)
|
||||||
|
{
|
||||||
|
Color c = _scribbleOverlay.color;
|
||||||
|
c.a = 1f;
|
||||||
|
_scribbleOverlay.color = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
_isEffectActive = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CancelActiveTweens()
|
||||||
|
{
|
||||||
|
if (_scribbleTweenId != -1)
|
||||||
|
{
|
||||||
|
LeanTween.cancel(_scribbleTweenId);
|
||||||
|
_scribbleTweenId = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_fadeTweenId != -1)
|
||||||
|
{
|
||||||
|
LeanTween.cancel(_fadeTweenId);
|
||||||
|
_fadeTweenId = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDestroy()
|
||||||
|
{
|
||||||
|
CancelActiveTweens();
|
||||||
|
|
||||||
|
if (_scribbleMaterialInstance != null)
|
||||||
|
Destroy(_scribbleMaterialInstance);
|
||||||
|
|
||||||
|
if (_scribbleOverlay != null)
|
||||||
|
Destroy(_scribbleOverlay.gameObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 0ee81e39cd832e34d9219099af39f4bb
|
||||||
@@ -30,7 +30,7 @@ namespace Unheimlich.Managers
|
|||||||
private readonly float _raycastInterval;
|
private readonly float _raycastInterval;
|
||||||
private readonly float _recoveryDuration;
|
private readonly float _recoveryDuration;
|
||||||
private readonly float _focusRetentionTime;
|
private readonly float _focusRetentionTime;
|
||||||
private readonly float _shakeIntensity;
|
private readonly float _fallbackShakeIntensity;
|
||||||
|
|
||||||
private static readonly Vector3 ViewportCenter = new Vector3(0.5f, 0.5f, 0f);
|
private static readonly Vector3 ViewportCenter = new Vector3(0.5f, 0.5f, 0f);
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@ namespace Unheimlich.Managers
|
|||||||
float raycastInterval,
|
float raycastInterval,
|
||||||
float recoveryDuration,
|
float recoveryDuration,
|
||||||
float focusRetentionTime,
|
float focusRetentionTime,
|
||||||
float shakeIntensity)
|
float fallbackShakeIntensity)
|
||||||
{
|
{
|
||||||
_manager = manager;
|
_manager = manager;
|
||||||
_mainCamera = mainCamera;
|
_mainCamera = mainCamera;
|
||||||
@@ -57,7 +57,7 @@ namespace Unheimlich.Managers
|
|||||||
_raycastInterval = raycastInterval;
|
_raycastInterval = raycastInterval;
|
||||||
_recoveryDuration = recoveryDuration;
|
_recoveryDuration = recoveryDuration;
|
||||||
_focusRetentionTime = focusRetentionTime;
|
_focusRetentionTime = focusRetentionTime;
|
||||||
_shakeIntensity = shakeIntensity;
|
_fallbackShakeIntensity = fallbackShakeIntensity;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -87,7 +87,9 @@ namespace Unheimlich.Managers
|
|||||||
if (_isFocusLocked)
|
if (_isFocusLocked)
|
||||||
{
|
{
|
||||||
if (_retentionTimer > 0f)
|
if (_retentionTimer > 0f)
|
||||||
_retentionTimer -= Time.deltaTime;
|
_retentionTimer -= Time.deltaTime;
|
||||||
|
else
|
||||||
|
_isFocusLocked = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,8 +117,8 @@ namespace Unheimlich.Managers
|
|||||||
{
|
{
|
||||||
if (_currentFocusedHandler != null)
|
if (_currentFocusedHandler != null)
|
||||||
{
|
{
|
||||||
_isFocusLocked = true;
|
_currentFocusedHandler.ResetFeedback(_recoveryDuration);
|
||||||
_currentFocusedHandler.ResetFeedback(_recoveryDuration);
|
ResetAllUnfocusEffects();
|
||||||
}
|
}
|
||||||
|
|
||||||
_currentFocusedHandler = hitHandler;
|
_currentFocusedHandler = hitHandler;
|
||||||
@@ -126,6 +128,8 @@ namespace Unheimlich.Managers
|
|||||||
if (_playerLook != null)
|
if (_playerLook != null)
|
||||||
_playerLook.LockAim(true);
|
_playerLook.LockAim(true);
|
||||||
|
|
||||||
|
ApplyUnfocusEffectToOthers(hitHandler);
|
||||||
|
|
||||||
DialogueAnimationSettings settings = _manager.CurrentAnimationSettings;
|
DialogueAnimationSettings settings = _manager.CurrentAnimationSettings;
|
||||||
bool shouldRotate = settings == null || settings.EnableRotation;
|
bool shouldRotate = settings == null || settings.EnableRotation;
|
||||||
if (shouldRotate && _manager.CurrentDialogueUI != null)
|
if (shouldRotate && _manager.CurrentDialogueUI != null)
|
||||||
@@ -149,18 +153,24 @@ namespace Unheimlich.Managers
|
|||||||
|
|
||||||
_currentFocusedHandler.ApplyFocusFeedback(progress);
|
_currentFocusedHandler.ApplyFocusFeedback(progress);
|
||||||
|
|
||||||
if (_playerLook != null)
|
DialogueAnimationSettings currentSettings = _manager.CurrentAnimationSettings;
|
||||||
_playerLook.Shake(progress / _shakeIntensity);
|
bool shouldShake = currentSettings == null || currentSettings.EnableCameraShakeOnFocus;
|
||||||
|
|
||||||
|
if (shouldShake && _playerLook != null)
|
||||||
|
{
|
||||||
|
float shakeIntensity = currentSettings != null ? currentSettings.CameraShakeIntensity : _fallbackShakeIntensity;
|
||||||
|
float shakeSmoothness = currentSettings != null ? currentSettings.CameraShakeSmoothness : 10f;
|
||||||
|
_playerLook.Shake(progress / shakeIntensity, shakeSmoothness);
|
||||||
|
}
|
||||||
|
|
||||||
if (_focusTimer >= _focusTime)
|
if (_focusTimer >= _focusTime)
|
||||||
{
|
{
|
||||||
_isFocusLocked = true;
|
ChoiceFocusHandler selectedHandler = _currentFocusedHandler;
|
||||||
_currentFocusedHandler.ResetFeedback(_recoveryDuration);
|
|
||||||
|
|
||||||
if (_currentFocusedHandler.DialogueData != null)
|
if (selectedHandler.DialogueData != null)
|
||||||
{
|
{
|
||||||
OnChoiceMade?.Invoke(_currentFocusedHandler.DialogueData);
|
OnChoiceMade?.Invoke(selectedHandler.DialogueData);
|
||||||
DialogueNode nextNode = _currentFocusedHandler.GetNextNode();
|
DialogueNode nextNode = selectedHandler.GetNextNode();
|
||||||
_manager.GoToNextNode(nextNode);
|
_manager.GoToNextNode(nextNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,6 +183,9 @@ namespace Unheimlich.Managers
|
|||||||
}
|
}
|
||||||
|
|
||||||
ResetAnimationTimers();
|
ResetAnimationTimers();
|
||||||
|
ResetAllUnfocusEffects();
|
||||||
|
|
||||||
|
selectedHandler.ResetFeedback(_recoveryDuration);
|
||||||
|
|
||||||
if (_playerLook != null)
|
if (_playerLook != null)
|
||||||
_playerLook.LockAim(false);
|
_playerLook.LockAim(false);
|
||||||
@@ -180,9 +193,8 @@ namespace Unheimlich.Managers
|
|||||||
}
|
}
|
||||||
else if (_currentFocusedHandler != null && _retentionTimer <= 0f)
|
else if (_currentFocusedHandler != null && _retentionTimer <= 0f)
|
||||||
{
|
{
|
||||||
_isFocusLocked = true;
|
_currentFocusedHandler.ResetFeedback(_recoveryDuration);
|
||||||
|
ResetAllUnfocusEffects();
|
||||||
_currentFocusedHandler.ResetFeedback(_recoveryDuration);
|
|
||||||
|
|
||||||
DialogueAnimationSettings settings = _manager.CurrentAnimationSettings;
|
DialogueAnimationSettings settings = _manager.CurrentAnimationSettings;
|
||||||
bool shouldRotate = settings == null || settings.EnableRotation;
|
bool shouldRotate = settings == null || settings.EnableRotation;
|
||||||
@@ -198,6 +210,41 @@ namespace Unheimlich.Managers
|
|||||||
_playerLook.LockAim(false);
|
_playerLook.LockAim(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ApplyUnfocusEffectToOthers(ChoiceFocusHandler focusedHandler)
|
||||||
|
{
|
||||||
|
if (_manager.CurrentDialogueUI == null || _manager.CurrentDialogueUI.ChoiceContainer == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
DialogueAnimationSettings settings = _manager.CurrentAnimationSettings;
|
||||||
|
float shakeSlowdown = settings != null ? settings.UnfocusedShakeSpeedMultiplier : 0.3f;
|
||||||
|
|
||||||
|
foreach (Transform child in _manager.CurrentDialogueUI.ChoiceContainer.transform)
|
||||||
|
{
|
||||||
|
ChoiceFocusHandler handler = child.GetComponent<ChoiceFocusHandler>();
|
||||||
|
if (handler != null && handler != focusedHandler)
|
||||||
|
{
|
||||||
|
handler.SetShakeSpeedMultiplier(shakeSlowdown);
|
||||||
|
handler.ApplySketchFade();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ResetAllUnfocusEffects()
|
||||||
|
{
|
||||||
|
if (_manager.CurrentDialogueUI == null || _manager.CurrentDialogueUI.ChoiceContainer == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (Transform child in _manager.CurrentDialogueUI.ChoiceContainer.transform)
|
||||||
|
{
|
||||||
|
ChoiceFocusHandler handler = child.GetComponent<ChoiceFocusHandler>();
|
||||||
|
if (handler != null)
|
||||||
|
{
|
||||||
|
handler.SetShakeSpeedMultiplier(1f);
|
||||||
|
handler.ResetSketchFade();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void ResetAnimationTimers()
|
private void ResetAnimationTimers()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -24,7 +24,9 @@ namespace Unheimlich.Managers
|
|||||||
[Header("Focus Stabilization")]
|
[Header("Focus Stabilization")]
|
||||||
[SerializeField] private float _recoveryDuration = 0.5f;
|
[SerializeField] private float _recoveryDuration = 0.5f;
|
||||||
[SerializeField] private float _focusRetentionTime = 0.1f;
|
[SerializeField] private float _focusRetentionTime = 0.1f;
|
||||||
[SerializeField] private float _shakeIntensity = 30f;
|
|
||||||
|
[Tooltip("Fallback camera shake intensity if not set in DialogueAnimationSettings")]
|
||||||
|
[SerializeField] private float _fallbackShakeIntensity = 30f;
|
||||||
|
|
||||||
public DialogueAnimationSettings CurrentAnimationSettings => _currentAnimationSettings;
|
public DialogueAnimationSettings CurrentAnimationSettings => _currentAnimationSettings;
|
||||||
public bool IsDialogueActive => IsInDialogue;
|
public bool IsDialogueActive => IsInDialogue;
|
||||||
@@ -74,7 +76,7 @@ namespace Unheimlich.Managers
|
|||||||
_raycastInterval,
|
_raycastInterval,
|
||||||
_recoveryDuration,
|
_recoveryDuration,
|
||||||
_focusRetentionTime,
|
_focusRetentionTime,
|
||||||
_shakeIntensity
|
_fallbackShakeIntensity
|
||||||
);
|
);
|
||||||
|
|
||||||
_focusSystem.OnChoiceMade += (choice) => OnChoiceMade?.Invoke(choice);
|
_focusSystem.OnChoiceMade += (choice) => OnChoiceMade?.Invoke(choice);
|
||||||
|
|||||||
Reference in New Issue
Block a user