Improved detective board system

This commit is contained in:
2026-02-10 03:00:42 +01:00
parent b172762d4f
commit 8758d6eaeb
28 changed files with 3211 additions and 305 deletions
@@ -15,7 +15,7 @@ MonoBehaviour:
PanSpeed: 2 PanSpeed: 2
PanBorderSize: 0.15 PanBorderSize: 0.15
MaxPanAngle: 45 MaxPanAngle: 45
EnableRecentering: 1 EnableRecentering: 0
RecenterSpeed: 0.5 RecenterSpeed: 0.5
RecenterDelay: 0.1 RecenterDelay: 0.1
AlignmentSpeed: 4 AlignmentSpeed: 4
@@ -10,14 +10,13 @@ MonoBehaviour:
m_Enabled: 1 m_Enabled: 1
m_EditorHideFlags: 0 m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 166ae120db91b064c9b98086267b9783, type: 3} m_Script: {fileID: 11500000, guid: 166ae120db91b064c9b98086267b9783, type: 3}
m_Name: ExampleClue_BrokenDoor m_Name: ExampleClue_LevitatingCube
m_EditorClassIdentifier: Assembly-CSharp::Unheimlich.Data.DetectiveBoard.ClueData m_EditorClassIdentifier: Assembly-CSharp::Unheimlich.Data.DetectiveBoard.ClueData
ClueID: clue_broken_door_002 ClueID: clue_levitation_cube
Title: Broken Door Title: Cube Levitation
Description: The door to cell 13 shows signs of forced entry. Scratch marks on Description: "Le cube l\xE9vitait ? "
the inside. Icon: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
Icon: {fileID: 0} NodeColor: {r: 0.5471698, g: 0.4341498, b: 0.025809828, a: 1}
NodeColor: {r: 0.8, g: 0.8, b: 0.8, a: 1}
PossibleConnections: PossibleConnections:
- clue_strange_sound_001 - clue_strange_sound_001
- clue_patient_testimony_003 - clue_patient_testimony_003
@@ -1,5 +1,133 @@
%YAML 1.1 %YAML 1.1
%TAG !u! tag:unity3d.com,2011: %TAG !u! tag:unity3d.com,2011:
--- !u!1 &178245048760048658
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4439308675065618236}
- component: {fileID: 8768173993509551329}
- component: {fileID: 8228955512308698997}
- component: {fileID: 610326624064972366}
- component: {fileID: 7357781231808705528}
m_Layer: 0
m_Name: Cube
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &4439308675065618236
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 178245048760048658}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 1.67, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 1570673126153523765}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &8768173993509551329
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 178245048760048658}
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
--- !u!23 &8228955512308698997
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 178245048760048658}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
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: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, 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!65 &610326624064972366
BoxCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 178245048760048658}
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: 1, y: 1, z: 1}
m_Center: {x: 0, y: 0, z: 0}
--- !u!114 &7357781231808705528
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 178245048760048658}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: cca584f48d1f0ab429416470fd01d543, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::Unheimlich.Handlers.DetectiveBoard.ClueUnlockOnInteraction
InteractionText: Interact
_clueToUnlock: {fileID: 11400000, guid: f00adada8d7d4d24eb9e1b189cb15cd2, type: 2}
_unlockOnlyOnce: 1
--- !u!1 &1426444537624782055 --- !u!1 &1426444537624782055
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -32,6 +160,41 @@ Transform:
- {fileID: 6782646836872321146} - {fileID: 6782646836872321146}
m_Father: {fileID: 3965737018690194595} m_Father: {fileID: 3965737018690194595}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1492141393047357634
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1025430116059553395}
m_Layer: 0
m_Name: ConnectionsContainer
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1025430116059553395
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1492141393047357634}
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: 3296430617892173296}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!1 &1995558577310749644 --- !u!1 &1995558577310749644
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -267,6 +430,130 @@ MeshRenderer:
m_SortingOrder: 0 m_SortingOrder: 0
m_MaskInteraction: 0 m_MaskInteraction: 0
m_AdditionalVertexStreams: {fileID: 0} m_AdditionalVertexStreams: {fileID: 0}
--- !u!1 &2846607907897423711
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3291832893027407756}
- component: {fileID: 7386465302982466894}
- component: {fileID: 645358304861263696}
- component: {fileID: 7749130983367147328}
- component: {fileID: 4342417931132834337}
m_Layer: 0
m_Name: Canvas
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &3291832893027407756
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2846607907897423711}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: -0.53}
m_LocalScale: {x: 0.01, y: 0.01, z: 0.01}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 3296430617892173296}
m_Father: {fileID: 5831650301161165405}
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: 700, y: 500}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!223 &7386465302982466894
Canvas:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2846607907897423711}
m_Enabled: 1
serializedVersion: 3
m_RenderMode: 2
m_Camera: {fileID: 0}
m_PlaneDistance: 100
m_PixelPerfect: 0
m_ReceivesEvents: 1
m_OverrideSorting: 0
m_OverridePixelPerfect: 0
m_SortingBucketNormalizedSize: 0
m_VertexColorAlwaysGammaSpace: 0
m_AdditionalShaderChannelsFlag: 25
m_UpdateRectTransformForStandalone: 0
m_SortingLayerID: 0
m_SortingOrder: 0
m_TargetDisplay: 0
--- !u!114 &645358304861263696
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2846607907897423711}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3}
m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.CanvasScaler
m_UiScaleMode: 0
m_ReferencePixelsPerUnit: 100
m_ScaleFactor: 1
m_ReferenceResolution: {x: 800, y: 600}
m_ScreenMatchMode: 0
m_MatchWidthOrHeight: 0
m_PhysicalUnit: 3
m_FallbackScreenDPI: 96
m_DefaultSpriteDPI: 96
m_DynamicPixelsPerUnit: 1
m_PresetInfoIsWorld: 1
--- !u!114 &7749130983367147328
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2846607907897423711}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3}
m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.GraphicRaycaster
m_IgnoreReversedGraphics: 1
m_BlockingObjects: 0
m_BlockingMask:
serializedVersion: 2
m_Bits: 4294967295
--- !u!114 &4342417931132834337
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2846607907897423711}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: edfcd01879d2cb34495302ef9882965b, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::Unheimlich.UI.DetectiveBoard.DetectiveBoardCanvas
_canvas: {fileID: 7386465302982466894}
_boardArea: {fileID: 3296430617892173296}
_postItNodePrefab: {fileID: 7846882426873689123, guid: a9f97c7c1680277458e17d17c4e255c5, type: 3}
_connectionLinePrefab: {fileID: 466932862949433828, guid: 08d69aa508d5b8f439912b8ef5ee8dfc, type: 3}
_targetCamera: {fileID: 0}
_connectionColor: {r: 0.99371064, g: 0.30311283, b: 0.30311283, a: 1}
_allowFreeConnections: 0
_connectModeKey: 55
_eliminateKey: 38
--- !u!1 &3210101827131705135 --- !u!1 &3210101827131705135
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -284,22 +571,27 @@ GameObject:
m_NavMeshLayer: 0 m_NavMeshLayer: 0
m_StaticEditorFlags: 0 m_StaticEditorFlags: 0
m_IsActive: 1 m_IsActive: 1
--- !u!4 &5831650301161165405 --- !u!224 &5831650301161165405
Transform: RectTransform:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0} m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0} m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0} m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3210101827131705135} m_GameObject: {fileID: 3210101827131705135}
serializedVersion: 2
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: -0.38435, y: 3.99, z: 13.13094} m_LocalPosition: {x: 0, y: 0, z: 13.13094}
m_LocalScale: {x: 1, y: 1, z: 1} m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0 m_ConstrainProportionsScale: 0
m_Children: m_Children:
- {fileID: 3941506515996401395} - {fileID: 3941506515996401395}
- {fileID: 3291832893027407756}
m_Father: {fileID: 3965737018690194595} m_Father: {fileID: 3965737018690194595}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 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.38435, y: 3.99}
m_SizeDelta: {x: 100, y: 100}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!65 &300362587813736772 --- !u!65 &300362587813736772
BoxCollider: BoxCollider:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -448,6 +740,38 @@ MonoBehaviour:
m_ShadowLayerMask: 1 m_ShadowLayerMask: 1
m_RenderingLayers: 1 m_RenderingLayers: 1
m_ShadowRenderingLayers: 1 m_ShadowRenderingLayers: 1
--- !u!1 &4282593541683510326
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1570673126153523765}
m_Layer: 0
m_Name: InspectableItems
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &1570673126153523765
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4282593541683510326}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 4439308675065618236}
m_Father: {fileID: 3965737018690194595}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &4459682163590834316 --- !u!1 &4459682163590834316
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -1184,6 +1508,41 @@ BoxCollider:
serializedVersion: 3 serializedVersion: 3
m_Size: {x: 28.783504, y: 14.541088, z: 26.26189} m_Size: {x: 28.783504, y: 14.541088, z: 26.26189}
m_Center: {x: 0, y: 7.270544, z: 0} m_Center: {x: 0, y: 7.270544, z: 0}
--- !u!1 &5479374775542439816
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1866179234455568745}
m_Layer: 0
m_Name: NodesContainer
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1866179234455568745
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5479374775542439816}
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: 3296430617892173296}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!1 &5852353150564838653 --- !u!1 &5852353150564838653
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -1404,11 +1763,13 @@ Transform:
m_LocalScale: {x: 1, y: 1, z: 1} m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0 m_ConstrainProportionsScale: 0
m_Children: m_Children:
- {fileID: 1486611898895186651}
- {fileID: 8686293093389133775} - {fileID: 8686293093389133775}
- {fileID: 3812313393986610632} - {fileID: 3812313393986610632}
- {fileID: 404191218827319330} - {fileID: 404191218827319330}
- {fileID: 7656844688830104809} - {fileID: 7656844688830104809}
- {fileID: 5831650301161165405} - {fileID: 5831650301161165405}
- {fileID: 1570673126153523765}
m_Father: {fileID: 0} m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &8358850242504541279 --- !u!1 &8358850242504541279
@@ -1443,6 +1804,157 @@ Transform:
- {fileID: 7557062904579759447} - {fileID: 7557062904579759447}
m_Father: {fileID: 5831650301161165405} m_Father: {fileID: 5831650301161165405}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &8770322228334495894
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3296430617892173296}
- component: {fileID: 5503299879017764016}
- component: {fileID: 6526961613812749078}
m_Layer: 0
m_Name: BoardArea
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &3296430617892173296
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8770322228334495894}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 1025430116059553395}
- {fileID: 1866179234455568745}
m_Father: {fileID: 3291832893027407756}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &5503299879017764016
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8770322228334495894}
m_CullTransparentMesh: 1
--- !u!114 &6526961613812749078
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8770322228334495894}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
m_Material: {fileID: 0}
m_Color: {r: 0.1, g: 0.1, b: 0.1, a: 0.95}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1001 &694012498343031781
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 3965737018690194595}
m_Modifications:
- target: {fileID: 417056584789800637, guid: 0048fed3be8aeb8449285faf2cc63a15, type: 3}
propertyPath: m_Name
value: NPC
objectReference: {fileID: 0}
- target: {fileID: 2089706605371115838, guid: 0048fed3be8aeb8449285faf2cc63a15, type: 3}
propertyPath: m_LocalPosition.x
value: -4.96
objectReference: {fileID: 0}
- target: {fileID: 2089706605371115838, guid: 0048fed3be8aeb8449285faf2cc63a15, type: 3}
propertyPath: m_LocalPosition.y
value: 1
objectReference: {fileID: 0}
- target: {fileID: 2089706605371115838, guid: 0048fed3be8aeb8449285faf2cc63a15, type: 3}
propertyPath: m_LocalPosition.z
value: 0.92
objectReference: {fileID: 0}
- target: {fileID: 2089706605371115838, guid: 0048fed3be8aeb8449285faf2cc63a15, type: 3}
propertyPath: m_LocalRotation.w
value: 0.024001773
objectReference: {fileID: 0}
- target: {fileID: 2089706605371115838, guid: 0048fed3be8aeb8449285faf2cc63a15, type: 3}
propertyPath: m_LocalRotation.x
value: -0
objectReference: {fileID: 0}
- target: {fileID: 2089706605371115838, guid: 0048fed3be8aeb8449285faf2cc63a15, type: 3}
propertyPath: m_LocalRotation.y
value: -0.99971193
objectReference: {fileID: 0}
- target: {fileID: 2089706605371115838, guid: 0048fed3be8aeb8449285faf2cc63a15, type: 3}
propertyPath: m_LocalRotation.z
value: -0
objectReference: {fileID: 0}
- target: {fileID: 2089706605371115838, guid: 0048fed3be8aeb8449285faf2cc63a15, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2089706605371115838, guid: 0048fed3be8aeb8449285faf2cc63a15, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: -177.249
objectReference: {fileID: 0}
- target: {fileID: 2089706605371115838, guid: 0048fed3be8aeb8449285faf2cc63a15, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3429640485016181805, guid: 0048fed3be8aeb8449285faf2cc63a15, type: 3}
propertyPath: Conversation
value:
objectReference: {fileID: 11400000, guid: e9616b580e808fc4db9990454a298402, type: 2}
- target: {fileID: 3429640485016181805, guid: 0048fed3be8aeb8449285faf2cc63a15, type: 3}
propertyPath: isRetriggerable
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3429640485016181805, guid: 0048fed3be8aeb8449285faf2cc63a15, type: 3}
propertyPath: animationSettings
value:
objectReference: {fileID: 11400000, guid: 8d2436fb443aa634aa29932571994f9e, type: 2}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 0048fed3be8aeb8449285faf2cc63a15, type: 3}
--- !u!4 &1486611898895186651 stripped
Transform:
m_CorrespondingSourceObject: {fileID: 2089706605371115838, guid: 0048fed3be8aeb8449285faf2cc63a15, type: 3}
m_PrefabInstance: {fileID: 694012498343031781}
m_PrefabAsset: {fileID: 0}
--- !u!1001 &6429269889663292092 --- !u!1001 &6429269889663292092
PrefabInstance: PrefabInstance:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 11775599cc2865c4987f479c5b0865d3
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,94 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &466932862949433828
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8354868711036720273}
- component: {fileID: 8318893385783982974}
- component: {fileID: 6968356431738730970}
- component: {fileID: 5775632746252415440}
m_Layer: 5
m_Name: ConnectionLine
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &8354868711036720273
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 466932862949433828}
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: 3}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &8318893385783982974
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 466932862949433828}
m_CullTransparentMesh: 1
--- !u!114 &6968356431738730970
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 466932862949433828}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
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_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!114 &5775632746252415440
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 466932862949433828}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d38fc1a64b1949443b49ec6506174085, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::Unheimlich.UI.DetectiveBoard.ConnectionLine
_lineImage: {fileID: 6968356431738730970}
_rectTransform: {fileID: 8354868711036720273}
_lineThickness: 3
_lineColor: {r: 1, g: 1, b: 1, a: 1}
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 08d69aa508d5b8f439912b8ef5ee8dfc
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,573 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &3672113589456314020
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8026902276077438045}
- component: {fileID: 7028051022038080768}
- component: {fileID: 5948765940382964026}
m_Layer: 5
m_Name: TitleText
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &8026902276077438045
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3672113589456314020}
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: 7591763859490843308}
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: 50}
m_SizeDelta: {x: 200, y: 50}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &7028051022038080768
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3672113589456314020}
m_CullTransparentMesh: 1
--- !u!114 &5948765940382964026
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3672113589456314020}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier: Unity.TextMeshPro::TMPro.TextMeshProUGUI
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: New Text
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_fontSharedMaterials:
- {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4278190080
m_fontColor: {r: 0, g: 0, b: 0, 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: 20
m_fontSizeBase: 20
m_fontWeight: 400
m_enableAutoSizing: 0
m_fontSizeMin: 18
m_fontSizeMax: 72
m_fontStyle: 0
m_HorizontalAlignment: 2
m_VerticalAlignment: 256
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: 1
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
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!1 &7688294146181944494
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 6807041897062497986}
- component: {fileID: 4404710262467152139}
- component: {fileID: 6992333417677707967}
m_Layer: 5
m_Name: Outline
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &6807041897062497986
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7688294146181944494}
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: 7591763859490843308}
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: 205, y: 155}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &4404710262467152139
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7688294146181944494}
m_CullTransparentMesh: 1
--- !u!114 &6992333417677707967
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7688294146181944494}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
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_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &7846882426873689123
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7591763859490843308}
- component: {fileID: 2194047863489680297}
- component: {fileID: 8070799684683118059}
m_Layer: 5
m_Name: PostItNode
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &7591763859490843308
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7846882426873689123}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 0.5, y: 0.5, z: 0.5}
m_ConstrainProportionsScale: 1
m_Children:
- {fileID: 6807041897062497986}
- {fileID: 3379618101084551040}
- {fileID: 8026902276077438045}
- {fileID: 41566004426457767}
- {fileID: 9220801998878648733}
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: 200, y: 150}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &2194047863489680297
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7846882426873689123}
m_CullTransparentMesh: 1
--- !u!114 &8070799684683118059
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7846882426873689123}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a398093f79b17c04e81fe88b509b1319, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::Unheimlich.UI.DetectiveBoard.PostItNode
_rectTransform: {fileID: 7591763859490843308}
_background: {fileID: 7922678125126277134}
_titleText: {fileID: 5948765940382964026}
_descriptionText: {fileID: 6676115482369832417}
_iconImage: {fileID: 6995818135968247161}
_strikethroughLine: {fileID: 0}
_selectionOutline: {fileID: 6992333417677707967}
_connectionPoint: {fileID: 7591763859490843308}
--- !u!1 &8534530790302832033
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 41566004426457767}
- component: {fileID: 7162169036624129114}
- component: {fileID: 6676115482369832417}
m_Layer: 5
m_Name: DescriptionText
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &41566004426457767
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8534530790302832033}
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: 7591763859490843308}
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: 19.4}
m_SizeDelta: {x: 200, y: 50}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &7162169036624129114
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8534530790302832033}
m_CullTransparentMesh: 1
--- !u!114 &6676115482369832417
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8534530790302832033}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier: Unity.TextMeshPro::TMPro.TextMeshProUGUI
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: New Text
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_fontSharedMaterials:
- {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4278190080
m_fontColor: {r: 0, g: 0, b: 0, 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: 10
m_fontSizeBase: 10
m_fontWeight: 400
m_enableAutoSizing: 0
m_fontSizeMin: 18
m_fontSizeMax: 72
m_fontStyle: 0
m_HorizontalAlignment: 2
m_VerticalAlignment: 256
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: 1
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
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!1 &8965906964013961457
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 9220801998878648733}
- component: {fileID: 8161626241881700946}
- component: {fileID: 6995818135968247161}
m_Layer: 5
m_Name: Icon
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &9220801998878648733
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8965906964013961457}
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: 7591763859490843308}
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: -38.8}
m_SizeDelta: {x: 64, y: 64}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &8161626241881700946
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8965906964013961457}
m_CullTransparentMesh: 1
--- !u!114 &6995818135968247161
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8965906964013961457}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
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_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &9203127167361325707
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3379618101084551040}
- component: {fileID: 8648018728799938431}
- component: {fileID: 7922678125126277134}
m_Layer: 5
m_Name: Background
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &3379618101084551040
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 9203127167361325707}
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: 7591763859490843308}
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: 200, y: 150}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &8648018728799938431
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 9203127167361325707}
m_CullTransparentMesh: 1
--- !u!114 &7922678125126277134
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 9203127167361325707}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
m_Material: {fileID: 0}
m_Color: {r: 0.44025147, g: 0.39399204, b: 0, 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_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: a9f97c7c1680277458e17d17c4e255c5
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
File diff suppressed because one or more lines are too long
@@ -0,0 +1,46 @@
using UnityEngine;
using System;
using System.Collections.Generic;
namespace Unheimlich.Data.DetectiveBoard
{
[Serializable]
public class PostItNodeData
{
public string NodeID;
public Vector2 Position;
public bool IsEliminated;
public List<string> ConnectedNodeIDs = new List<string>();
public PostItNodeData(string id, Vector2 position)
{
NodeID = id;
Position = position;
IsEliminated = false;
}
}
[Serializable]
public class DetectiveBoardSaveData
{
public List<PostItNodeData> Nodes = new List<PostItNodeData>();
public PostItNodeData GetNodeData(string nodeID)
{
return Nodes.Find(n => n.NodeID == nodeID);
}
public void AddOrUpdateNode(PostItNodeData nodeData)
{
int index = Nodes.FindIndex(n => n.NodeID == nodeData.NodeID);
if (index >= 0)
{
Nodes[index] = nodeData;
}
else
{
Nodes.Add(nodeData);
}
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: f2344709e137fdf46aaa5445a330db2f
@@ -27,6 +27,8 @@ namespace Unheimlich.Gameplay.DetectiveBoard
private CameraPanSettings _originalCameraPanSettings; private CameraPanSettings _originalCameraPanSettings;
private CameraHeadBob _cameraHeadBob; private CameraHeadBob _cameraHeadBob;
public bool IsBoardActive => _isBoardActive;
private void Awake() private void Awake()
{ {
_playerCamera = Camera.main; _playerCamera = Camera.main;
@@ -24,6 +24,7 @@ namespace Unheimlich.Gameplay.Items
private Rigidbody _rigidbody; private Rigidbody _rigidbody;
private bool _isAnimationPlaying = false; private bool _isAnimationPlaying = false;
private ObjectDescriptionTrigger _objectDescriptionTrigger; private ObjectDescriptionTrigger _objectDescriptionTrigger;
private LevitatingObject _levitatingObject;
public bool IsAnimationPlaying => _isAnimationPlaying; public bool IsAnimationPlaying => _isAnimationPlaying;
@@ -37,6 +38,7 @@ namespace Unheimlich.Gameplay.Items
_originalParent = transform.parent; _originalParent = transform.parent;
_objectDescriptionTrigger = GetComponent<ObjectDescriptionTrigger>(); _objectDescriptionTrigger = GetComponent<ObjectDescriptionTrigger>();
_levitatingObject = GetComponent<LevitatingObject>();
} }
public override void Interact(GameObject interactor) public override void Interact(GameObject interactor)
@@ -75,7 +77,12 @@ namespace Unheimlich.Gameplay.Items
_rigidbody.isKinematic = true; _rigidbody.isKinematic = true;
transform.SetParent(holdPoint); transform.SetParent(holdPoint);
transform.localPosition = Vector3.forward * _inspectionDistance; transform.localPosition = Vector3.forward * _inspectionDistance;
transform.localRotation = Quaternion.identity; transform.localRotation = Quaternion.identity;
if (_levitatingObject != null)
{
_levitatingObject.UpdateBasePosition();
}
} }
public void Release() public void Release()
@@ -85,6 +92,11 @@ namespace Unheimlich.Gameplay.Items
transform.rotation = _originalRotation; transform.rotation = _originalRotation;
_rigidbody.isKinematic = true; _rigidbody.isKinematic = true;
if (_levitatingObject != null)
{
_levitatingObject.UpdateBasePosition();
}
} }
public float RotationSpeed => _rotationSpeed; public float RotationSpeed => _rotationSpeed;
@@ -0,0 +1,37 @@
using UnityEngine;
namespace Unheimlich.Gameplay.Items
{
public class LevitatingObject : MonoBehaviour
{
[Header("Levitation Settings")]
[SerializeField] private float _levitationHeight = 0.5f;
[SerializeField] private float _levitationSpeed = 1f;
[Header("Rotation Settings")]
[SerializeField] private float _rotationSpeed = 30f;
[SerializeField] private Vector3 _rotationAxis = Vector3.up;
private Vector3 _startLocalPosition;
private float _timeOffset;
private void Start()
{
_startLocalPosition = transform.localPosition;
_timeOffset = Random.Range(0f, Mathf.PI * 2f);
}
private void Update()
{
float yOffset = Mathf.Sin((Time.time + _timeOffset) * _levitationSpeed) * _levitationHeight;
transform.localPosition = _startLocalPosition + new Vector3(0f, yOffset, 0f);
transform.Rotate(_rotationAxis.normalized, _rotationSpeed * Time.deltaTime, Space.World);
}
public void UpdateBasePosition()
{
_startLocalPosition = transform.localPosition;
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 899101746b780fa4ca1a66d0af13173c
@@ -2,12 +2,13 @@ using UnityEngine;
using Unheimlich.Data.DetectiveBoard; using Unheimlich.Data.DetectiveBoard;
using Unheimlich.Interactions.Core; using Unheimlich.Interactions.Core;
using Unheimlich.Managers; using Unheimlich.Managers;
using Unheimlich.Gameplay.Items;
namespace Unheimlich.Handlers.DetectiveBoard namespace Unheimlich.Handlers.DetectiveBoard
{ {
/// <summary> /// <summary>
/// Unlocks a clue when the player interacts with this object. /// Unlocks a clue when the player interacts with this object.
/// Extends InteractableBase to integrate with the existing interaction system. /// Can work standalone (extends InteractableBase) or piggyback on an existing InspectableItem.
/// </summary> /// </summary>
public class ClueUnlockOnInteraction : InteractableBase public class ClueUnlockOnInteraction : InteractableBase
{ {
@@ -19,15 +20,27 @@ namespace Unheimlich.Handlers.DetectiveBoard
[SerializeField] private bool _unlockOnlyOnce = true; [SerializeField] private bool _unlockOnlyOnce = true;
private bool _hasUnlocked; private bool _hasUnlocked;
private InspectableItem _inspectableItem;
private void Awake()
{
_inspectableItem = GetComponent<InspectableItem>();
}
public override void Interact(GameObject interactor) public override void Interact(GameObject interactor)
{ {
if (_unlockOnlyOnce && _hasUnlocked) if (_unlockOnlyOnce && _hasUnlocked)
{
if (_inspectableItem != null)
_inspectableItem.Interact(interactor);
return; return;
}
if (_clueToUnlock == null) if (_clueToUnlock == null)
{ {
Debug.LogError("[ClueUnlockOnInteraction] No clue data assigned!"); Debug.LogError("[ClueUnlockOnInteraction] No clue data assigned!");
if (_inspectableItem != null)
_inspectableItem.Interact(interactor);
return; return;
} }
@@ -38,6 +51,11 @@ namespace Unheimlich.Handlers.DetectiveBoard
Debug.Log($"[ClueUnlockOnInteraction] Unlocked clue: {_clueToUnlock.Title} via interaction"); Debug.Log($"[ClueUnlockOnInteraction] Unlocked clue: {_clueToUnlock.Title} via interaction");
} }
if (_inspectableItem != null)
{
_inspectableItem.Interact(interactor);
}
} }
} }
} }
@@ -67,17 +67,32 @@ namespace Unheimlich.Managers
BoardPosition = clueData.InitialPosition BoardPosition = clueData.InitialPosition
}; };
Debug.Log($"[DetectiveBoardManager] Unlocked clue: {clueData.Title}");
OnClueUnlocked?.Invoke(clueData); OnClueUnlocked?.Invoke(clueData);
} }
else if (!_clueStates[clueData.ClueID].IsUnlocked) else if (!_clueStates[clueData.ClueID].IsUnlocked)
{ {
_clueStates[clueData.ClueID].IsUnlocked = true; _clueStates[clueData.ClueID].IsUnlocked = true;
Debug.Log($"[DetectiveBoardManager] Unlocked clue: {clueData.Title}");
OnClueUnlocked?.Invoke(clueData); OnClueUnlocked?.Invoke(clueData);
} }
} }
/// <summary>
/// Returns a list of all currently unlocked clues.
/// Used by DetectiveBoardCanvas to display already-unlocked clues on initialization.
/// </summary>
public List<ClueData> GetUnlockedClues()
{
List<ClueData> unlockedClues = new List<ClueData>();
foreach (var state in _clueStates.Values)
{
if (state.IsUnlocked)
{
unlockedClues.Add(state.Data);
}
}
return unlockedClues;
}
/// <summary> /// <summary>
/// Unlocks a clue by its ID string. /// Unlocks a clue by its ID string.
/// </summary> /// </summary>
@@ -88,7 +103,6 @@ namespace Unheimlich.Managers
if (!state.IsUnlocked) if (!state.IsUnlocked)
{ {
state.IsUnlocked = true; state.IsUnlocked = true;
Debug.Log($"[DetectiveBoardManager] Unlocked clue: {state.Data.Title}");
OnClueUnlocked?.Invoke(state.Data); OnClueUnlocked?.Invoke(state.Data);
} }
} }
@@ -1,93 +0,0 @@
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using Unheimlich.Data.DetectiveBoard;
namespace Unheimlich.UI.DetectiveBoard
{
/// <summary>
/// Visual representation of a clue node on the detective board.
/// Displays as a post-it/card with title, description, and icon.
/// Supports visual states: unlocked, eliminated, highlighted.
/// </summary>
public class ClueNodeUI : MonoBehaviour
{
[Header("References")]
[SerializeField] private Image _nodeImage;
[SerializeField] private TextMeshProUGUI _titleText;
[SerializeField] private Image _iconImage;
[SerializeField] private GameObject _eliminatedOverlay;
private ClueData _clueData;
private bool _isEliminated;
private Color _originalColor;
public ClueData ClueData => _clueData;
public bool IsEliminated => _isEliminated;
/// <summary>
/// Initializes the node with clue data.
/// </summary>
public void Initialize(ClueData clueData)
{
_clueData = clueData;
if (_titleText != null)
_titleText.text = clueData.Title;
if (_iconImage != null && clueData.Icon != null)
{
_iconImage.sprite = clueData.Icon;
_iconImage.enabled = true;
}
else if (_iconImage != null)
{
_iconImage.enabled = false;
}
if (_nodeImage != null)
{
_originalColor = clueData.NodeColor;
_nodeImage.color = _originalColor;
}
if (_eliminatedOverlay != null)
_eliminatedOverlay.SetActive(false);
}
/// <summary>
/// Marks this node as eliminated (incorrect hypothesis).
/// </summary>
public void SetEliminated(bool eliminated)
{
_isEliminated = eliminated;
if (_eliminatedOverlay != null)
_eliminatedOverlay.SetActive(eliminated);
if (_nodeImage != null)
{
_nodeImage.color = eliminated ? Color.gray : _originalColor;
}
}
/// <summary>
/// Highlights the node when hovered.
/// </summary>
public void SetHighlighted(bool highlighted, Color highlightColor)
{
if (_nodeImage != null && !_isEliminated)
{
_nodeImage.color = highlighted ? highlightColor : _originalColor;
}
}
/// <summary>
/// Updates the position of this node on the board (world space or canvas).
/// </summary>
public void SetPosition(Vector3 position)
{
transform.position = position;
}
}
}
@@ -1,2 +0,0 @@
fileFormatVersion: 2
guid: a7086ec4620627b458b08500e412ee90
@@ -0,0 +1,79 @@
using UnityEngine;
using UnityEngine.UI;
namespace Unheimlich.UI.DetectiveBoard
{
[RequireComponent(typeof(RectTransform))]
public class ConnectionLine : MonoBehaviour
{
[Header("References")]
[SerializeField] private Image _lineImage;
[SerializeField] private RectTransform _rectTransform;
[Header("Settings")]
[SerializeField] private float _lineThickness = 3f;
[SerializeField] private Color _lineColor = Color.white;
private PostItNode _startNode;
private PostItNode _endNode;
public PostItNode StartNode => _startNode;
public PostItNode EndNode => _endNode;
private void Awake()
{
if (_rectTransform == null)
_rectTransform = GetComponent<RectTransform>();
if (_lineImage == null)
_lineImage = GetComponent<Image>();
}
public void Initialize(PostItNode startNode, PostItNode endNode, Color? color = null)
{
_startNode = startNode;
_endNode = endNode;
if (color.HasValue)
_lineColor = color.Value;
if (_lineImage != null)
_lineImage.color = _lineColor;
UpdateLine();
}
public void UpdateLine()
{
if (_startNode == null || _endNode == null || _rectTransform == null)
return;
Vector2 startPos = _startNode.ConnectionPoint.anchoredPosition;
Vector2 endPos = _endNode.ConnectionPoint.anchoredPosition;
Vector2 direction = endPos - startPos;
float distance = direction.magnitude;
_rectTransform.anchoredPosition = startPos;
_rectTransform.sizeDelta = new Vector2(distance, _lineThickness);
float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
_rectTransform.rotation = Quaternion.Euler(0, 0, angle);
_rectTransform.pivot = new Vector2(0, 0.5f);
}
public void SetColor(Color color)
{
_lineColor = color;
if (_lineImage != null)
_lineImage.color = color;
}
public bool ConnectsNodes(PostItNode nodeA, PostItNode nodeB)
{
return (_startNode == nodeA && _endNode == nodeB) ||
(_startNode == nodeB && _endNode == nodeA);
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: d38fc1a64b1949443b49ec6506174085
@@ -0,0 +1,380 @@
using UnityEngine;
using UnityEngine.InputSystem;
using System.Collections.Generic;
using System.Linq;
using Unheimlich.Data.DetectiveBoard;
using Unheimlich.Managers;
namespace Unheimlich.UI.DetectiveBoard
{
public class DetectiveBoardCanvas : MonoBehaviour
{
[Header("References")]
[SerializeField] private Canvas _canvas;
[SerializeField] private RectTransform _boardArea;
[SerializeField] private GameObject _postItNodePrefab;
[SerializeField] private GameObject _connectionLinePrefab;
[Header("World Space Setup")]
[SerializeField] private Camera _targetCamera;
[Header("Connection Settings")]
[SerializeField] private Color _connectionColor = Color.white;
[SerializeField] private bool _allowFreeConnections = false;
[Header("Input")]
[SerializeField] private Key _connectModeKey = Key.LeftCtrl;
[SerializeField] private Key _eliminateKey = Key.X;
private Dictionary<string, PostItNode> _activeNodes = new Dictionary<string, PostItNode>();
private List<ConnectionLine> _activeConnections = new List<ConnectionLine>();
private PostItNode _selectedNode;
private bool _isConnectMode;
private DetectiveBoardSaveData _saveData;
public bool IsConnectMode => _isConnectMode;
/// <summary>
/// Called by DetectiveBoardInteraction when a node is left-clicked.
/// Handles connection creation in connect mode, or selection in normal mode.
/// </summary>
public void OnNodeClicked(PostItNode node)
{
if (_isConnectMode)
{
HandleConnectionModeClick(node);
}
else
{
_selectedNode = node;
UpdateAllNodeSelections();
}
}
/// <summary>
/// Called by DetectiveBoardInteraction when a node is right-clicked.
/// Toggles the eliminated state of the node.
/// </summary>
public void OnNodeRightClicked(PostItNode node)
{
ToggleNodeEliminated(node);
}
private void Awake()
{
if (_canvas == null)
_canvas = GetComponent<Canvas>();
if (_canvas != null && _canvas.renderMode == RenderMode.WorldSpace)
{
if (_targetCamera == null)
_targetCamera = Camera.main;
_canvas.worldCamera = _targetCamera;
}
_saveData = new DetectiveBoardSaveData();
}
private void OnEnable()
{
TrySubscribeToManager();
}
private void Start()
{
TrySubscribeToManager();
}
private void TrySubscribeToManager()
{
if (DetectiveBoardManager.Instance != null)
{
DetectiveBoardManager.Instance.OnClueUnlocked -= OnClueUnlocked;
DetectiveBoardManager.Instance.OnClueUnlocked += OnClueUnlocked;
foreach (var clue in DetectiveBoardManager.Instance.GetUnlockedClues())
{
if (!_activeNodes.ContainsKey(clue.ClueID))
{
AddClueNode(clue);
}
}
}
}
private void OnDisable()
{
if (DetectiveBoardManager.Instance != null)
{
DetectiveBoardManager.Instance.OnClueUnlocked -= OnClueUnlocked;
}
}
private void OnClueUnlocked(ClueData clueData)
{
Debug.Log($"[DetectiveBoardCanvas] OnClueUnlocked received for: {clueData.ClueID}");
AddClueNode(clueData);
}
private void Update()
{
HandleConnectModeInput();
HandleEliminateInput();
}
private void HandleConnectModeInput()
{
if (Keyboard.current == null)
return;
bool wasConnectMode = _isConnectMode;
_isConnectMode = Keyboard.current[_connectModeKey].isPressed;
if (wasConnectMode && !_isConnectMode)
{
_selectedNode = null;
UpdateAllNodeSelections();
}
}
private void HandleEliminateInput()
{
if (Keyboard.current == null)
return;
if (Keyboard.current[_eliminateKey].wasPressedThisFrame && _selectedNode != null)
{
ToggleNodeEliminated(_selectedNode);
}
}
public void AddClueNode(ClueData clueData)
{
if (_activeNodes.ContainsKey(clueData.ClueID))
return;
if (_postItNodePrefab == null)
{
Debug.LogError("[DetectiveBoardCanvas] _postItNodePrefab is null! Assign the prefab in the inspector.");
return;
}
if (_boardArea == null)
{
Debug.LogError("[DetectiveBoardCanvas] _boardArea is null! Assign NodesContainer in the inspector.");
return;
}
PostItNodeData nodeData = _saveData.GetNodeData(clueData.ClueID);
if (nodeData == null)
{
Vector2 canvasSize = _boardArea.rect.size;
Vector2 randomPos = new Vector2(
Random.Range(-canvasSize.x * 0.4f, canvasSize.x * 0.4f),
Random.Range(-canvasSize.y * 0.4f, canvasSize.y * 0.4f)
);
nodeData = new PostItNodeData(clueData.ClueID, randomPos);
_saveData.AddOrUpdateNode(nodeData);
}
GameObject nodeObj = Instantiate(_postItNodePrefab, _boardArea);
PostItNode node = nodeObj.GetComponent<PostItNode>();
if (node == null)
{
Debug.LogError("[DetectiveBoardCanvas] PostItNode component not found on prefab");
Destroy(nodeObj);
return;
}
node.Initialize(clueData, nodeData);
_activeNodes.Add(clueData.ClueID, node);
RestoreConnectionsForNode(node);
}
public void RemoveClueNode(string clueID)
{
if (!_activeNodes.TryGetValue(clueID, out PostItNode node))
return;
RemoveConnectionsForNode(node);
_activeNodes.Remove(clueID);
Destroy(node.gameObject);
}
private void HandleConnectionModeClick(PostItNode clickedNode)
{
if (_selectedNode == null)
{
_selectedNode = clickedNode;
UpdateAllNodeSelections();
}
else if (_selectedNode == clickedNode)
{
_selectedNode = null;
UpdateAllNodeSelections();
}
else
{
ToggleConnection(_selectedNode, clickedNode);
_selectedNode = null;
UpdateAllNodeSelections();
}
}
private void ToggleConnection(PostItNode nodeA, PostItNode nodeB)
{
if (!CanConnect(nodeA, nodeB))
return;
ConnectionLine existingConnection = _activeConnections.Find(c => c.ConnectsNodes(nodeA, nodeB));
if (existingConnection != null)
{
RemoveConnection(existingConnection);
}
else
{
CreateConnection(nodeA, nodeB);
}
}
private bool CanConnect(PostItNode nodeA, PostItNode nodeB)
{
if (nodeA == null || nodeB == null)
return false;
if (_allowFreeConnections)
return true;
if (nodeA.ClueData.PossibleConnections == null || nodeA.ClueData.PossibleConnections.Length == 0)
return true;
return nodeA.ClueData.PossibleConnections.Contains(nodeB.NodeID);
}
private void CreateConnection(PostItNode startNode, PostItNode endNode)
{
GameObject lineObj = Instantiate(_connectionLinePrefab, _boardArea);
lineObj.transform.SetAsFirstSibling();
ConnectionLine line = lineObj.GetComponent<ConnectionLine>();
if (line == null)
{
Debug.LogError("[DetectiveBoardCanvas] ConnectionLine component not found on prefab");
Destroy(lineObj);
return;
}
line.Initialize(startNode, endNode, _connectionColor);
_activeConnections.Add(line);
if (!startNode.NodeData.ConnectedNodeIDs.Contains(endNode.NodeID))
startNode.NodeData.ConnectedNodeIDs.Add(endNode.NodeID);
if (!endNode.NodeData.ConnectedNodeIDs.Contains(startNode.NodeID))
endNode.NodeData.ConnectedNodeIDs.Add(startNode.NodeID);
}
private void RemoveConnection(ConnectionLine connection)
{
if (connection.StartNode != null && connection.EndNode != null)
{
connection.StartNode.NodeData.ConnectedNodeIDs.Remove(connection.EndNode.NodeID);
connection.EndNode.NodeData.ConnectedNodeIDs.Remove(connection.StartNode.NodeID);
}
_activeConnections.Remove(connection);
Destroy(connection.gameObject);
}
private void RemoveConnectionsForNode(PostItNode node)
{
var connectionsToRemove = _activeConnections
.Where(c => c.StartNode == node || c.EndNode == node)
.ToList();
foreach (var connection in connectionsToRemove)
{
RemoveConnection(connection);
}
}
/// <summary>
/// Updates all connection lines attached to the specified node.
/// Called during node dragging to keep connections visually updated.
/// </summary>
public void UpdateConnectionsForNode(PostItNode node)
{
foreach (var connection in _activeConnections)
{
if (connection.StartNode == node || connection.EndNode == node)
{
connection.UpdateLine();
}
}
}
private void RestoreConnectionsForNode(PostItNode node)
{
if (node.NodeData.ConnectedNodeIDs == null || node.NodeData.ConnectedNodeIDs.Count == 0)
return;
foreach (string connectedID in node.NodeData.ConnectedNodeIDs)
{
if (_activeNodes.TryGetValue(connectedID, out PostItNode otherNode))
{
bool connectionExists = _activeConnections.Any(c => c.ConnectsNodes(node, otherNode));
if (!connectionExists)
{
CreateConnection(node, otherNode);
}
}
}
}
private void ToggleNodeEliminated(PostItNode node)
{
node.SetEliminated(!node.IsEliminated);
}
private void UpdateAllNodeSelections()
{
foreach (var node in _activeNodes.Values)
{
node.SetSelected(node == _selectedNode);
}
}
public DetectiveBoardSaveData GetSaveData()
{
return _saveData;
}
public void LoadSaveData(DetectiveBoardSaveData saveData)
{
_saveData = saveData;
foreach (var node in _activeNodes.Values)
{
PostItNodeData nodeData = _saveData.GetNodeData(node.NodeID);
if (nodeData != null)
{
node.SetPosition(nodeData.Position);
node.SetEliminated(nodeData.IsEliminated);
}
}
_activeConnections.Clear();
foreach (var node in _activeNodes.Values)
{
RestoreConnectionsForNode(node);
}
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: edfcd01879d2cb34495302ef9882965b
@@ -0,0 +1,289 @@
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;
using Unheimlich.Gameplay.DetectiveBoard;
namespace Unheimlich.UI.DetectiveBoard
{
/// <summary>
/// Handles mouse interaction for the detective board World Space canvas.
/// Manages hover, selection, dragging, and click forwarding for Post-It nodes.
/// Interactions are only active when the board is in inspection mode.
/// </summary>
public class DetectiveBoardInteraction : MonoBehaviour
{
[Header("References")]
[SerializeField] private Camera _camera;
[SerializeField] private Canvas _boardCanvas;
[SerializeField] private RectTransform _boardArea;
[SerializeField] private LayerMask _boardLayer;
[SerializeField] private DetectiveBoardController _boardController;
[Header("Settings")]
[SerializeField] private float _maxInteractionDistance = 5f;
private DetectiveBoardCanvas _canvasManager;
private PostItNode _hoveredNode;
private PostItNode _selectedNode;
private bool _isDragging;
private Plane _canvasPlane;
private Vector3 _dragOffset;
private void Start()
{
if (_camera == null)
_camera = Camera.main;
if (_boardController == null)
_boardController = FindFirstObjectByType<DetectiveBoardController>();
if (_canvasManager == null)
_canvasManager = GetComponent<DetectiveBoardCanvas>();
UpdateCanvasPlane();
}
private void Update()
{
if (!IsInBoardInteractionMode())
{
ClearInteractionState();
return;
}
UpdateCanvasPlane();
if (_isDragging)
{
HandleDrag();
}
else
{
HandleHover();
}
HandleClick();
}
private bool IsInBoardInteractionMode()
{
return _boardController != null && _boardController.IsBoardActive;
}
private void ClearInteractionState()
{
if (_hoveredNode != null)
{
_hoveredNode.SetHovered(false);
_hoveredNode = null;
}
if (_selectedNode != null && _isDragging)
{
_selectedNode.SetSelected(false);
_selectedNode = null;
_isDragging = false;
}
}
private void UpdateCanvasPlane()
{
if (_boardCanvas != null)
{
Vector3 planeNormal = -_boardCanvas.transform.forward;
Vector3 planePosition = _boardCanvas.transform.position;
_canvasPlane = new Plane(planeNormal, planePosition);
}
}
private void HandleHover()
{
PostItNode hitNode = RaycastForNode();
if (hitNode != _hoveredNode)
{
if (_hoveredNode != null)
{
_hoveredNode.SetHovered(false);
}
_hoveredNode = hitNode;
if (_hoveredNode != null)
{
_hoveredNode.SetHovered(true);
}
}
}
private void HandleClick()
{
if (Mouse.current == null)
return;
PostItNode hitNode = RaycastForNode();
if (Mouse.current.leftButton.wasPressedThisFrame)
{
HandleLeftClick(hitNode);
}
else if (Mouse.current.rightButton.wasPressedThisFrame && hitNode != null && _canvasManager != null)
{
_canvasManager.OnNodeRightClicked(hitNode);
}
}
private void HandleLeftClick(PostItNode hitNode)
{
if (_canvasManager != null && _canvasManager.IsConnectMode)
{
if (hitNode != null)
{
_canvasManager.OnNodeClicked(hitNode);
}
return;
}
if (_isDragging)
{
_isDragging = false;
if (_selectedNode != null && hitNode == _selectedNode)
{
return;
}
if (_selectedNode != null)
{
_selectedNode.SetSelected(false);
}
if (hitNode != null)
{
_selectedNode = hitNode;
_selectedNode.SetSelected(true);
_isDragging = true;
CalculateDragOffset();
}
else
{
_selectedNode = null;
}
}
else
{
if (hitNode != null)
{
if (_selectedNode != null && _selectedNode != hitNode)
{
_selectedNode.SetSelected(false);
}
_selectedNode = hitNode;
_selectedNode.SetSelected(true);
_isDragging = true;
CalculateDragOffset();
}
else
{
if (_selectedNode != null)
{
_selectedNode.SetSelected(false);
_selectedNode = null;
}
}
}
}
private void HandleDrag()
{
if (_selectedNode == null || _camera == null)
return;
Vector2 mousePos = Mouse.current.position.ReadValue();
Ray ray = _camera.ScreenPointToRay(new Vector3(mousePos.x, mousePos.y, 0));
if (_canvasPlane.Raycast(ray, out float enter))
{
Vector3 worldHitPoint = ray.GetPoint(enter);
Vector3 newWorldPos = worldHitPoint + _dragOffset;
Vector3 localPos = _boardCanvas.transform.InverseTransformPoint(newWorldPos);
Vector2 clampedPos = ClampPositionToBoard(new Vector2(localPos.x, localPos.y));
_selectedNode.SetPosition(clampedPos);
if (_canvasManager != null)
{
_canvasManager.UpdateConnectionsForNode(_selectedNode);
}
}
}
private Vector2 ClampPositionToBoard(Vector2 position)
{
if (_boardArea == null)
return position;
Rect boardRect = _boardArea.rect;
float halfWidth = boardRect.width * 0.5f;
float halfHeight = boardRect.height * 0.5f;
float clampedX = Mathf.Clamp(position.x, -halfWidth, halfWidth);
float clampedY = Mathf.Clamp(position.y, -halfHeight, halfHeight);
return new Vector2(clampedX, clampedY);
}
private void CalculateDragOffset()
{
if (_selectedNode == null || _camera == null)
return;
Vector2 mousePos = Mouse.current.position.ReadValue();
Ray ray = _camera.ScreenPointToRay(new Vector3(mousePos.x, mousePos.y, 0));
if (_canvasPlane.Raycast(ray, out float enter))
{
Vector3 worldHitPoint = ray.GetPoint(enter);
Vector3 currentWorldPos = _selectedNode.transform.position;
_dragOffset = currentWorldPos - worldHitPoint;
}
}
private PostItNode RaycastForNode()
{
if (_camera == null)
return null;
Vector2 mousePos = Mouse.current.position.ReadValue();
Ray ray = _camera.ScreenPointToRay(new Vector3(mousePos.x, mousePos.y, 0));
if (Physics.Raycast(ray, out RaycastHit hit, _maxInteractionDistance, _boardLayer))
{
return hit.collider.GetComponentInParent<PostItNode>();
}
GraphicRaycaster raycaster = _boardCanvas.GetComponent<GraphicRaycaster>();
if (raycaster != null)
{
var pointerEventData = new UnityEngine.EventSystems.PointerEventData(UnityEngine.EventSystems.EventSystem.current)
{
position = mousePos
};
var results = new System.Collections.Generic.List<UnityEngine.EventSystems.RaycastResult>();
raycaster.Raycast(pointerEventData, results);
foreach (var result in results)
{
PostItNode node = result.gameObject.GetComponentInParent<PostItNode>();
if (node != null)
return node;
}
}
return null;
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 17bf00a333a0bc9409c21009e3ac6aea
@@ -0,0 +1,128 @@
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using Unheimlich.Data.DetectiveBoard;
namespace Unheimlich.UI.DetectiveBoard
{
public class PostItNode : MonoBehaviour
{
[Header("UI References")]
[SerializeField] private RectTransform _rectTransform;
[SerializeField] private Image _background;
[SerializeField] private TextMeshProUGUI _titleText;
[SerializeField] private TextMeshProUGUI _descriptionText;
[SerializeField] private Image _iconImage;
[SerializeField] private GameObject _strikethroughLine;
[SerializeField] private Image _selectionOutline;
[Header("Connection Points")]
[SerializeField] private RectTransform _connectionPoint;
private ClueData _clueData;
private PostItNodeData _nodeData;
private bool _isEliminated;
private bool _isSelected;
private Color _originalColor;
public string NodeID => _clueData?.ClueID;
public RectTransform RectTransform => _rectTransform;
public RectTransform ConnectionPoint => _connectionPoint;
public ClueData ClueData => _clueData;
public PostItNodeData NodeData => _nodeData;
public bool IsEliminated => _isEliminated;
public bool IsSelected => _isSelected;
private void Awake()
{
if (_rectTransform == null)
_rectTransform = GetComponent<RectTransform>();
if (_strikethroughLine != null)
_strikethroughLine.SetActive(false);
if (_selectionOutline != null)
_selectionOutline.enabled = false;
}
public void Initialize(ClueData clueData, PostItNodeData nodeData)
{
_clueData = clueData;
_nodeData = nodeData;
if (_titleText != null)
_titleText.text = clueData.Title;
if (_descriptionText != null)
_descriptionText.text = clueData.Description;
if (_iconImage != null && clueData.Icon != null)
{
_iconImage.sprite = clueData.Icon;
_iconImage.enabled = true;
}
else if (_iconImage != null)
{
_iconImage.enabled = false;
}
if (_background != null)
{
_originalColor = clueData.NodeColor;
_background.color = _originalColor;
}
if (_connectionPoint == null)
{
_connectionPoint = _rectTransform;
}
SetPosition(nodeData.Position);
SetEliminated(nodeData.IsEliminated);
}
public void SetPosition(Vector2 position)
{
if (_rectTransform != null)
{
_rectTransform.anchoredPosition = position;
if (_nodeData != null)
_nodeData.Position = position;
}
}
public void SetEliminated(bool eliminated)
{
_isEliminated = eliminated;
if (_strikethroughLine != null)
_strikethroughLine.SetActive(eliminated);
if (_background != null)
{
_background.color = eliminated ? new Color(0.5f, 0.5f, 0.5f, 0.8f) : _originalColor;
}
if (_nodeData != null)
_nodeData.IsEliminated = eliminated;
}
public void SetSelected(bool selected)
{
_isSelected = selected;
if (_selectionOutline != null)
{
_selectionOutline.enabled = selected;
}
}
public void SetHovered(bool hovered)
{
if (_selectionOutline != null)
{
_selectionOutline.enabled = hovered || _isSelected;
}
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: a398093f79b17c04e81fe88b509b1319