Smooth 3C & simplify hallucination trigger
This commit is contained in:
Vendored
+1
-1
@@ -67,5 +67,5 @@
|
|||||||
"*.sln": "*.csproj",
|
"*.sln": "*.csproj",
|
||||||
"*.slnx": "*.csproj"
|
"*.slnx": "*.csproj"
|
||||||
},
|
},
|
||||||
"dotnet.defaultSolution": "Unheimlish_POC.slnx"
|
"dotnet.defaultSolution": "Unheimlich_POC.slnx"
|
||||||
}
|
}
|
||||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,205 @@
|
|||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!1 &1550415954014096864
|
||||||
|
GameObject:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
serializedVersion: 6
|
||||||
|
m_Component:
|
||||||
|
- component: {fileID: 2882973441548793895}
|
||||||
|
- component: {fileID: 4372620151762523236}
|
||||||
|
- component: {fileID: 6391984422839570246}
|
||||||
|
- component: {fileID: 2810473078386703306}
|
||||||
|
m_Layer: 0
|
||||||
|
m_Name: ChoiceText-3D
|
||||||
|
m_TagString: Untagged
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_NavMeshLayer: 0
|
||||||
|
m_StaticEditorFlags: 0
|
||||||
|
m_IsActive: 1
|
||||||
|
--- !u!224 &2882973441548793895
|
||||||
|
RectTransform:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 1550415954014096864}
|
||||||
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||||
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
|
m_ConstrainProportionsScale: 0
|
||||||
|
m_Children: []
|
||||||
|
m_Father: {fileID: 0}
|
||||||
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
|
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||||
|
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||||
|
m_AnchoredPosition: {x: 0, y: 0}
|
||||||
|
m_SizeDelta: {x: 100, y: 20}
|
||||||
|
m_Pivot: {x: 0.5, y: 0.5}
|
||||||
|
--- !u!23 &4372620151762523236
|
||||||
|
MeshRenderer:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 1550415954014096864}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_CastShadows: 0
|
||||||
|
m_ReceiveShadows: 0
|
||||||
|
m_DynamicOccludee: 1
|
||||||
|
m_StaticShadowCaster: 0
|
||||||
|
m_MotionVectors: 1
|
||||||
|
m_LightProbeUsage: 1
|
||||||
|
m_ReflectionProbeUsage: 1
|
||||||
|
m_RayTracingMode: 2
|
||||||
|
m_RayTraceProcedural: 0
|
||||||
|
m_RayTracingAccelStructBuildFlagsOverride: 0
|
||||||
|
m_RayTracingAccelStructBuildFlags: 1
|
||||||
|
m_SmallMeshCulling: 1
|
||||||
|
m_ForceMeshLod: -1
|
||||||
|
m_MeshLodSelectionBias: 0
|
||||||
|
m_RenderingLayerMask: 1
|
||||||
|
m_RendererPriority: 0
|
||||||
|
m_Materials:
|
||||||
|
- {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||||
|
m_StaticBatchInfo:
|
||||||
|
firstSubMesh: 0
|
||||||
|
subMeshCount: 0
|
||||||
|
m_StaticBatchRoot: {fileID: 0}
|
||||||
|
m_ProbeAnchor: {fileID: 0}
|
||||||
|
m_LightProbeVolumeOverride: {fileID: 0}
|
||||||
|
m_ScaleInLightmap: 1
|
||||||
|
m_ReceiveGI: 1
|
||||||
|
m_PreserveUVs: 0
|
||||||
|
m_IgnoreNormalsForChartDetection: 0
|
||||||
|
m_ImportantGI: 0
|
||||||
|
m_StitchLightmapSeams: 1
|
||||||
|
m_SelectedEditorRenderState: 3
|
||||||
|
m_MinimumChartSize: 4
|
||||||
|
m_AutoUVMaxDistance: 0.5
|
||||||
|
m_AutoUVMaxAngle: 89
|
||||||
|
m_LightmapParameters: {fileID: 0}
|
||||||
|
m_GlobalIlluminationMeshLod: 0
|
||||||
|
m_SortingLayerID: 0
|
||||||
|
m_SortingLayer: 0
|
||||||
|
m_SortingOrder: 0
|
||||||
|
m_MaskInteraction: 0
|
||||||
|
m_AdditionalVertexStreams: {fileID: 0}
|
||||||
|
--- !u!114 &6391984422839570246
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 1550415954014096864}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier: Unity.TextMeshPro::TMPro.TextMeshPro
|
||||||
|
m_Material: {fileID: 0}
|
||||||
|
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
m_RaycastTarget: 1
|
||||||
|
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
m_Maskable: 1
|
||||||
|
m_OnCullStateChanged:
|
||||||
|
m_PersistentCalls:
|
||||||
|
m_Calls: []
|
||||||
|
m_text: Sample text
|
||||||
|
m_isRightToLeft: 0
|
||||||
|
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||||
|
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||||
|
m_fontSharedMaterials: []
|
||||||
|
m_fontMaterial: {fileID: 0}
|
||||||
|
m_fontMaterials: []
|
||||||
|
m_fontColor32:
|
||||||
|
serializedVersion: 2
|
||||||
|
rgba: 4294967295
|
||||||
|
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
m_enableVertexGradient: 0
|
||||||
|
m_colorMode: 3
|
||||||
|
m_fontColorGradient:
|
||||||
|
topLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
topRight: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
bottomRight: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
m_fontColorGradientPreset: {fileID: 0}
|
||||||
|
m_spriteAsset: {fileID: 0}
|
||||||
|
m_tintAllSprites: 0
|
||||||
|
m_StyleSheet: {fileID: 0}
|
||||||
|
m_TextStyleHashCode: -1183493901
|
||||||
|
m_overrideHtmlColors: 0
|
||||||
|
m_faceColor:
|
||||||
|
serializedVersion: 2
|
||||||
|
rgba: 4294967295
|
||||||
|
m_fontSize: 150
|
||||||
|
m_fontSizeBase: 150
|
||||||
|
m_fontWeight: 400
|
||||||
|
m_enableAutoSizing: 0
|
||||||
|
m_fontSizeMin: 18
|
||||||
|
m_fontSizeMax: 72
|
||||||
|
m_fontStyle: 0
|
||||||
|
m_HorizontalAlignment: 2
|
||||||
|
m_VerticalAlignment: 512
|
||||||
|
m_textAlignment: 65535
|
||||||
|
m_characterSpacing: 0
|
||||||
|
m_characterHorizontalScale: 1
|
||||||
|
m_wordSpacing: 0
|
||||||
|
m_lineSpacing: 0
|
||||||
|
m_lineSpacingMax: 0
|
||||||
|
m_paragraphSpacing: 0
|
||||||
|
m_charWidthMaxAdj: 0
|
||||||
|
m_TextWrappingMode: 1
|
||||||
|
m_wordWrappingRatios: 0.4
|
||||||
|
m_overflowMode: 0
|
||||||
|
m_linkedTextComponent: {fileID: 0}
|
||||||
|
parentLinkedComponent: {fileID: 0}
|
||||||
|
m_enableKerning: 0
|
||||||
|
m_ActiveFontFeatures: 6e72656b
|
||||||
|
m_enableExtraPadding: 0
|
||||||
|
checkPaddingRequired: 0
|
||||||
|
m_isRichText: 1
|
||||||
|
m_EmojiFallbackSupport: 1
|
||||||
|
m_parseCtrlCharacters: 1
|
||||||
|
m_isOrthographic: 0
|
||||||
|
m_isCullingEnabled: 0
|
||||||
|
m_horizontalMapping: 0
|
||||||
|
m_verticalMapping: 0
|
||||||
|
m_uvLineOffset: 0
|
||||||
|
m_geometrySortingOrder: 0
|
||||||
|
m_IsTextObjectScaleStatic: 0
|
||||||
|
m_VertexBufferAutoSizeReduction: 0
|
||||||
|
m_useMaxVisibleDescender: 1
|
||||||
|
m_pageToDisplay: 1
|
||||||
|
m_margin: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
m_isUsingLegacyAnimationComponent: 0
|
||||||
|
m_isVolumetricText: 0
|
||||||
|
_SortingLayer: 0
|
||||||
|
_SortingLayerID: 0
|
||||||
|
_SortingOrder: 0
|
||||||
|
m_hasFontAssetChanged: 0
|
||||||
|
m_renderer: {fileID: 4372620151762523236}
|
||||||
|
m_maskType: 0
|
||||||
|
--- !u!65 &2810473078386703306
|
||||||
|
BoxCollider:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 1550415954014096864}
|
||||||
|
m_Material: {fileID: 0}
|
||||||
|
m_IncludeLayers:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Bits: 0
|
||||||
|
m_ExcludeLayers:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Bits: 0
|
||||||
|
m_LayerOverridePriority: 0
|
||||||
|
m_IsTrigger: 0
|
||||||
|
m_ProvidesContacts: 0
|
||||||
|
m_Enabled: 1
|
||||||
|
serializedVersion: 3
|
||||||
|
m_Size: {x: 100, y: 20, z: 4}
|
||||||
|
m_Center: {x: 0, y: 0, z: 0}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e30711fd9b66695439ed306d6259baf3
|
||||||
|
PrefabImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: af84361be91d60641aa5efca93697051
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -5658,10 +5658,8 @@ GameObject:
|
|||||||
- component: {fileID: 360436926}
|
- component: {fileID: 360436926}
|
||||||
- component: {fileID: 360436927}
|
- component: {fileID: 360436927}
|
||||||
- component: {fileID: 360436928}
|
- component: {fileID: 360436928}
|
||||||
- component: {fileID: 360436929}
|
|
||||||
- component: {fileID: 360436931}
|
|
||||||
- component: {fileID: 360436930}
|
- component: {fileID: 360436930}
|
||||||
- component: {fileID: 360436932}
|
- component: {fileID: 360436931}
|
||||||
m_Layer: 10
|
m_Layer: 10
|
||||||
m_Name: RoomB
|
m_Name: RoomB
|
||||||
m_TagString: Untagged
|
m_TagString: Untagged
|
||||||
@@ -5707,58 +5705,58 @@ MonoBehaviour:
|
|||||||
_maxBounds: {x: 19, y: 0, z: 20}
|
_maxBounds: {x: 19, y: 0, z: 20}
|
||||||
_tilesRoot: {fileID: 2138324238}
|
_tilesRoot: {fileID: 2138324238}
|
||||||
_tiles:
|
_tiles:
|
||||||
- {fileID: 616022719}
|
|
||||||
- {fileID: 547887412}
|
|
||||||
- {fileID: 1292076245}
|
|
||||||
- {fileID: 81303610}
|
|
||||||
- {fileID: 1556111475}
|
|
||||||
- {fileID: 466646084}
|
|
||||||
- {fileID: 726912091}
|
|
||||||
- {fileID: 202558941}
|
- {fileID: 202558941}
|
||||||
- {fileID: 18266763}
|
- {fileID: 18266763}
|
||||||
- {fileID: 113951836}
|
|
||||||
- {fileID: 1359493433}
|
|
||||||
- {fileID: 672345281}
|
|
||||||
- {fileID: 2124187222}
|
|
||||||
- {fileID: 1805577975}
|
|
||||||
- {fileID: 2018221532}
|
|
||||||
- {fileID: 719594784}
|
|
||||||
- {fileID: 821635054}
|
|
||||||
- {fileID: 313816134}
|
|
||||||
- {fileID: 797045252}
|
|
||||||
- {fileID: 1534650363}
|
|
||||||
- {fileID: 119900065}
|
|
||||||
- {fileID: 1596512284}
|
|
||||||
- {fileID: 701311839}
|
|
||||||
- {fileID: 1858599999}
|
- {fileID: 1858599999}
|
||||||
- {fileID: 947318234}
|
- {fileID: 701311839}
|
||||||
- {fileID: 562500083}
|
|
||||||
- {fileID: 1488568118}
|
|
||||||
- {fileID: 1049095639}
|
|
||||||
- {fileID: 571092902}
|
|
||||||
- {fileID: 550008352}
|
|
||||||
- {fileID: 320835867}
|
|
||||||
- {fileID: 1573784960}
|
|
||||||
- {fileID: 368130861}
|
|
||||||
- {fileID: 771312550}
|
|
||||||
- {fileID: 1077265498}
|
|
||||||
- {fileID: 1966203162}
|
|
||||||
- {fileID: 978214104}
|
|
||||||
- {fileID: 1490835241}
|
|
||||||
- {fileID: 907046323}
|
|
||||||
- {fileID: 223660540}
|
|
||||||
- {fileID: 531406861}
|
|
||||||
- {fileID: 795382345}
|
|
||||||
- {fileID: 1067276305}
|
|
||||||
- {fileID: 695066148}
|
|
||||||
- {fileID: 152452649}
|
|
||||||
- {fileID: 1916111538}
|
|
||||||
- {fileID: 1854904808}
|
|
||||||
- {fileID: 715398034}
|
|
||||||
- {fileID: 197403794}
|
|
||||||
- {fileID: 185205363}
|
|
||||||
- {fileID: 1776065554}
|
- {fileID: 1776065554}
|
||||||
- {fileID: 1515469345}
|
- {fileID: 1515469345}
|
||||||
|
- {fileID: 1292076245}
|
||||||
|
- {fileID: 947318234}
|
||||||
|
- {fileID: 616022719}
|
||||||
|
- {fileID: 547887412}
|
||||||
|
- {fileID: 113951836}
|
||||||
|
- {fileID: 562500083}
|
||||||
|
- {fileID: 1488568118}
|
||||||
|
- {fileID: 368130861}
|
||||||
|
- {fileID: 1556111475}
|
||||||
|
- {fileID: 1049095639}
|
||||||
|
- {fileID: 571092902}
|
||||||
|
- {fileID: 223660540}
|
||||||
|
- {fileID: 1573784960}
|
||||||
|
- {fileID: 550008352}
|
||||||
|
- {fileID: 466646084}
|
||||||
|
- {fileID: 726912091}
|
||||||
|
- {fileID: 1966203162}
|
||||||
|
- {fileID: 771312550}
|
||||||
|
- {fileID: 152452649}
|
||||||
|
- {fileID: 1077265498}
|
||||||
|
- {fileID: 313816134}
|
||||||
|
- {fileID: 978214104}
|
||||||
|
- {fileID: 197403794}
|
||||||
|
- {fileID: 1359493433}
|
||||||
|
- {fileID: 119900065}
|
||||||
|
- {fileID: 1490835241}
|
||||||
|
- {fileID: 2124187222}
|
||||||
|
- {fileID: 672345281}
|
||||||
|
- {fileID: 185205363}
|
||||||
|
- {fileID: 1805577975}
|
||||||
|
- {fileID: 907046323}
|
||||||
|
- {fileID: 2018221532}
|
||||||
|
- {fileID: 531406861}
|
||||||
|
- {fileID: 795382345}
|
||||||
|
- {fileID: 719594784}
|
||||||
|
- {fileID: 1067276305}
|
||||||
|
- {fileID: 1916111538}
|
||||||
|
- {fileID: 81303610}
|
||||||
|
- {fileID: 1854904808}
|
||||||
|
- {fileID: 695066148}
|
||||||
|
- {fileID: 821635054}
|
||||||
|
- {fileID: 715398034}
|
||||||
|
- {fileID: 1534650363}
|
||||||
|
- {fileID: 320835867}
|
||||||
|
- {fileID: 797045252}
|
||||||
|
- {fileID: 1596512284}
|
||||||
_floors:
|
_floors:
|
||||||
- Columns:
|
- Columns:
|
||||||
- Rows:
|
- Rows:
|
||||||
@@ -5850,29 +5848,8 @@ BoxCollider:
|
|||||||
m_ProvidesContacts: 0
|
m_ProvidesContacts: 0
|
||||||
m_Enabled: 1
|
m_Enabled: 1
|
||||||
serializedVersion: 3
|
serializedVersion: 3
|
||||||
m_Size: {x: 5, y: 3, z: 6}
|
m_Size: {x: 5.76, y: 3, z: 7.89}
|
||||||
m_Center: {x: 3, y: 2, z: -2}
|
m_Center: {x: 3, y: 2, z: -2}
|
||||||
--- !u!114 &360436929
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 360436924}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: f33be20afd5d4c843a800ba1d8dd8437, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier: Assembly-CSharp::Unheimlich.Interactions.Dialogues.DialogueTriggerZone
|
|
||||||
_playerTag: Player
|
|
||||||
_gizmoColor: {r: 0.8, g: 0.5, b: 0, a: 0.35}
|
|
||||||
_conversation: {fileID: 11400000, guid: ebd856967a3b7d342a7d4a3a17c6149f, type: 2}
|
|
||||||
_isRetriggerable: 1
|
|
||||||
_pauseOnExit: 1
|
|
||||||
_floatingWordAnchor: {fileID: 1029059055}
|
|
||||||
_animationSettings: {fileID: 11400000, guid: da7719558573c894e81bd9b85400681b, type: 2}
|
|
||||||
_localDialogueUI: {fileID: 1029059056}
|
|
||||||
_enableBlurEffect: 1
|
|
||||||
--- !u!114 &360436930
|
--- !u!114 &360436930
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -5888,6 +5865,10 @@ MonoBehaviour:
|
|||||||
_playerTag: Player
|
_playerTag: Player
|
||||||
_gizmoColor: {r: 0.8, g: 0.5, b: 0, a: 0.35}
|
_gizmoColor: {r: 0.8, g: 0.5, b: 0, a: 0.35}
|
||||||
_retriggerable: 1
|
_retriggerable: 1
|
||||||
|
_delay: 0
|
||||||
|
_insanityAmount: 0
|
||||||
|
_hallucinationEvent: {fileID: 11400000, guid: 11ffb12bd28a98f40a40a63db49d7df3, type: 2}
|
||||||
|
_debugMode: 0
|
||||||
--- !u!114 &360436931
|
--- !u!114 &360436931
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -5897,31 +5878,18 @@ MonoBehaviour:
|
|||||||
m_GameObject: {fileID: 360436924}
|
m_GameObject: {fileID: 360436924}
|
||||||
m_Enabled: 1
|
m_Enabled: 1
|
||||||
m_EditorHideFlags: 0
|
m_EditorHideFlags: 0
|
||||||
m_Script: {fileID: 11500000, guid: 358c75d041ea30a4ab85380893077e70, type: 3}
|
m_Script: {fileID: 11500000, guid: f33be20afd5d4c843a800ba1d8dd8437, type: 3}
|
||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier: Assembly-CSharp::Unheimlich.Core.Events.GameEventTrigger
|
m_EditorClassIdentifier: Assembly-CSharp::Unheimlich.Features.Dialogue.DialogueTriggerZone
|
||||||
_fireOnStart: 0
|
_playerTag: Player
|
||||||
_fireOnEnable: 0
|
_gizmoColor: {r: 0.33852464, g: 0.8, b: 0, a: 0.35}
|
||||||
_delay: 0
|
_conversation: {fileID: 11400000, guid: ebd856967a3b7d342a7d4a3a17c6149f, type: 2}
|
||||||
_fireOnlyOnce: 0
|
_isRetriggerable: 1
|
||||||
_onTriggered:
|
_pauseOnExit: 1
|
||||||
m_PersistentCalls:
|
_floatingWordAnchor: {fileID: 1029059055}
|
||||||
m_Calls: []
|
_animationSettings: {fileID: 11400000, guid: da7719558573c894e81bd9b85400681b, type: 2}
|
||||||
--- !u!114 &360436932
|
_localDialogueUI: {fileID: 1029059056}
|
||||||
MonoBehaviour:
|
_enableBlurEffect: 1
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 360436924}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: 5e1119e5c406d0346b0350dbcc91845f, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier: Assembly-CSharp::Unheimlich.Features.Hallucination.HallucinationTrigger
|
|
||||||
_insanityAmount: 0.2
|
|
||||||
_hallucinationEvent: {fileID: 11400000, guid: 11ffb12bd28a98f40a40a63db49d7df3, type: 2}
|
|
||||||
_debugMode: 0
|
|
||||||
--- !u!1001 &362081299
|
--- !u!1001 &362081299
|
||||||
PrefabInstance:
|
PrefabInstance:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
|||||||
@@ -0,0 +1,156 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Unheimlich.Core.Audio
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Base class for components that react to an AudioSource's playback state.
|
||||||
|
/// Supports three fire conditions: OnPlay, OnFinish, and OnTimeReached.
|
||||||
|
/// Subclasses implement Execute() to define what happens when the condition is met.
|
||||||
|
/// </summary>
|
||||||
|
[RequireComponent(typeof(AudioSource))]
|
||||||
|
public abstract class AudioTriggerBase : MonoBehaviour
|
||||||
|
{
|
||||||
|
public enum FireCondition
|
||||||
|
{
|
||||||
|
/// <summary>Fire as soon as the audio starts playing.</summary>
|
||||||
|
OnPlay,
|
||||||
|
/// <summary>Fire when the audio clip finishes.</summary>
|
||||||
|
OnFinish,
|
||||||
|
/// <summary>Fire when playback reaches a specific timestamp.</summary>
|
||||||
|
OnTimeReached
|
||||||
|
}
|
||||||
|
|
||||||
|
[Header("Audio Trigger")]
|
||||||
|
[Tooltip("When to fire the effect")]
|
||||||
|
[SerializeField] protected FireCondition _fireCondition = FireCondition.OnPlay;
|
||||||
|
|
||||||
|
[Tooltip("Playback time in seconds that triggers the effect (OnTimeReached only)")]
|
||||||
|
[SerializeField] protected float _triggerTime = 1f;
|
||||||
|
|
||||||
|
[Header("Behaviour")]
|
||||||
|
[Tooltip("Prevent firing more than once per session")]
|
||||||
|
[SerializeField] protected bool _fireOnlyOnce = true;
|
||||||
|
|
||||||
|
[Header("Debug")]
|
||||||
|
[SerializeField] protected bool _debugMode;
|
||||||
|
|
||||||
|
protected AudioSource AudioSource { get; private set; }
|
||||||
|
|
||||||
|
private bool _hasFired;
|
||||||
|
private bool _isMonitoring;
|
||||||
|
private Coroutine _finishWatcher;
|
||||||
|
|
||||||
|
protected virtual void Awake()
|
||||||
|
{
|
||||||
|
AudioSource = GetComponent<AudioSource>();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void OnEnable()
|
||||||
|
{
|
||||||
|
_hasFired = false;
|
||||||
|
_isMonitoring = false;
|
||||||
|
|
||||||
|
if (AudioSource != null && AudioSource.isPlaying)
|
||||||
|
StartMonitoring();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void OnDisable()
|
||||||
|
{
|
||||||
|
StopMonitoring();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── Public API ────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Notify this component that the AudioSource has started playing.
|
||||||
|
/// Wire this to whatever code or event starts the AudioSource.
|
||||||
|
/// </summary>
|
||||||
|
public void OnAudioPlay()
|
||||||
|
{
|
||||||
|
StartMonitoring();
|
||||||
|
|
||||||
|
if (_fireCondition == FireCondition.OnPlay)
|
||||||
|
TryExecute();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Resets the fired state so this can fire again.</summary>
|
||||||
|
public void ResetFired()
|
||||||
|
{
|
||||||
|
_hasFired = false;
|
||||||
|
StopMonitoring();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── Monitoring ────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
private void StartMonitoring()
|
||||||
|
{
|
||||||
|
_isMonitoring = true;
|
||||||
|
|
||||||
|
if (_fireCondition == FireCondition.OnFinish)
|
||||||
|
{
|
||||||
|
StopMonitoring();
|
||||||
|
_finishWatcher = StartCoroutine(WatchForFinish());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StopMonitoring()
|
||||||
|
{
|
||||||
|
_isMonitoring = false;
|
||||||
|
|
||||||
|
if (_finishWatcher != null)
|
||||||
|
{
|
||||||
|
StopCoroutine(_finishWatcher);
|
||||||
|
_finishWatcher = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Update()
|
||||||
|
{
|
||||||
|
if (!_isMonitoring || (_fireOnlyOnce && _hasFired))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_fireCondition != FireCondition.OnTimeReached)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (AudioSource != null && AudioSource.isPlaying && AudioSource.time >= _triggerTime)
|
||||||
|
TryExecute();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uses a coroutine instead of Update polling so the finish detection is frame-accurate
|
||||||
|
// even for very short clips that could end between two Update calls.
|
||||||
|
private IEnumerator WatchForFinish()
|
||||||
|
{
|
||||||
|
if (AudioSource == null)
|
||||||
|
yield break;
|
||||||
|
|
||||||
|
// Wait until the clip actually has a length to work with
|
||||||
|
yield return null;
|
||||||
|
|
||||||
|
if (AudioSource.clip != null)
|
||||||
|
yield return new WaitForSeconds(AudioSource.clip.length);
|
||||||
|
else
|
||||||
|
yield return new WaitUntil(() => !AudioSource.isPlaying);
|
||||||
|
|
||||||
|
TryExecute();
|
||||||
|
_finishWatcher = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── Internal ──────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
private void TryExecute()
|
||||||
|
{
|
||||||
|
if (_fireOnlyOnce && _hasFired)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_hasFired = true;
|
||||||
|
StopMonitoring();
|
||||||
|
Execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when the fire condition is met. Implement the payload here.
|
||||||
|
/// </summary>
|
||||||
|
protected abstract void Execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 16d04d63a4903d54dbd0eee78c2ba121
|
||||||
@@ -22,23 +22,23 @@ namespace Unheimlich.Core.Interaction
|
|||||||
_playerCamera = GetComponent<Camera>();
|
_playerCamera = GetComponent<Camera>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool _didHit;
|
||||||
|
|
||||||
private void Update()
|
private void Update()
|
||||||
{
|
{
|
||||||
if (RaycastHelper.ThrottledRaycastComponent(
|
_didHit = RaycastHelper.ThrottledRaycastComponent(
|
||||||
ref _raycastTimer,
|
ref _raycastTimer,
|
||||||
_raycastInterval,
|
_raycastInterval,
|
||||||
_playerCamera,
|
_playerCamera,
|
||||||
_interactionRange,
|
_interactionRange,
|
||||||
_interactableLayers,
|
_interactableLayers,
|
||||||
out InteractableBase interactable))
|
out InteractableBase interactable);
|
||||||
{
|
|
||||||
|
if (_didHit)
|
||||||
_currentInteractable = interactable;
|
_currentInteractable = interactable;
|
||||||
}
|
else if (!_didHit && _raycastTimer <= 0f)
|
||||||
else if (_raycastTimer == 0f)
|
|
||||||
{
|
|
||||||
_currentInteractable = null;
|
_currentInteractable = null;
|
||||||
}
|
|
||||||
|
|
||||||
HandleInteractionInput();
|
HandleInteractionInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -85,8 +85,6 @@ namespace Unheimlich.Core.Interaction
|
|||||||
|
|
||||||
private void ResetSessionState()
|
private void ResetSessionState()
|
||||||
{
|
{
|
||||||
// Force-despawn any leftover words from the previous session
|
|
||||||
// (their GOs were destroyed but _spawnedWords list may still have stale entries).
|
|
||||||
if (_isActive)
|
if (_isActive)
|
||||||
{
|
{
|
||||||
foreach (var word in _spawnedWords)
|
foreach (var word in _spawnedWords)
|
||||||
@@ -103,19 +101,19 @@ namespace Unheimlich.Core.Interaction
|
|||||||
_isActive = false;
|
_isActive = false;
|
||||||
_isMerged = false;
|
_isMerged = false;
|
||||||
_hasBeenMergedOnce = false;
|
_hasBeenMergedOnce = false;
|
||||||
// _hasCompletedMergeOnce intentionally NOT reset here — persists during session
|
_hasCompletedMergeOnce = false; // reset so MergeOnce objects start fresh each session
|
||||||
// so a merged object stays merged when the player re-enters its activation range.
|
|
||||||
// It is only reset at the start of a new Play Mode session (see OnPlayModeReset).
|
|
||||||
_currentConvergenceRadius = 0f;
|
_currentConvergenceRadius = 0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resets _hasCompletedMergeOnce at the very start of each Play Mode session,
|
// Resets _hasCompletedMergeOnce at the very start of each Play Mode session so
|
||||||
// before any scene loads, so objects start fresh without full Domain Reload.
|
// merged objects start fresh without requiring a full Domain Reload.
|
||||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
|
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
|
||||||
private static void OnPlayModeReset()
|
private static void OnPlayModeReset()
|
||||||
{
|
{
|
||||||
// Static reset — instance fields will be re-initialized by Awake/Start naturally.
|
// Finding all instances isn't possible from a static context with SubsystemRegistration.
|
||||||
// No instance access needed here; ResetSessionState() handles the rest on OnEnable.
|
// The reset is handled per-instance in OnEnable via _hasCompletedMergeOnce being
|
||||||
|
// re-initialized when the scene reloads. For Enter Play Mode without scene reload,
|
||||||
|
// ResetSessionState() is called from OnEnable and now correctly clears the flag.
|
||||||
}
|
}
|
||||||
|
|
||||||
void Update()
|
void Update()
|
||||||
|
|||||||
+19
-94
@@ -1,115 +1,40 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using Unheimlich.Core.Audio;
|
||||||
using Unheimlich.Features.DetectiveBoard.Data;
|
using Unheimlich.Features.DetectiveBoard.Data;
|
||||||
using Unheimlich.Features.DetectiveBoard;
|
|
||||||
|
|
||||||
namespace Unheimlich.Features.DetectiveBoard
|
namespace Unheimlich.Features.DetectiveBoard
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Unlocks a clue when a specific audio source plays or finishes playing.
|
/// Unlocks a clue when a specific AudioSource plays, finishes, or reaches a timestamp.
|
||||||
/// Useful for triggering clues based on environmental sounds, dialogue, or hallucinations.
|
/// Call OnAudioPlay() from whatever drives the AudioSource to start monitoring.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[RequireComponent(typeof(AudioSource))]
|
public class ClueUnlockOnAudio : AudioTriggerBase
|
||||||
public class ClueUnlockOnAudio : MonoBehaviour
|
|
||||||
{
|
{
|
||||||
public enum UnlockTrigger
|
|
||||||
{
|
|
||||||
OnPlay,
|
|
||||||
OnFinish,
|
|
||||||
OnTimeReached
|
|
||||||
}
|
|
||||||
|
|
||||||
[Header("Clue Configuration")]
|
[Header("Clue Configuration")]
|
||||||
[Tooltip("The clue to unlock")]
|
[Tooltip("The clue to unlock")]
|
||||||
[SerializeField] private ClueData _clueToUnlock;
|
[SerializeField] private ClueData _clueToUnlock;
|
||||||
|
|
||||||
[Header("Audio Trigger")]
|
protected override void Execute()
|
||||||
[Tooltip("When to unlock the clue")]
|
|
||||||
[SerializeField] private UnlockTrigger _trigger = UnlockTrigger.OnPlay;
|
|
||||||
|
|
||||||
[Tooltip("Time in seconds to wait before unlocking (only for OnTimeReached)")]
|
|
||||||
[SerializeField] private float _unlockTime = 1f;
|
|
||||||
|
|
||||||
private AudioSource _audioSource;
|
|
||||||
private bool _hasUnlocked;
|
|
||||||
private bool _isMonitoring;
|
|
||||||
private float _currentTime;
|
|
||||||
|
|
||||||
private void Awake()
|
|
||||||
{
|
{
|
||||||
_audioSource = GetComponent<AudioSource>();
|
if (_clueToUnlock == null)
|
||||||
}
|
|
||||||
|
|
||||||
private void OnEnable()
|
|
||||||
{
|
|
||||||
if (_audioSource != null && _audioSource.isPlaying)
|
|
||||||
{
|
{
|
||||||
StartMonitoring();
|
Debug.LogError("[ClueUnlockOnAudio] No ClueData assigned!", this);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Update()
|
|
||||||
{
|
|
||||||
if (!_isMonitoring || _hasUnlocked)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (_audioSource == null || !_audioSource.isPlaying)
|
|
||||||
{
|
|
||||||
if (_trigger == UnlockTrigger.OnFinish && _isMonitoring)
|
|
||||||
{
|
|
||||||
UnlockClue();
|
|
||||||
}
|
|
||||||
_isMonitoring = false;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_currentTime = _audioSource.time;
|
if (DetectiveBoardManager.Instance == null)
|
||||||
|
|
||||||
if (_trigger == UnlockTrigger.OnTimeReached && _currentTime >= _unlockTime)
|
|
||||||
{
|
{
|
||||||
UnlockClue();
|
Debug.LogError("[ClueUnlockOnAudio] DetectiveBoardManager not found!", this);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Call this when the audio starts playing.
|
|
||||||
/// </summary>
|
|
||||||
public void OnAudioPlay()
|
|
||||||
{
|
|
||||||
StartMonitoring();
|
|
||||||
|
|
||||||
if (_trigger == UnlockTrigger.OnPlay)
|
|
||||||
{
|
|
||||||
UnlockClue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void StartMonitoring()
|
|
||||||
{
|
|
||||||
_isMonitoring = true;
|
|
||||||
_currentTime = 0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UnlockClue()
|
|
||||||
{
|
|
||||||
if (_hasUnlocked || _clueToUnlock == null)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (DetectiveBoardManager.Instance != null)
|
|
||||||
{
|
|
||||||
DetectiveBoardManager.Instance.UnlockClue(_clueToUnlock);
|
|
||||||
_hasUnlocked = true;
|
|
||||||
|
|
||||||
Debug.Log($"[ClueUnlockOnAudio] Unlocked clue: {_clueToUnlock.Title} via audio trigger");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DetectiveBoardManager.Instance.UnlockClue(_clueToUnlock);
|
||||||
|
|
||||||
|
if (_debugMode)
|
||||||
|
Debug.Log($"[ClueUnlockOnAudio] Unlocked clue '{_clueToUnlock.Title}' on '{_fireCondition}'.", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Resets the unlock state so the clue can be unlocked again.</summary>
|
||||||
/// Resets the unlock state.
|
public void ResetUnlock() => ResetFired();
|
||||||
/// </summary>
|
|
||||||
public void ResetUnlock()
|
|
||||||
{
|
|
||||||
_hasUnlocked = false;
|
|
||||||
_isMonitoring = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ namespace Unheimlich.Features.Dialogue
|
|||||||
public DialogueConversation CurrentConversation => _currentConversation;
|
public DialogueConversation CurrentConversation => _currentConversation;
|
||||||
public DialogueNode CurrentNode => _currentNode;
|
public DialogueNode CurrentNode => _currentNode;
|
||||||
|
|
||||||
|
private bool _blurEnabled;
|
||||||
|
|
||||||
public event Action<DialogueChoiceData> OnChoiceMade;
|
public event Action<DialogueChoiceData> OnChoiceMade;
|
||||||
public event Action<object> OnDialogueCompleted;
|
public event Action<object> OnDialogueCompleted;
|
||||||
|
|
||||||
@@ -132,11 +134,9 @@ namespace Unheimlich.Features.Dialogue
|
|||||||
|
|
||||||
IsInDialogue = false;
|
IsInDialogue = false;
|
||||||
_isWaitingForAutoClose = false;
|
_isWaitingForAutoClose = false;
|
||||||
|
|
||||||
if (DialogueBlurEffectURP.Instance != null)
|
if (_blurEnabled && DialogueBlurEffectURP.Instance != null)
|
||||||
{
|
|
||||||
DialogueBlurEffectURP.Instance.HideBlur();
|
DialogueBlurEffectURP.Instance.HideBlur();
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -154,7 +154,7 @@ namespace Unheimlich.Features.Dialogue
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StartConversation(DialogueConversation conversation, Transform choiceAnchor = null, DialogueAnimationSettings animationSettings = null, DialogueUI customDialogueUI = null, object owner = null)
|
public void StartConversation(DialogueConversation conversation, Transform choiceAnchor = null, DialogueAnimationSettings animationSettings = null, DialogueUI customDialogueUI = null, object owner = null, bool showBlur = false)
|
||||||
{
|
{
|
||||||
if (conversation == null)
|
if (conversation == null)
|
||||||
{
|
{
|
||||||
@@ -175,6 +175,7 @@ namespace Unheimlich.Features.Dialogue
|
|||||||
_currentAnimationSettings = animationSettings;
|
_currentAnimationSettings = animationSettings;
|
||||||
_activeDialogueUI = customDialogueUI;
|
_activeDialogueUI = customDialogueUI;
|
||||||
CurrentOwner = owner;
|
CurrentOwner = owner;
|
||||||
|
_blurEnabled = showBlur;
|
||||||
|
|
||||||
if (_activeDialogueUI == null)
|
if (_activeDialogueUI == null)
|
||||||
{
|
{
|
||||||
@@ -182,6 +183,10 @@ namespace Unheimlich.Features.Dialogue
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_blurEnabled && DialogueBlurEffectURP.Instance != null)
|
||||||
|
DialogueBlurEffectURP.Instance.ShowBlur();
|
||||||
|
|
||||||
|
PlayerEvents.TriggerEnterDialogue();
|
||||||
ShowCurrentNode();
|
ShowCurrentNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,13 +264,14 @@ namespace Unheimlich.Features.Dialogue
|
|||||||
public void EndDialogue()
|
public void EndDialogue()
|
||||||
{
|
{
|
||||||
IsInDialogue = false;
|
IsInDialogue = false;
|
||||||
|
|
||||||
if (_activeDialogueUI != null)
|
if (_activeDialogueUI != null)
|
||||||
_activeDialogueUI.HideDialogueBox();
|
_activeDialogueUI.HideDialogueBox();
|
||||||
|
|
||||||
if (DialogueBlurEffectURP.Instance != null)
|
if (_blurEnabled && DialogueBlurEffectURP.Instance != null)
|
||||||
DialogueBlurEffectURP.Instance.HideBlur();
|
DialogueBlurEffectURP.Instance.HideBlur();
|
||||||
|
|
||||||
|
PlayerEvents.TriggerExitDialogue();
|
||||||
CleanupDialogue();
|
CleanupDialogue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,7 +281,8 @@ namespace Unheimlich.Features.Dialogue
|
|||||||
_currentAnimationSettings = null;
|
_currentAnimationSettings = null;
|
||||||
_activeDialogueUI = null;
|
_activeDialogueUI = null;
|
||||||
CurrentOwner = null;
|
CurrentOwner = null;
|
||||||
|
_blurEnabled = false;
|
||||||
|
|
||||||
_currentConversation = null;
|
_currentConversation = null;
|
||||||
_currentNode = null;
|
_currentNode = null;
|
||||||
_autoCloseTimer = 0f;
|
_autoCloseTimer = 0f;
|
||||||
|
|||||||
@@ -60,9 +60,6 @@ namespace Unheimlich.Features.Dialogue
|
|||||||
if (_dialogueState.HasPausedDialogue)
|
if (_dialogueState.HasPausedDialogue)
|
||||||
{
|
{
|
||||||
_dialogueState.ResumeDialogue();
|
_dialogueState.ResumeDialogue();
|
||||||
|
|
||||||
if (_enableBlurEffect && DialogueBlurEffectURP.Instance != null)
|
|
||||||
DialogueBlurEffectURP.Instance.ShowBlur();
|
|
||||||
}
|
}
|
||||||
else if (!_hasTriggered || (_isRetriggerable && _dialogueState.IsCompleted))
|
else if (!_hasTriggered || (_isRetriggerable && _dialogueState.IsCompleted))
|
||||||
{
|
{
|
||||||
@@ -75,12 +72,7 @@ namespace Unheimlich.Features.Dialogue
|
|||||||
if (_pauseOnExit && DialogueManager.Instance != null && DialogueManager.Instance.IsDialogueActive)
|
if (_pauseOnExit && DialogueManager.Instance != null && DialogueManager.Instance.IsDialogueActive)
|
||||||
{
|
{
|
||||||
if ((Object)DialogueManager.Instance.CurrentOwner == this)
|
if ((Object)DialogueManager.Instance.CurrentOwner == this)
|
||||||
{
|
|
||||||
_dialogueState.PauseDialogue();
|
_dialogueState.PauseDialogue();
|
||||||
|
|
||||||
if (_enableBlurEffect && DialogueBlurEffectURP.Instance != null)
|
|
||||||
DialogueBlurEffectURP.Instance.HideBlur();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,19 +92,15 @@ namespace Unheimlich.Features.Dialogue
|
|||||||
|
|
||||||
_hasTriggered = true;
|
_hasTriggered = true;
|
||||||
|
|
||||||
if (_enableBlurEffect && DialogueBlurEffectURP.Instance != null)
|
|
||||||
{
|
|
||||||
DialogueBlurEffectURP.Instance.ShowBlur();
|
|
||||||
}
|
|
||||||
|
|
||||||
DialogueManager.Instance.StartConversation(
|
DialogueManager.Instance.StartConversation(
|
||||||
_conversation,
|
_conversation,
|
||||||
_floatingWordAnchor,
|
_floatingWordAnchor,
|
||||||
_animationSettings,
|
_animationSettings,
|
||||||
_localDialogueUI,
|
_localDialogueUI,
|
||||||
this
|
this,
|
||||||
|
_enableBlurEffect
|
||||||
);
|
);
|
||||||
|
|
||||||
DialogueManager.Instance.OnDialogueCompleted += OnDialogueCompleted;
|
DialogueManager.Instance.OnDialogueCompleted += OnDialogueCompleted;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,9 +115,6 @@ namespace Unheimlich.Features.Dialogue
|
|||||||
_hasTriggered = false;
|
_hasTriggered = false;
|
||||||
_dialogueState.AllowRetrigger();
|
_dialogueState.AllowRetrigger();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_enableBlurEffect && DialogueBlurEffectURP.Instance != null)
|
|
||||||
DialogueBlurEffectURP.Instance.HideBlur();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DialogueManager.Instance != null)
|
if (DialogueManager.Instance != null)
|
||||||
|
|||||||
@@ -86,9 +86,6 @@ namespace Unheimlich.Features.Dialogue
|
|||||||
_dialogueState.ResumeDialogue();
|
_dialogueState.ResumeDialogue();
|
||||||
DialogueManager.Instance.OnDialogueCompleted += OnDialogueCompleted;
|
DialogueManager.Instance.OnDialogueCompleted += OnDialogueCompleted;
|
||||||
_isDialogueActive = true;
|
_isDialogueActive = true;
|
||||||
|
|
||||||
if (_enableBlurEffect && DialogueBlurEffectURP.Instance != null)
|
|
||||||
DialogueBlurEffectURP.Instance.ShowBlur();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -98,12 +95,16 @@ namespace Unheimlich.Features.Dialogue
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DialogueManager.Instance.StartConversation(Conversation, _floatingWordAnchor, _animationSettings, _localDialogueUI, this);
|
DialogueManager.Instance.StartConversation(
|
||||||
|
Conversation,
|
||||||
|
_floatingWordAnchor,
|
||||||
|
_animationSettings,
|
||||||
|
_localDialogueUI,
|
||||||
|
this,
|
||||||
|
_enableBlurEffect
|
||||||
|
);
|
||||||
DialogueManager.Instance.OnDialogueCompleted += OnDialogueCompleted;
|
DialogueManager.Instance.OnDialogueCompleted += OnDialogueCompleted;
|
||||||
_isDialogueActive = true;
|
_isDialogueActive = true;
|
||||||
|
|
||||||
if (_enableBlurEffect && DialogueBlurEffectURP.Instance != null)
|
|
||||||
DialogueBlurEffectURP.Instance.ShowBlur();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,7 +123,7 @@ namespace Unheimlich.Features.Dialogue
|
|||||||
if (DialogueManager.Instance != null)
|
if (DialogueManager.Instance != null)
|
||||||
DialogueManager.Instance.OnDialogueCompleted -= OnDialogueCompleted;
|
DialogueManager.Instance.OnDialogueCompleted -= OnDialogueCompleted;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDestroy()
|
private void OnDestroy()
|
||||||
{
|
{
|
||||||
if (DialogueManager.Instance != null)
|
if (DialogueManager.Instance != null)
|
||||||
|
|||||||
+10
-4
@@ -1,7 +1,8 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.InputSystem;
|
using Unheimlich.Core;
|
||||||
using Unheimlich.Core.Audio;
|
using Unheimlich.Core.Audio;
|
||||||
using Unheimlich.Features.OctoArms;
|
using Unheimlich.Features.OctoArms;
|
||||||
|
using InputManager = Unheimlich.Core.Input.InputManager;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
|
||||||
@@ -73,12 +74,11 @@ public class DiapasonEquipmentManager : MonoBehaviour
|
|||||||
{
|
{
|
||||||
CheckForSoundEmitters();
|
CheckForSoundEmitters();
|
||||||
|
|
||||||
if (Mouse.current != null && Mouse.current.leftButton.wasPressedThisFrame)
|
var fireAction = InputManager.GetFireAction();
|
||||||
|
if (fireAction != null && fireAction.WasPressedThisFrame())
|
||||||
{
|
{
|
||||||
if (CanTap)
|
if (CanTap)
|
||||||
{
|
|
||||||
TapDiapason();
|
TapDiapason();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -200,6 +200,8 @@ public class DiapasonEquipmentManager : MonoBehaviour
|
|||||||
|
|
||||||
private void OnDiapasonEquipped()
|
private void OnDiapasonEquipped()
|
||||||
{
|
{
|
||||||
|
PlayerEvents.TriggerDiapasonEquip();
|
||||||
|
|
||||||
if (_diapasonAnimator != null)
|
if (_diapasonAnimator != null)
|
||||||
{
|
{
|
||||||
_diapasonAnimator.enabled = true;
|
_diapasonAnimator.enabled = true;
|
||||||
@@ -216,6 +218,8 @@ public class DiapasonEquipmentManager : MonoBehaviour
|
|||||||
|
|
||||||
private void OnDiapasonUnequipped()
|
private void OnDiapasonUnequipped()
|
||||||
{
|
{
|
||||||
|
PlayerEvents.TriggerDiapasonUnequip();
|
||||||
|
|
||||||
_isVibrating = false;
|
_isVibrating = false;
|
||||||
_diapasonAnimator = null;
|
_diapasonAnimator = null;
|
||||||
_diapasonParticles = null;
|
_diapasonParticles = null;
|
||||||
@@ -270,6 +274,8 @@ public class DiapasonEquipmentManager : MonoBehaviour
|
|||||||
{
|
{
|
||||||
_currentDetectedEmitter.StartListening(transform.position);
|
_currentDetectedEmitter.StartListening(transform.position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PlayerEvents.TriggerDiapasonTap();
|
||||||
|
|
||||||
if (_vibrationCoroutine != null)
|
if (_vibrationCoroutine != null)
|
||||||
StopCoroutine(_vibrationCoroutine);
|
StopCoroutine(_vibrationCoroutine);
|
||||||
|
|||||||
+4
-21
@@ -42,28 +42,9 @@ namespace Unheimlich.Features.Diapason
|
|||||||
_playerAudioSource = gameObject.AddComponent<AudioSource>();
|
_playerAudioSource = gameObject.AddComponent<AudioSource>();
|
||||||
|
|
||||||
_cameraHeadBob = GetComponentInChildren<CameraHeadBob>();
|
_cameraHeadBob = GetComponentInChildren<CameraHeadBob>();
|
||||||
|
|
||||||
if (PlayerController.Instance != null)
|
|
||||||
{
|
|
||||||
SubscribeToEquipmentEvents();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnDestroy()
|
void OnDestroy() { }
|
||||||
{
|
|
||||||
if (PlayerController.Instance != null && PlayerController.Instance.DiapasonEquipment != null)
|
|
||||||
{
|
|
||||||
UnsubscribeFromEquipmentEvents();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SubscribeToEquipmentEvents()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UnsubscribeFromEquipmentEvents()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void Update()
|
void Update()
|
||||||
{
|
{
|
||||||
@@ -93,7 +74,8 @@ namespace Unheimlich.Features.Diapason
|
|||||||
|
|
||||||
if (_listeningCoroutine != null)
|
if (_listeningCoroutine != null)
|
||||||
StopCoroutine(_listeningCoroutine);
|
StopCoroutine(_listeningCoroutine);
|
||||||
|
|
||||||
|
PlayerEvents.TriggerEnterListening();
|
||||||
_listeningCoroutine = StartCoroutine(ListeningSequence());
|
_listeningCoroutine = StartCoroutine(ListeningSequence());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,6 +163,7 @@ namespace Unheimlich.Features.Diapason
|
|||||||
}
|
}
|
||||||
|
|
||||||
InputManager.SetContext(InputManager.InputContext.Normal);
|
InputManager.SetContext(InputManager.InputContext.Normal);
|
||||||
|
PlayerEvents.TriggerExitListening();
|
||||||
|
|
||||||
Cursor.lockState = CursorLockMode.Locked;
|
Cursor.lockState = CursorLockMode.Locked;
|
||||||
Cursor.visible = false;
|
Cursor.visible = false;
|
||||||
|
|||||||
+7
-96
@@ -1,112 +1,23 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using Unheimlich.Core.Audio;
|
||||||
|
|
||||||
namespace Unheimlich.Features.Hallucination
|
namespace Unheimlich.Features.Hallucination
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fires a hallucination trigger when a specific AudioSource plays, finishes, or reaches a timestamp.
|
/// Fires a hallucination effect when a specific AudioSource plays, finishes, or reaches a timestamp.
|
||||||
/// Mirrors the pattern of ClueUnlockOnAudio but targets HallucinationManager.
|
/// Call OnAudioPlay() from whatever drives the AudioSource to start monitoring.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[RequireComponent(typeof(AudioSource))]
|
public class HallucinationOnAudio : AudioTriggerBase
|
||||||
public class HallucinationOnAudio : MonoBehaviour
|
|
||||||
{
|
{
|
||||||
public enum FireCondition
|
|
||||||
{
|
|
||||||
OnPlay,
|
|
||||||
OnFinish,
|
|
||||||
OnTimeReached
|
|
||||||
}
|
|
||||||
|
|
||||||
[Header("Audio Trigger")]
|
|
||||||
[Tooltip("When to fire the hallucination effect")]
|
|
||||||
[SerializeField] private FireCondition _fireCondition = FireCondition.OnPlay;
|
|
||||||
|
|
||||||
[Tooltip("Playback time in seconds to reach before firing (only for OnTimeReached)")]
|
|
||||||
[SerializeField] private float _triggerTime = 1f;
|
|
||||||
|
|
||||||
[Header("Hallucination Payload")]
|
[Header("Hallucination Payload")]
|
||||||
[Tooltip("Amount of sanity to add when this fires (0 = no change)")]
|
[Tooltip("Amount of insanity to add when this fires (0 = no change)")]
|
||||||
[SerializeField, Range(0f, 1f)] private float _insanityAmount = 0f;
|
[SerializeField, Range(0f, 1f)] private float _insanityAmount = 0f;
|
||||||
|
|
||||||
[Tooltip("Optional discrete hallucination event to fire")]
|
[Tooltip("Optional discrete hallucination event to fire")]
|
||||||
[SerializeField] private HallucinationEvent _hallucinationEvent;
|
[SerializeField] private HallucinationEvent _hallucinationEvent;
|
||||||
|
|
||||||
[Header("Behaviour")]
|
protected override void Execute()
|
||||||
[Tooltip("Prevent firing more than once per Play Mode session")]
|
|
||||||
[SerializeField] private bool _fireOnlyOnce = true;
|
|
||||||
|
|
||||||
[Header("Debug")]
|
|
||||||
[SerializeField] private bool _debugMode;
|
|
||||||
|
|
||||||
private AudioSource _audioSource;
|
|
||||||
private bool _hasFired;
|
|
||||||
private bool _isMonitoring;
|
|
||||||
|
|
||||||
private void Awake()
|
|
||||||
{
|
{
|
||||||
_audioSource = GetComponent<AudioSource>();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnEnable()
|
|
||||||
{
|
|
||||||
_hasFired = false;
|
|
||||||
_isMonitoring = false;
|
|
||||||
|
|
||||||
if (_audioSource != null && _audioSource.isPlaying)
|
|
||||||
StartMonitoring();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Update()
|
|
||||||
{
|
|
||||||
if (!_isMonitoring || (_fireOnlyOnce && _hasFired))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (_audioSource == null || !_audioSource.isPlaying)
|
|
||||||
{
|
|
||||||
if (_fireCondition == FireCondition.OnFinish)
|
|
||||||
Execute();
|
|
||||||
|
|
||||||
_isMonitoring = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_fireCondition == FireCondition.OnTimeReached && _audioSource.time >= _triggerTime)
|
|
||||||
Execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Notify this component that the AudioSource has started playing.
|
|
||||||
/// Wire this to whatever code or event drives the AudioSource.
|
|
||||||
/// </summary>
|
|
||||||
public void OnAudioPlay()
|
|
||||||
{
|
|
||||||
StartMonitoring();
|
|
||||||
|
|
||||||
if (_fireCondition == FireCondition.OnPlay)
|
|
||||||
Execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Resets the fired state so this can fire again.
|
|
||||||
/// </summary>
|
|
||||||
public void ResetFired()
|
|
||||||
{
|
|
||||||
_hasFired = false;
|
|
||||||
_isMonitoring = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void StartMonitoring()
|
|
||||||
{
|
|
||||||
_isMonitoring = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Execute()
|
|
||||||
{
|
|
||||||
if (_fireOnlyOnce && _hasFired)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_hasFired = true;
|
|
||||||
_isMonitoring = false;
|
|
||||||
|
|
||||||
if (HallucinationManager.Instance == null)
|
if (HallucinationManager.Instance == null)
|
||||||
{
|
{
|
||||||
Debug.LogError("[HallucinationOnAudio] HallucinationManager not found!", this);
|
Debug.LogError("[HallucinationOnAudio] HallucinationManager not found!", this);
|
||||||
@@ -120,7 +31,7 @@ namespace Unheimlich.Features.Hallucination
|
|||||||
HallucinationManager.Instance.TriggerHallucinationEvent(_hallucinationEvent);
|
HallucinationManager.Instance.TriggerHallucinationEvent(_hallucinationEvent);
|
||||||
|
|
||||||
if (_debugMode)
|
if (_debugMode)
|
||||||
Debug.Log($"[HallucinationOnAudio] Fired on '{_fireCondition}'. Sanity now: {HallucinationManager.Instance.SanityLevel:F2}", this);
|
Debug.Log($"[HallucinationOnAudio] Fired on '{_fireCondition}'. Sanity: {HallucinationManager.Instance.SanityLevel:F2}", this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-23
@@ -1,19 +1,16 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using Unheimlich.Core.Events;
|
|
||||||
|
|
||||||
namespace Unheimlich.Features.Hallucination
|
namespace Unheimlich.Features.Hallucination
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Drives the HallucinationManager when its GameEventTrigger fires.
|
/// Standalone hallucination payload component.
|
||||||
/// Can increase sanity, fire a discrete HallucinationEvent, or both.
|
/// Call Trigger() from any external script, UnityEvent, interaction, dialogue callback, etc.
|
||||||
/// Compose a GameEventTrigger on the same GameObject to control the firing condition
|
/// No other component required alongside it — compose freely.
|
||||||
/// (OnStart, OnEnable, delay, once-flag, external call via UnityEvent, etc.).
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[RequireComponent(typeof(GameEventTrigger))]
|
|
||||||
public class HallucinationTrigger : MonoBehaviour
|
public class HallucinationTrigger : MonoBehaviour
|
||||||
{
|
{
|
||||||
[Header("Sanity")]
|
[Header("Sanity")]
|
||||||
[Tooltip("Amount of sanity to add when this trigger fires (0 = no change)")]
|
[Tooltip("Amount of insanity to add when this trigger fires (0 = no change)")]
|
||||||
[SerializeField, Range(0f, 1f)] private float _insanityAmount = 0f;
|
[SerializeField, Range(0f, 1f)] private float _insanityAmount = 0f;
|
||||||
|
|
||||||
[Header("Hallucination Event")]
|
[Header("Hallucination Event")]
|
||||||
@@ -23,22 +20,9 @@ namespace Unheimlich.Features.Hallucination
|
|||||||
[Header("Debug")]
|
[Header("Debug")]
|
||||||
[SerializeField] private bool _debugMode;
|
[SerializeField] private bool _debugMode;
|
||||||
|
|
||||||
private GameEventTrigger _eventTrigger;
|
|
||||||
|
|
||||||
private void Awake()
|
|
||||||
{
|
|
||||||
_eventTrigger = GetComponent<GameEventTrigger>();
|
|
||||||
_eventTrigger.OnTriggered += Trigger;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnDestroy()
|
|
||||||
{
|
|
||||||
if (_eventTrigger != null)
|
|
||||||
_eventTrigger.OnTriggered -= Trigger;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fires the hallucination effect. Can be called directly from external scripts or UnityEvents.
|
/// Fires the hallucination effect.
|
||||||
|
/// Wire this to any UnityEvent, interaction callback, dialogue node event, audio trigger, etc.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Trigger()
|
public void Trigger()
|
||||||
{
|
{
|
||||||
@@ -53,7 +37,7 @@ namespace Unheimlich.Features.Hallucination
|
|||||||
HallucinationManager.Instance.AddInsanity(_insanityAmount);
|
HallucinationManager.Instance.AddInsanity(_insanityAmount);
|
||||||
|
|
||||||
if (_debugMode)
|
if (_debugMode)
|
||||||
Debug.Log($"[HallucinationTrigger] Added {_insanityAmount:F2} insanity. New sanity: {HallucinationManager.Instance.SanityLevel:F2}", this);
|
Debug.Log($"[HallucinationTrigger] Added {_insanityAmount:F2} insanity. Sanity now: {HallucinationManager.Instance.SanityLevel:F2}", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_hallucinationEvent != null)
|
if (_hallucinationEvent != null)
|
||||||
|
|||||||
+49
-13
@@ -4,30 +4,66 @@ using Unheimlich.Core.Events;
|
|||||||
namespace Unheimlich.Features.Hallucination
|
namespace Unheimlich.Features.Hallucination
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fires a GameEventTrigger (and therefore a HallucinationTrigger) when the player
|
/// Self-contained zone that triggers a hallucination effect when the player enters.
|
||||||
/// enters a physics trigger collider. Pair with GameEventTrigger + HallucinationTrigger
|
/// Handles the once-flag, optional delay, insanity increase, and a discrete HallucinationEvent
|
||||||
/// on the same GameObject.
|
/// — no GameEventTrigger or HallucinationTrigger required alongside it.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[RequireComponent(typeof(GameEventTrigger))]
|
|
||||||
public class HallucinationTriggerZone : TriggerZoneBase
|
public class HallucinationTriggerZone : TriggerZoneBase
|
||||||
{
|
{
|
||||||
[Header("Zone Behaviour")]
|
[Header("Zone Behaviour")]
|
||||||
[Tooltip("Allow the zone to fire again after the player exits and re-enters")]
|
[Tooltip("Allow the zone to fire again after the player exits and re-enters")]
|
||||||
[SerializeField] private bool _retriggerable = false;
|
[SerializeField] private bool _retriggerable = false;
|
||||||
|
|
||||||
|
[Tooltip("Delay in seconds before the hallucination fires after the player enters")]
|
||||||
|
[SerializeField] private float _delay = 0f;
|
||||||
|
|
||||||
|
[Header("Sanity")]
|
||||||
|
[Tooltip("Amount of insanity added when the zone fires (0 = no change)")]
|
||||||
|
[SerializeField, Range(0f, 1f)] private float _insanityAmount = 0f;
|
||||||
|
|
||||||
|
[Header("Hallucination Event")]
|
||||||
|
[Tooltip("Optional discrete hallucination event (ghost word, vision flash, etc.)")]
|
||||||
|
[SerializeField] private HallucinationEvent _hallucinationEvent;
|
||||||
|
|
||||||
|
[Header("Debug")]
|
||||||
|
[SerializeField] private bool _debugMode;
|
||||||
|
|
||||||
protected override bool IsRetriggerable => _retriggerable;
|
protected override bool IsRetriggerable => _retriggerable;
|
||||||
|
|
||||||
private GameEventTrigger _eventTrigger;
|
|
||||||
|
|
||||||
protected override void Awake()
|
|
||||||
{
|
|
||||||
base.Awake();
|
|
||||||
_eventTrigger = GetComponent<GameEventTrigger>();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnPlayerEntered(Collider playerCollider)
|
protected override void OnPlayerEntered(Collider playerCollider)
|
||||||
{
|
{
|
||||||
_eventTrigger.Fire();
|
if (_delay > 0f)
|
||||||
|
Invoke(nameof(Fire), _delay);
|
||||||
|
else
|
||||||
|
Fire();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fires the hallucination effect. Can also be called from external scripts or UnityEvents.
|
||||||
|
/// </summary>
|
||||||
|
public void Fire()
|
||||||
|
{
|
||||||
|
if (HallucinationManager.Instance == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("[HallucinationTriggerZone] HallucinationManager not found in scene!", this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_insanityAmount > 0f)
|
||||||
|
{
|
||||||
|
HallucinationManager.Instance.AddInsanity(_insanityAmount);
|
||||||
|
|
||||||
|
if (_debugMode)
|
||||||
|
Debug.Log($"[HallucinationTriggerZone] Added {_insanityAmount:F2} insanity on '{gameObject.name}'.", this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_hallucinationEvent != null)
|
||||||
|
{
|
||||||
|
HallucinationManager.Instance.TriggerHallucinationEvent(_hallucinationEvent);
|
||||||
|
|
||||||
|
if (_debugMode)
|
||||||
|
Debug.Log($"[HallucinationTriggerZone] Fired event: {_hallucinationEvent.Label}", this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,5 +26,22 @@ namespace Unheimlich.Features.Player.Data
|
|||||||
|
|
||||||
[Header("Head Bob - General")]
|
[Header("Head Bob - General")]
|
||||||
public float resetSpeed = 5f;
|
public float resetSpeed = 5f;
|
||||||
|
|
||||||
|
[Tooltip("Amplitude of the subtle Z-axis roll added to the bob (degrees).")]
|
||||||
|
public float bobRollAmplitude = 0.4f;
|
||||||
|
|
||||||
|
[Header("Camera Tilt")]
|
||||||
|
[Tooltip("Maximum Z roll angle when strafing (degrees).")]
|
||||||
|
public float strafeTiltAngle = 2.5f;
|
||||||
|
|
||||||
|
[Tooltip("Speed at which the strafe tilt lerps in and out.")]
|
||||||
|
public float strafeTiltSpeed = 6f;
|
||||||
|
|
||||||
|
[Header("FOV Kick")]
|
||||||
|
[Tooltip("FOV added on top of the base FOV when sprinting.")]
|
||||||
|
public float fovKickAmount = 6f;
|
||||||
|
|
||||||
|
[Tooltip("Speed at which FOV lerps to kick target and back.")]
|
||||||
|
public float fovKickSpeed = 8f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.InputSystem;
|
using UnityEngine.InputSystem;
|
||||||
|
using Unheimlich.Core;
|
||||||
using Unheimlich.Features.Player.Data;
|
using Unheimlich.Features.Player.Data;
|
||||||
using Unheimlich.Features.Dialogue;
|
using Unheimlich.Features.Dialogue;
|
||||||
using InputManager = Unheimlich.Core.Input.InputManager;
|
using InputManager = Unheimlich.Core.Input.InputManager;
|
||||||
@@ -7,7 +8,7 @@ using InputManager = Unheimlich.Core.Input.InputManager;
|
|||||||
namespace Unheimlich.Features.Player
|
namespace Unheimlich.Features.Player
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handles camera effects: aim assist and shake.
|
/// Handles camera effects: aim assist, shake, and FOV kick on sprint.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class CameraEffects : MonoBehaviour
|
public class CameraEffects : MonoBehaviour
|
||||||
{
|
{
|
||||||
@@ -22,29 +23,62 @@ namespace Unheimlich.Features.Player
|
|||||||
private Vector3 _pendingAimAssistTarget;
|
private Vector3 _pendingAimAssistTarget;
|
||||||
private bool _hasAimAssistTarget;
|
private bool _hasAimAssistTarget;
|
||||||
|
|
||||||
|
// FOV kick
|
||||||
|
private float _baseFov = -1f;
|
||||||
|
private float _currentFovOffset = 0f;
|
||||||
|
|
||||||
public bool IsAimLocked { get; private set; }
|
public bool IsAimLocked { get; private set; }
|
||||||
public bool HasActiveLookInput { get; private set; }
|
public bool HasActiveLookInput { get; private set; }
|
||||||
public bool IsUsingGamepad { get; private set; }
|
public bool IsUsingGamepad { get; private set; }
|
||||||
|
|
||||||
void Start()
|
private void Start()
|
||||||
{
|
{
|
||||||
if (Settings != null)
|
if (Settings != null)
|
||||||
_shakeInterval = 1f / Settings.shakeFrequency;
|
_shakeInterval = 1f / Settings.shakeFrequency;
|
||||||
|
|
||||||
|
if (PlayerController.Instance?.PlayerCamera != null)
|
||||||
|
_baseFov = PlayerController.Instance.PlayerCamera.fieldOfView;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Update()
|
private void Update()
|
||||||
{
|
{
|
||||||
DetectInputDevice();
|
DetectInputDevice();
|
||||||
|
UpdateFovKick();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LateUpdate()
|
private void LateUpdate()
|
||||||
{
|
{
|
||||||
if (_hasAimAssistTarget)
|
if (_hasAimAssistTarget)
|
||||||
{
|
|
||||||
ApplyAimAssistInternal(_pendingAimAssistTarget);
|
ApplyAimAssistInternal(_pendingAimAssistTarget);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── FOV Kick ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
private void UpdateFovKick()
|
||||||
|
{
|
||||||
|
if (Settings == null || PlayerController.Instance?.PlayerCamera == null) return;
|
||||||
|
|
||||||
|
// Capture base FOV once (handles cases where FOV is changed externally before Start).
|
||||||
|
if (_baseFov < 0f)
|
||||||
|
_baseFov = PlayerController.Instance.PlayerCamera.fieldOfView;
|
||||||
|
|
||||||
|
float targetOffset = PlayerController.Instance.IsRunning ? Settings.fovKickAmount : 0f;
|
||||||
|
_currentFovOffset = Mathf.Lerp(_currentFovOffset, targetOffset, Time.deltaTime * Settings.fovKickSpeed);
|
||||||
|
|
||||||
|
PlayerController.Instance.PlayerCamera.fieldOfView = _baseFov + _currentFovOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Resets the base FOV reference. Call this if the camera FOV is changed intentionally at runtime.
|
||||||
|
/// </summary>
|
||||||
|
public void ResetBaseFov()
|
||||||
|
{
|
||||||
|
if (PlayerController.Instance?.PlayerCamera != null)
|
||||||
|
_baseFov = PlayerController.Instance.PlayerCamera.fieldOfView;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Input device detection ────────────────────────────────────────────────
|
||||||
|
|
||||||
private void DetectInputDevice()
|
private void DetectInputDevice()
|
||||||
{
|
{
|
||||||
Vector2 lookInput = InputManager.GetLookInput();
|
Vector2 lookInput = InputManager.GetLookInput();
|
||||||
@@ -56,11 +90,15 @@ namespace Unheimlich.Features.Player
|
|||||||
IsUsingGamepad = false;
|
IsUsingGamepad = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Camera Shake ──────────────────────────────────────────────────────────
|
||||||
|
|
||||||
public void ShakeCamera(float amplitude, float smoothness = 0f)
|
public void ShakeCamera(float amplitude, float smoothness = 0f)
|
||||||
{
|
{
|
||||||
if (PlayerController.Instance == null || PlayerController.Instance.CameraPivot == null || Settings == null)
|
if (PlayerController.Instance == null || PlayerController.Instance.CameraPivot == null || Settings == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
PlayerEvents.TriggerCameraShake(amplitude);
|
||||||
|
|
||||||
_shakeSmoothness = smoothness;
|
_shakeSmoothness = smoothness;
|
||||||
_shakeTimer -= Time.deltaTime;
|
_shakeTimer -= Time.deltaTime;
|
||||||
|
|
||||||
@@ -78,8 +116,8 @@ namespace Unheimlich.Features.Player
|
|||||||
if (_shakeSmoothness > 0f)
|
if (_shakeSmoothness > 0f)
|
||||||
{
|
{
|
||||||
PlayerController.Instance.CameraPivot.position = Vector3.Lerp(
|
PlayerController.Instance.CameraPivot.position = Vector3.Lerp(
|
||||||
PlayerController.Instance.CameraPivot.position,
|
PlayerController.Instance.CameraPivot.position,
|
||||||
_shakeTarget,
|
_shakeTarget,
|
||||||
Time.deltaTime * _shakeSmoothness);
|
Time.deltaTime * _shakeSmoothness);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -88,6 +126,8 @@ namespace Unheimlich.Features.Player
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Aim Assist ────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
public void ApplyAimAssist(Vector3 targetCenter)
|
public void ApplyAimAssist(Vector3 targetCenter)
|
||||||
{
|
{
|
||||||
_pendingAimAssistTarget = targetCenter;
|
_pendingAimAssistTarget = targetCenter;
|
||||||
@@ -96,9 +136,9 @@ namespace Unheimlich.Features.Player
|
|||||||
|
|
||||||
private void ApplyAimAssistInternal(Vector3 targetCenter)
|
private void ApplyAimAssistInternal(Vector3 targetCenter)
|
||||||
{
|
{
|
||||||
if (PlayerController.Instance == null || PlayerController.Instance.CameraTransform == null || Settings == null)
|
if (PlayerController.Instance == null || PlayerController.Instance.CameraTransform == null || Settings == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (PlayerController.Instance.Movement == null)
|
if (PlayerController.Instance.Movement == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -113,17 +153,17 @@ namespace Unheimlich.Features.Player
|
|||||||
Vector3 targetDirection = directionToTarget;
|
Vector3 targetDirection = directionToTarget;
|
||||||
float targetYaw = Mathf.Atan2(targetDirection.x, targetDirection.z) * Mathf.Rad2Deg;
|
float targetYaw = Mathf.Atan2(targetDirection.x, targetDirection.z) * Mathf.Rad2Deg;
|
||||||
float targetPitch = -Mathf.Asin(targetDirection.y) * Mathf.Rad2Deg;
|
float targetPitch = -Mathf.Asin(targetDirection.y) * Mathf.Rad2Deg;
|
||||||
|
|
||||||
float currentYaw = PlayerController.Instance.Movement.Yaw;
|
float currentYaw = PlayerController.Instance.Movement.Yaw;
|
||||||
float currentPitch = PlayerController.Instance.Movement.Pitch;
|
float currentPitch = PlayerController.Instance.Movement.Pitch;
|
||||||
|
|
||||||
float newYaw = Mathf.LerpAngle(currentYaw, targetYaw, Settings.aimAssistStrength * Time.deltaTime);
|
float newYaw = Mathf.LerpAngle(currentYaw, targetYaw, Settings.aimAssistStrength * Time.deltaTime);
|
||||||
float newPitch = Mathf.Lerp(currentPitch, targetPitch, Settings.aimAssistStrength * Time.deltaTime);
|
float newPitch = Mathf.Lerp(currentPitch, targetPitch, Settings.aimAssistStrength * Time.deltaTime);
|
||||||
|
|
||||||
PlayerController.Instance.Movement.Yaw = newYaw;
|
PlayerController.Instance.Movement.Yaw = newYaw;
|
||||||
PlayerController.Instance.Movement.Pitch = newPitch;
|
PlayerController.Instance.Movement.Pitch = newPitch;
|
||||||
}
|
}
|
||||||
|
|
||||||
_hasAimAssistTarget = false;
|
_hasAimAssistTarget = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,125 +6,194 @@ namespace Unheimlich.Features.Player
|
|||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Simulates camera head bobbing motion during player movement and idle states.
|
/// Simulates camera head bobbing motion during player movement and idle states.
|
||||||
|
/// Smoothly transitions between idle, walk and run bob parameters.
|
||||||
|
/// Adds a subtle Z-axis roll to the bob and a strafe tilt applied in LateUpdate.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class CameraHeadBob : MonoBehaviour
|
public class CameraHeadBob : MonoBehaviour
|
||||||
{
|
|
||||||
private float _timer = 0f;
|
|
||||||
private Vector3 _startLocalPos;
|
|
||||||
|
|
||||||
private HeadBobMode _overrideMode = HeadBobMode.Normal;
|
|
||||||
private bool _hasOverride = false;
|
|
||||||
private Coroutine _resetCoroutine;
|
|
||||||
|
|
||||||
void Start()
|
|
||||||
{
|
{
|
||||||
_startLocalPos = transform.localPosition;
|
private float _timer = 0f;
|
||||||
}
|
private Vector3 _startLocalPos;
|
||||||
|
|
||||||
void Update()
|
// Smoothly interpolated bob parameters to avoid brutal state switches.
|
||||||
{
|
private float _currentBobSpeed = 0f;
|
||||||
if (PlayerController.Instance == null || PlayerController.Instance.CharController == null)
|
private float _currentBobAmplitude = 0f;
|
||||||
return;
|
|
||||||
|
|
||||||
var settings = PlayerController.Instance.CameraEffects?.Settings;
|
// Strafe tilt (Z roll applied in LateUpdate, after OctoPlayer sets camera pitch).
|
||||||
if (settings == null) return;
|
private float _currentTilt = 0f;
|
||||||
|
|
||||||
HeadBobMode currentMode = _hasOverride ? _overrideMode : HeadBobMode.Normal;
|
private HeadBobMode _overrideMode = HeadBobMode.Normal;
|
||||||
|
private bool _hasOverride = false;
|
||||||
if (currentMode == HeadBobMode.Disabled)
|
private Coroutine _resetCoroutine;
|
||||||
|
|
||||||
|
private void Start()
|
||||||
{
|
{
|
||||||
ResetPosition(settings.resetSpeed);
|
_startLocalPos = transform.localPosition;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentMode == HeadBobMode.Idle || (PlayerInspectionHandler.Instance != null && PlayerInspectionHandler.Instance.IsInspecting))
|
|
||||||
{
|
|
||||||
ApplyBob(settings.idleBobSpeed, settings.idleBobAmplitude);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isMoving = PlayerController.Instance.IsMoving;
|
|
||||||
bool isRunning = PlayerController.Instance.IsRunning;
|
|
||||||
bool isGrounded = PlayerController.Instance.CharController.isGrounded;
|
|
||||||
|
|
||||||
if (isGrounded)
|
private void Update()
|
||||||
{
|
{
|
||||||
if (isMoving)
|
if (PlayerController.Instance == null || PlayerController.Instance.CharController == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var settings = PlayerController.Instance.CameraEffects?.Settings;
|
||||||
|
if (settings == null) return;
|
||||||
|
|
||||||
|
HeadBobMode currentMode = _hasOverride ? _overrideMode : HeadBobMode.Normal;
|
||||||
|
|
||||||
|
if (currentMode == HeadBobMode.Disabled)
|
||||||
{
|
{
|
||||||
if (isRunning)
|
SetBobDirect(settings.idleBobSpeed, 0f);
|
||||||
ApplyBob(settings.runBobSpeed, settings.runBobAmplitude);
|
ApplySmoothedBob(settings.bobRollAmplitude);
|
||||||
else
|
return;
|
||||||
ApplyBob(settings.walkBobSpeed, settings.walkBobAmplitude);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
ApplyBob(settings.idleBobSpeed, settings.idleBobAmplitude);
|
bool forceIdle = currentMode == HeadBobMode.Idle
|
||||||
|
|| (PlayerInspectionHandler.Instance != null && PlayerInspectionHandler.Instance.IsInspecting);
|
||||||
|
|
||||||
|
if (forceIdle)
|
||||||
|
{
|
||||||
|
SetBobDirect(settings.idleBobSpeed, settings.idleBobAmplitude);
|
||||||
|
ApplySmoothedBob(settings.bobRollAmplitude);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isGrounded = PlayerController.Instance.CharController.isGrounded;
|
||||||
|
if (!isGrounded)
|
||||||
|
{
|
||||||
|
SetBobDirect(settings.idleBobSpeed, 0f);
|
||||||
|
ApplySmoothedBob(settings.bobRollAmplitude);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Drive bob parameters directly from the actual physics velocity.
|
||||||
|
// This is naturally in sync with OctoPlayer's inertia — no extra lerp needed.
|
||||||
|
float horizontalSpeed = new Vector3(
|
||||||
|
PlayerController.Instance.CharController.velocity.x,
|
||||||
|
0f,
|
||||||
|
PlayerController.Instance.CharController.velocity.z).magnitude;
|
||||||
|
|
||||||
|
bool isRunning = PlayerController.Instance.IsRunning;
|
||||||
|
|
||||||
|
// Normalise: 0 = stopped, 1 = full walk/run speed (m/s converted from km/h ÷ 3.6).
|
||||||
|
const float WalkSpeedMs = 10f / 3.6f;
|
||||||
|
const float RunSpeedMs = 20f / 3.6f;
|
||||||
|
|
||||||
|
float maxSpeed = isRunning ? RunSpeedMs : WalkSpeedMs;
|
||||||
|
float t = Mathf.Clamp01(horizontalSpeed / maxSpeed);
|
||||||
|
|
||||||
|
float targetSpeed = Mathf.Lerp(settings.idleBobSpeed, isRunning ? settings.runBobSpeed : settings.walkBobSpeed, t);
|
||||||
|
float targetAmplitude = Mathf.Lerp(settings.idleBobAmplitude, isRunning ? settings.runBobAmplitude : settings.walkBobAmplitude, t);
|
||||||
|
|
||||||
|
SetBobDirect(targetSpeed, targetAmplitude);
|
||||||
|
ApplySmoothedBob(settings.bobRollAmplitude);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
ResetPosition(settings.resetSpeed);
|
/// <summary>
|
||||||
}
|
/// Applies strafe tilt in LateUpdate so it composites correctly over OctoPlayer's pitch rotation.
|
||||||
|
/// </summary>
|
||||||
public void SetMode(HeadBobMode mode)
|
private void LateUpdate()
|
||||||
{
|
|
||||||
_overrideMode = mode;
|
|
||||||
_hasOverride = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ClearOverride()
|
|
||||||
{
|
|
||||||
_hasOverride = false;
|
|
||||||
|
|
||||||
if (_resetCoroutine != null)
|
|
||||||
{
|
{
|
||||||
StopCoroutine(_resetCoroutine);
|
if (PlayerController.Instance == null || PlayerController.Instance.CharController == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var settings = PlayerController.Instance.CameraEffects?.Settings;
|
||||||
|
if (settings == null) return;
|
||||||
|
|
||||||
|
// Strafe direction in local space using actual character velocity.
|
||||||
|
Vector3 velocity = PlayerController.Instance.CharController.velocity;
|
||||||
|
float strafeAmount = Vector3.Dot(velocity, PlayerController.Instance.transform.right);
|
||||||
|
|
||||||
|
// Normalise by run speed (km/h → m/s: / 3.6) to get a -1..1 factor.
|
||||||
|
float runSpeedMs = PlayerController.Instance.Movement != null ? 20f / 3.6f : 5.5f;
|
||||||
|
float strafeFactor = Mathf.Clamp(strafeAmount / runSpeedMs, -1f, 1f);
|
||||||
|
|
||||||
|
float targetTilt = -strafeFactor * settings.strafeTiltAngle;
|
||||||
|
_currentTilt = Mathf.Lerp(_currentTilt, targetTilt, Time.deltaTime * settings.strafeTiltSpeed);
|
||||||
|
|
||||||
|
// Compose with the existing local rotation (OctoPlayer already wrote pitch into it).
|
||||||
|
Quaternion baseRot = transform.localRotation;
|
||||||
|
transform.localRotation = baseRot * Quaternion.Euler(0f, 0f, _currentTilt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Public API ────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
/// <summary>Overrides the head bob mode (Idle, Normal, Disabled).</summary>
|
||||||
|
public void SetMode(HeadBobMode mode)
|
||||||
|
{
|
||||||
|
_overrideMode = mode;
|
||||||
|
_hasOverride = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Clears any active mode override and returns to Normal.</summary>
|
||||||
|
public void ClearOverride()
|
||||||
|
{
|
||||||
|
_hasOverride = false;
|
||||||
|
|
||||||
|
if (_resetCoroutine != null)
|
||||||
|
{
|
||||||
|
StopCoroutine(_resetCoroutine);
|
||||||
|
_resetCoroutine = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Lerps the camera local position back to origin over <paramref name="duration"/> seconds.</summary>
|
||||||
|
public void LerpToZero(float duration)
|
||||||
|
{
|
||||||
|
if (_resetCoroutine != null)
|
||||||
|
StopCoroutine(_resetCoroutine);
|
||||||
|
|
||||||
|
_resetCoroutine = StartCoroutine(LerpToZeroCoroutine(duration));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Private helpers ───────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
/// <summary>Sets bob speed and amplitude directly without lerp — velocity already carries the inertia.</summary>
|
||||||
|
private void SetBobDirect(float speed, float amplitude)
|
||||||
|
{
|
||||||
|
_currentBobSpeed = speed;
|
||||||
|
_currentBobAmplitude = amplitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Advances the bob timer and writes the resulting local position offset.
|
||||||
|
/// Includes a subtle Z roll (Lissajous third axis) for organic feel.
|
||||||
|
/// </summary>
|
||||||
|
private void ApplySmoothedBob(float rollAmplitude)
|
||||||
|
{
|
||||||
|
_timer += Time.deltaTime * _currentBobSpeed;
|
||||||
|
|
||||||
|
float x = Mathf.Sin(_timer * 0.5f) * _currentBobAmplitude * 0.6f;
|
||||||
|
float y = Mathf.Cos(_timer) * _currentBobAmplitude;
|
||||||
|
|
||||||
|
// Micro Z roll: half frequency of Y so it drifts independently.
|
||||||
|
float roll = Mathf.Sin(_timer * 0.5f + Mathf.PI * 0.25f) * rollAmplitude * (_currentBobAmplitude / Mathf.Max(0.001f, 0.03f));
|
||||||
|
|
||||||
|
Vector3 newPos = _startLocalPos;
|
||||||
|
newPos.x += x;
|
||||||
|
newPos.y += y;
|
||||||
|
transform.localPosition = newPos;
|
||||||
|
|
||||||
|
// Store roll so LateUpdate can composite it with the strafe tilt.
|
||||||
|
// We write only the bob-driven roll here; LateUpdate adds strafe tilt on top.
|
||||||
|
Quaternion bobRot = Quaternion.Euler(0f, 0f, roll);
|
||||||
|
transform.localRotation = bobRot;
|
||||||
|
}
|
||||||
|
|
||||||
|
private System.Collections.IEnumerator LerpToZeroCoroutine(float duration)
|
||||||
|
{
|
||||||
|
Vector3 startPos = transform.localPosition;
|
||||||
|
float elapsed = 0f;
|
||||||
|
|
||||||
|
while (elapsed < duration)
|
||||||
|
{
|
||||||
|
elapsed += Time.deltaTime;
|
||||||
|
float t = Mathf.Clamp01(elapsed / duration);
|
||||||
|
transform.localPosition = Vector3.Lerp(startPos, _startLocalPos, t);
|
||||||
|
yield return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
transform.localPosition = _startLocalPos;
|
||||||
_resetCoroutine = null;
|
_resetCoroutine = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LerpToZero(float duration)
|
|
||||||
{
|
|
||||||
if (_resetCoroutine != null)
|
|
||||||
StopCoroutine(_resetCoroutine);
|
|
||||||
|
|
||||||
_resetCoroutine = StartCoroutine(LerpToZeroCoroutine(duration));
|
|
||||||
}
|
|
||||||
|
|
||||||
private System.Collections.IEnumerator LerpToZeroCoroutine(float duration)
|
|
||||||
{
|
|
||||||
Vector3 startPos = transform.localPosition;
|
|
||||||
float elapsed = 0f;
|
|
||||||
|
|
||||||
while (elapsed < duration)
|
|
||||||
{
|
|
||||||
elapsed += Time.deltaTime;
|
|
||||||
float t = Mathf.Clamp01(elapsed / duration);
|
|
||||||
transform.localPosition = Vector3.Lerp(startPos, Vector3.zero, t);
|
|
||||||
yield return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
transform.localPosition = Vector3.zero;
|
|
||||||
_resetCoroutine = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ApplyBob(float speed, float amplitude)
|
|
||||||
{
|
|
||||||
_timer += Time.deltaTime * speed;
|
|
||||||
|
|
||||||
float x = Mathf.Sin(_timer * 0.5f) * amplitude;
|
|
||||||
float y = Mathf.Cos(_timer) * amplitude;
|
|
||||||
|
|
||||||
Vector3 newPos = _startLocalPos;
|
|
||||||
newPos.x += x;
|
|
||||||
newPos.y += y;
|
|
||||||
|
|
||||||
transform.localPosition = newPos;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ResetPosition(float resetSpeed)
|
|
||||||
{
|
|
||||||
transform.localPosition = Vector3.Lerp(transform.localPosition, _startLocalPos, Time.deltaTime * resetSpeed);
|
|
||||||
|
|
||||||
if (Vector3.Distance(transform.localPosition, _startLocalPos) < 0.001f)
|
|
||||||
_timer = 0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -36,34 +36,19 @@ namespace Unheimlich.Features.Player
|
|||||||
|
|
||||||
public InputManager Inputs => InputManager.Instance;
|
public InputManager Inputs => InputManager.Instance;
|
||||||
|
|
||||||
public bool IsMoving
|
// Cached sprint InputAction — resolved once in OnAwake to avoid per-frame foreach.
|
||||||
{
|
private UnityEngine.InputSystem.InputAction _sprintAction;
|
||||||
get
|
|
||||||
{
|
/// <summary>
|
||||||
// Read directly from action instead of cached value
|
/// True when the character is physically moving (based on CharacterController velocity,
|
||||||
var moveAction = InputManager.GetMoveAction();
|
/// not raw input — correctly synced with OctoPlayer's inertia).
|
||||||
if (moveAction == null) return false;
|
/// </summary>
|
||||||
return moveAction.ReadValue<UnityEngine.Vector2>().magnitude > 0.1f;
|
public bool IsMoving => CharController != null && CharController.velocity.magnitude > 0.1f;
|
||||||
}
|
|
||||||
}
|
/// <summary>
|
||||||
public bool IsRunning
|
/// True while the sprint input is held and the player is moving.
|
||||||
{
|
/// </summary>
|
||||||
get
|
public bool IsRunning => _sprintAction != null && _sprintAction.IsPressed() && IsMoving;
|
||||||
{
|
|
||||||
if (Movement == null || OctoCore.OctoCore.Instance == null) return false;
|
|
||||||
|
|
||||||
var actions = OctoCore.OctoCore.Instance.Inputs?.Actions;
|
|
||||||
if (actions != null)
|
|
||||||
{
|
|
||||||
foreach (var actionInfo in actions)
|
|
||||||
{
|
|
||||||
if (actionInfo.Name == "Sprint" && actionInfo.Reference != null)
|
|
||||||
return actionInfo.Reference.action.IsPressed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnAwake()
|
protected override void OnAwake()
|
||||||
{
|
{
|
||||||
@@ -76,15 +61,34 @@ namespace Unheimlich.Features.Player
|
|||||||
DiapasonEquipment = GetComponent<DiapasonEquipmentManager>();
|
DiapasonEquipment = GetComponent<DiapasonEquipmentManager>();
|
||||||
InspectionHandler = GetComponent<PlayerInspectionHandler>();
|
InspectionHandler = GetComponent<PlayerInspectionHandler>();
|
||||||
DetectiveBoardController = GetComponent<DetectiveBoardController>();
|
DetectiveBoardController = GetComponent<DetectiveBoardController>();
|
||||||
|
|
||||||
PlayerCamera = GetComponentInChildren<Camera>();
|
PlayerCamera = GetComponentInChildren<Camera>();
|
||||||
ArmsSystem = GetComponentInChildren<OctoIkArmsImproved>();
|
ArmsSystem = GetComponentInChildren<OctoIkArmsImproved>();
|
||||||
|
|
||||||
if (PlayerCamera != null)
|
if (PlayerCamera != null)
|
||||||
{
|
{
|
||||||
CameraTransform = PlayerCamera.transform;
|
CameraTransform = PlayerCamera.transform;
|
||||||
CameraPivot = CameraTransform.parent;
|
CameraPivot = CameraTransform.parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CacheSprintAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Resolves the Sprint InputAction once from OctoCore to avoid per-frame foreach iteration.
|
||||||
|
/// </summary>
|
||||||
|
private void CacheSprintAction()
|
||||||
|
{
|
||||||
|
if (OctoCore.OctoCore.Instance?.Inputs?.Actions == null) return;
|
||||||
|
|
||||||
|
foreach (var actionInfo in OctoCore.OctoCore.Instance.Inputs.Actions)
|
||||||
|
{
|
||||||
|
if (actionInfo.Name == "Sprint" && actionInfo.Reference != null)
|
||||||
|
{
|
||||||
|
_sprintAction = actionInfo.Reference.action;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Teleport
|
// Teleport
|
||||||
|
|||||||
+4
-3
@@ -1,6 +1,7 @@
|
|||||||
<Solution>
|
<Solution>
|
||||||
<Project Path="OctoCore.Runtime.csproj" />
|
|
||||||
<Project Path="Assembly-CSharp-Editor.csproj" />
|
|
||||||
<Project Path="OctoCore.Editor.csproj" />
|
|
||||||
<Project Path="Assembly-CSharp.csproj" />
|
<Project Path="Assembly-CSharp.csproj" />
|
||||||
|
<Project Path="Assembly-CSharp-Editor.csproj" />
|
||||||
|
<Project Path="OctoCore.Runtime.csproj" />
|
||||||
|
<Project Path="OctoCore.Editor.csproj" />
|
||||||
|
<Project Path="Bezi.Editor.csproj" />
|
||||||
</Solution>
|
</Solution>
|
||||||
|
|||||||
Reference in New Issue
Block a user