Add Hunter NPC and Teleporter features with associated prefabs and effects
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -13,6 +13,8 @@
|
|||||||
/[Ll]ogs/
|
/[Ll]ogs/
|
||||||
/[Uu]ser[Ss]ettings/
|
/[Uu]ser[Ss]ettings/
|
||||||
|
|
||||||
|
.idea/
|
||||||
|
|
||||||
# MemoryCaptures can get excessive in size.
|
# MemoryCaptures can get excessive in size.
|
||||||
# They also could contain extremely sensitive data
|
# They also could contain extremely sensitive data
|
||||||
/[Mm]emoryCaptures/
|
/[Mm]emoryCaptures/
|
||||||
|
|||||||
162
Assets/Prefabs/HunterNpc.prefab
Normal file
162
Assets/Prefabs/HunterNpc.prefab
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!1 &6956164580015912564
|
||||||
|
GameObject:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
serializedVersion: 6
|
||||||
|
m_Component:
|
||||||
|
- component: {fileID: 2158095965342707446}
|
||||||
|
- component: {fileID: 522917209739125732}
|
||||||
|
- component: {fileID: 54217236340769722}
|
||||||
|
- component: {fileID: 121674684165614314}
|
||||||
|
- component: {fileID: 283610869708690177}
|
||||||
|
- component: {fileID: 4496988857626767934}
|
||||||
|
m_Layer: 0
|
||||||
|
m_Name: HunterNpc
|
||||||
|
m_TagString: Untagged
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_NavMeshLayer: 0
|
||||||
|
m_StaticEditorFlags: 0
|
||||||
|
m_IsActive: 1
|
||||||
|
--- !u!4 &2158095965342707446
|
||||||
|
Transform:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 6956164580015912564}
|
||||||
|
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: []
|
||||||
|
m_Father: {fileID: 0}
|
||||||
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
|
--- !u!33 &522917209739125732
|
||||||
|
MeshFilter:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 6956164580015912564}
|
||||||
|
m_Mesh: {fileID: 10208, guid: 0000000000000000e000000000000000, type: 0}
|
||||||
|
--- !u!23 &54217236340769722
|
||||||
|
MeshRenderer:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 6956164580015912564}
|
||||||
|
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: a64e346b67480caceae337f37543db27, 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!136 &121674684165614314
|
||||||
|
CapsuleCollider:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 6956164580015912564}
|
||||||
|
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: 2
|
||||||
|
m_Radius: 0.5
|
||||||
|
m_Height: 2
|
||||||
|
m_Direction: 1
|
||||||
|
m_Center: {x: 0, y: 0, z: 0}
|
||||||
|
--- !u!54 &283610869708690177
|
||||||
|
Rigidbody:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 6956164580015912564}
|
||||||
|
serializedVersion: 5
|
||||||
|
m_Mass: 1
|
||||||
|
m_LinearDamping: 0
|
||||||
|
m_AngularDamping: 0.05
|
||||||
|
m_CenterOfMass: {x: 0, y: 0, z: 0}
|
||||||
|
m_InertiaTensor: {x: 1, y: 1, z: 1}
|
||||||
|
m_InertiaRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
|
m_IncludeLayers:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Bits: 0
|
||||||
|
m_ExcludeLayers:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Bits: 0
|
||||||
|
m_ImplicitCom: 1
|
||||||
|
m_ImplicitTensor: 1
|
||||||
|
m_UseGravity: 1
|
||||||
|
m_IsKinematic: 0
|
||||||
|
m_Interpolate: 0
|
||||||
|
m_Constraints: 0
|
||||||
|
m_CollisionDetection: 0
|
||||||
|
--- !u!114 &4496988857626767934
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 6956164580015912564}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: d87e12fdb2c23b238910064019f2ad59, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier: Assembly-CSharp::Infrastructure.Unity.HunterNpcController
|
||||||
|
moveSpeed: 7
|
||||||
|
tileLayer:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Bits: 8
|
||||||
|
rb: {fileID: 283610869708690177}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 4ce47d492ed71cb5b9390762eab7a749
|
guid: ab4e193839fef9a2189f27360914c044
|
||||||
PrefabImporter:
|
PrefabImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
userData:
|
userData:
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
%YAML 1.1
|
%YAML 1.1
|
||||||
%TAG !u! tag:unity3d.com,2011:
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
--- !u!1 &7219310182397398916
|
--- !u!1 &6659026961635312632
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
@@ -8,25 +8,25 @@ GameObject:
|
|||||||
m_PrefabAsset: {fileID: 0}
|
m_PrefabAsset: {fileID: 0}
|
||||||
serializedVersion: 6
|
serializedVersion: 6
|
||||||
m_Component:
|
m_Component:
|
||||||
- component: {fileID: 4070461624121405295}
|
- component: {fileID: 663514258571720717}
|
||||||
- component: {fileID: 930667067315408562}
|
- component: {fileID: 8432450954479424108}
|
||||||
- component: {fileID: 2173926958931993968}
|
- component: {fileID: 7819803615826365176}
|
||||||
- component: {fileID: 5033597944775254142}
|
- component: {fileID: 6615024751381665233}
|
||||||
- component: {fileID: 2639250404559520579}
|
- component: {fileID: 7381336953128067686}
|
||||||
m_Layer: 0
|
m_Layer: 0
|
||||||
m_Name: Light footed
|
m_Name: PowerUp
|
||||||
m_TagString: Untagged
|
m_TagString: Untagged
|
||||||
m_Icon: {fileID: 0}
|
m_Icon: {fileID: 0}
|
||||||
m_NavMeshLayer: 0
|
m_NavMeshLayer: 0
|
||||||
m_StaticEditorFlags: 0
|
m_StaticEditorFlags: 0
|
||||||
m_IsActive: 1
|
m_IsActive: 1
|
||||||
--- !u!4 &4070461624121405295
|
--- !u!4 &663514258571720717
|
||||||
Transform:
|
Transform:
|
||||||
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: 7219310182397398916}
|
m_GameObject: {fileID: 6659026961635312632}
|
||||||
serializedVersion: 2
|
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, y: 0, z: 0}
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||||
@@ -35,21 +35,21 @@ Transform:
|
|||||||
m_Children: []
|
m_Children: []
|
||||||
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!33 &930667067315408562
|
--- !u!33 &8432450954479424108
|
||||||
MeshFilter:
|
MeshFilter:
|
||||||
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: 7219310182397398916}
|
m_GameObject: {fileID: 6659026961635312632}
|
||||||
m_Mesh: {fileID: 10208, guid: 0000000000000000e000000000000000, type: 0}
|
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
|
||||||
--- !u!23 &2173926958931993968
|
--- !u!23 &7819803615826365176
|
||||||
MeshRenderer:
|
MeshRenderer:
|
||||||
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: 7219310182397398916}
|
m_GameObject: {fileID: 6659026961635312632}
|
||||||
m_Enabled: 1
|
m_Enabled: 1
|
||||||
m_CastShadows: 1
|
m_CastShadows: 1
|
||||||
m_ReceiveShadows: 1
|
m_ReceiveShadows: 1
|
||||||
@@ -92,13 +92,13 @@ MeshRenderer:
|
|||||||
m_SortingOrder: 0
|
m_SortingOrder: 0
|
||||||
m_MaskInteraction: 0
|
m_MaskInteraction: 0
|
||||||
m_AdditionalVertexStreams: {fileID: 0}
|
m_AdditionalVertexStreams: {fileID: 0}
|
||||||
--- !u!136 &5033597944775254142
|
--- !u!65 &6615024751381665233
|
||||||
CapsuleCollider:
|
BoxCollider:
|
||||||
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: 7219310182397398916}
|
m_GameObject: {fileID: 6659026961635312632}
|
||||||
m_Material: {fileID: 0}
|
m_Material: {fileID: 0}
|
||||||
m_IncludeLayers:
|
m_IncludeLayers:
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
@@ -110,24 +110,22 @@ CapsuleCollider:
|
|||||||
m_IsTrigger: 1
|
m_IsTrigger: 1
|
||||||
m_ProvidesContacts: 0
|
m_ProvidesContacts: 0
|
||||||
m_Enabled: 1
|
m_Enabled: 1
|
||||||
serializedVersion: 2
|
serializedVersion: 3
|
||||||
m_Radius: 0.5
|
m_Size: {x: 1, y: 1, z: 1}
|
||||||
m_Height: 2
|
|
||||||
m_Direction: 1
|
|
||||||
m_Center: {x: 0, y: 0, z: 0}
|
m_Center: {x: 0, y: 0, z: 0}
|
||||||
--- !u!114 &2639250404559520579
|
--- !u!114 &7381336953128067686
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
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: 7219310182397398916}
|
m_GameObject: {fileID: 6659026961635312632}
|
||||||
m_Enabled: 1
|
m_Enabled: 1
|
||||||
m_EditorHideFlags: 0
|
m_EditorHideFlags: 0
|
||||||
m_Script: {fileID: 11500000, guid: 5886e2d0e6414ce98bf68f8e5ac887fc, type: 3}
|
m_Script: {fileID: 11500000, guid: 5886e2d0e6414ce98bf68f8e5ac887fc, type: 3}
|
||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier: Assembly-CSharp::Infrastructure.Unity.PowerUpViewAdapter
|
m_EditorClassIdentifier: Assembly-CSharp::Infrastructure.Unity.PowerUpViewAdapter
|
||||||
type: 0
|
type: 0
|
||||||
duration: 10
|
duration: 5
|
||||||
pickupVfx: {fileID: 0}
|
pickupVfx: {fileID: 0}
|
||||||
meshRenderer: {fileID: 2173926958931993968}
|
meshRenderer: {fileID: 7819803615826365176}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 32d69de3e08c76e63a4b5086b87b12df
|
guid: 8b540be4548e610709c2f7eccf8bf9c6
|
||||||
PrefabImporter:
|
PrefabImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
userData:
|
userData:
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
%YAML 1.1
|
%YAML 1.1
|
||||||
%TAG !u! tag:unity3d.com,2011:
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
--- !u!1 &7219310182397398916
|
--- !u!1 &2198048708000581807
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
@@ -8,48 +8,48 @@ GameObject:
|
|||||||
m_PrefabAsset: {fileID: 0}
|
m_PrefabAsset: {fileID: 0}
|
||||||
serializedVersion: 6
|
serializedVersion: 6
|
||||||
m_Component:
|
m_Component:
|
||||||
- component: {fileID: 4070461624121405295}
|
- component: {fileID: 7276685985893193207}
|
||||||
- component: {fileID: 930667067315408562}
|
- component: {fileID: 6152181000324460277}
|
||||||
- component: {fileID: 2173926958931993968}
|
- component: {fileID: 1559715898324095926}
|
||||||
- component: {fileID: 5033597944775254142}
|
- component: {fileID: 6093691026861389653}
|
||||||
- component: {fileID: 2639250404559520579}
|
- component: {fileID: 4601941687390792571}
|
||||||
m_Layer: 0
|
m_Layer: 0
|
||||||
m_Name: Speed Boost
|
m_Name: Teleporter pad
|
||||||
m_TagString: Untagged
|
m_TagString: Untagged
|
||||||
m_Icon: {fileID: 0}
|
m_Icon: {fileID: 0}
|
||||||
m_NavMeshLayer: 0
|
m_NavMeshLayer: 0
|
||||||
m_StaticEditorFlags: 0
|
m_StaticEditorFlags: 0
|
||||||
m_IsActive: 1
|
m_IsActive: 1
|
||||||
--- !u!4 &4070461624121405295
|
--- !u!4 &7276685985893193207
|
||||||
Transform:
|
Transform:
|
||||||
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: 7219310182397398916}
|
m_GameObject: {fileID: 2198048708000581807}
|
||||||
serializedVersion: 2
|
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, y: 0, z: 0}
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||||
m_LocalScale: {x: 0.5, y: 0.5, z: 0.5}
|
m_LocalScale: {x: 1, y: 0.1, z: 1}
|
||||||
m_ConstrainProportionsScale: 0
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children: []
|
m_Children: []
|
||||||
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!33 &930667067315408562
|
--- !u!33 &6152181000324460277
|
||||||
MeshFilter:
|
MeshFilter:
|
||||||
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: 7219310182397398916}
|
m_GameObject: {fileID: 2198048708000581807}
|
||||||
m_Mesh: {fileID: 10208, guid: 0000000000000000e000000000000000, type: 0}
|
m_Mesh: {fileID: 10206, guid: 0000000000000000e000000000000000, type: 0}
|
||||||
--- !u!23 &2173926958931993968
|
--- !u!23 &1559715898324095926
|
||||||
MeshRenderer:
|
MeshRenderer:
|
||||||
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: 7219310182397398916}
|
m_GameObject: {fileID: 2198048708000581807}
|
||||||
m_Enabled: 1
|
m_Enabled: 1
|
||||||
m_CastShadows: 1
|
m_CastShadows: 1
|
||||||
m_ReceiveShadows: 1
|
m_ReceiveShadows: 1
|
||||||
@@ -68,7 +68,7 @@ MeshRenderer:
|
|||||||
m_RenderingLayerMask: 1
|
m_RenderingLayerMask: 1
|
||||||
m_RendererPriority: 0
|
m_RendererPriority: 0
|
||||||
m_Materials:
|
m_Materials:
|
||||||
- {fileID: 2100000, guid: aece89a4ea685f6969a31191b980f70b, type: 2}
|
- {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2}
|
||||||
m_StaticBatchInfo:
|
m_StaticBatchInfo:
|
||||||
firstSubMesh: 0
|
firstSubMesh: 0
|
||||||
subMeshCount: 0
|
subMeshCount: 0
|
||||||
@@ -92,13 +92,13 @@ MeshRenderer:
|
|||||||
m_SortingOrder: 0
|
m_SortingOrder: 0
|
||||||
m_MaskInteraction: 0
|
m_MaskInteraction: 0
|
||||||
m_AdditionalVertexStreams: {fileID: 0}
|
m_AdditionalVertexStreams: {fileID: 0}
|
||||||
--- !u!136 &5033597944775254142
|
--- !u!136 &6093691026861389653
|
||||||
CapsuleCollider:
|
CapsuleCollider:
|
||||||
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: 7219310182397398916}
|
m_GameObject: {fileID: 2198048708000581807}
|
||||||
m_Material: {fileID: 0}
|
m_Material: {fileID: 0}
|
||||||
m_IncludeLayers:
|
m_IncludeLayers:
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
@@ -111,23 +111,19 @@ CapsuleCollider:
|
|||||||
m_ProvidesContacts: 0
|
m_ProvidesContacts: 0
|
||||||
m_Enabled: 1
|
m_Enabled: 1
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
m_Radius: 0.5
|
m_Radius: 0.5000001
|
||||||
m_Height: 2
|
m_Height: 2
|
||||||
m_Direction: 1
|
m_Direction: 1
|
||||||
m_Center: {x: 0, y: 0, z: 0}
|
m_Center: {x: 0.000000059604645, y: 0, z: -0.00000008940697}
|
||||||
--- !u!114 &2639250404559520579
|
--- !u!114 &4601941687390792571
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
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: 7219310182397398916}
|
m_GameObject: {fileID: 2198048708000581807}
|
||||||
m_Enabled: 1
|
m_Enabled: 1
|
||||||
m_EditorHideFlags: 0
|
m_EditorHideFlags: 0
|
||||||
m_Script: {fileID: 11500000, guid: 5886e2d0e6414ce98bf68f8e5ac887fc, type: 3}
|
m_Script: {fileID: 11500000, guid: 82fa71545d10e6ee187b00ae7fba2eea, type: 3}
|
||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier: Assembly-CSharp::Infrastructure.Unity.PowerUpViewAdapter
|
m_EditorClassIdentifier: Assembly-CSharp::Infrastructure.Unity.TeleporterAdapter
|
||||||
type: 1
|
|
||||||
duration: 10
|
|
||||||
pickupVfx: {fileID: 0}
|
|
||||||
meshRenderer: {fileID: 2173926958931993968}
|
|
||||||
7
Assets/Prefabs/Teleporter pad.prefab.meta
Normal file
7
Assets/Prefabs/Teleporter pad.prefab.meta
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 53f1de555c523511e9aaa1dee06fdf79
|
||||||
|
PrefabImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -155,6 +155,7 @@ MonoBehaviour:
|
|||||||
m_EditorClassIdentifier: Assembly-CSharp::Infrastructure.Unity.TileViewAdapter
|
m_EditorClassIdentifier: Assembly-CSharp::Infrastructure.Unity.TileViewAdapter
|
||||||
stableColor: {r: 0.08627451, g: 0.12941177, b: 0.24313726, a: 1}
|
stableColor: {r: 0.08627451, g: 0.12941177, b: 0.24313726, a: 1}
|
||||||
warningColor: {r: 1, g: 0.18039216, b: 0.3882353, a: 1}
|
warningColor: {r: 1, g: 0.18039216, b: 0.3882353, a: 1}
|
||||||
|
fragileColor: {r: 0.08627451, g: 0.12941177, b: 0.24313726, a: 0.5}
|
||||||
colorSpeed: 2
|
colorSpeed: 2
|
||||||
rb: {fileID: 6985771395868845393}
|
rb: {fileID: 6985771395868845393}
|
||||||
meshRenderer: {fileID: 1516947233778832648}
|
meshRenderer: {fileID: 1516947233778832648}
|
||||||
|
|||||||
@@ -633,6 +633,7 @@ MonoBehaviour:
|
|||||||
soundManager: {fileID: 1341134052}
|
soundManager: {fileID: 1341134052}
|
||||||
cameraController: {fileID: 1265730430}
|
cameraController: {fileID: 1265730430}
|
||||||
npcPrefab: {fileID: 6083523108754401876, guid: 4b3d84858334857368bde30df360ae3e, type: 3}
|
npcPrefab: {fileID: 6083523108754401876, guid: 4b3d84858334857368bde30df360ae3e, type: 3}
|
||||||
|
hunterNpcPrefab: {fileID: 4496988857626767934, guid: ab4e193839fef9a2189f27360914c044, type: 3}
|
||||||
floorsCount: 3
|
floorsCount: 3
|
||||||
floorHeightDistance: 15
|
floorHeightDistance: 15
|
||||||
scoreText: {fileID: 412275999}
|
scoreText: {fileID: 412275999}
|
||||||
@@ -640,8 +641,7 @@ MonoBehaviour:
|
|||||||
gameOverUi: {fileID: 87831902}
|
gameOverUi: {fileID: 87831902}
|
||||||
startScreenUi: {fileID: 1763855010}
|
startScreenUi: {fileID: 1763855010}
|
||||||
restartTime: 3
|
restartTime: 3
|
||||||
lightFootedPrefab: {fileID: 2639250404559520579, guid: 4ce47d492ed71cb5b9390762eab7a749, type: 3}
|
powerUpPrefab: {fileID: 7381336953128067686, guid: 8b540be4548e610709c2f7eccf8bf9c6, type: 3}
|
||||||
speedBoostPrefab: {fileID: 2639250404559520579, guid: 32d69de3e08c76e63a4b5086b87b12df, type: 3}
|
|
||||||
--- !u!4 &453022421
|
--- !u!4 &453022421
|
||||||
Transform:
|
Transform:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -672,6 +672,7 @@ MonoBehaviour:
|
|||||||
tilePrefab: {fileID: 2142595510769725438, guid: a84ad84e96942d35c824885a7c08a844, type: 3}
|
tilePrefab: {fileID: 2142595510769725438, guid: a84ad84e96942d35c824885a7c08a844, type: 3}
|
||||||
tileBreakVfxPrefab: {fileID: 3395603910160708684, guid: 7c5c893ba21562b2aad6bffb1887f4b1, type: 3}
|
tileBreakVfxPrefab: {fileID: 3395603910160708684, guid: 7c5c893ba21562b2aad6bffb1887f4b1, type: 3}
|
||||||
jumpPadPrefab: {fileID: 3258547662887829175, guid: e1d1bd44370c9986ebd4bb7730430a12, type: 3}
|
jumpPadPrefab: {fileID: 3258547662887829175, guid: e1d1bd44370c9986ebd4bb7730430a12, type: 3}
|
||||||
|
teleporterPrefab: {fileID: 4601941687390792571, guid: 53f1de555c523511e9aaa1dee06fdf79, type: 3}
|
||||||
gridSizeX: 20
|
gridSizeX: 20
|
||||||
gridSizeY: 20
|
gridSizeY: 20
|
||||||
floorsCount: 3
|
floorsCount: 3
|
||||||
|
|||||||
@@ -9,11 +9,13 @@ namespace Core.Domain
|
|||||||
private const string HighScoreKey = "HighScore";
|
private const string HighScoreKey = "HighScore";
|
||||||
private const float NpcSpawnTime = 4f;
|
private const float NpcSpawnTime = 4f;
|
||||||
private const float PowerUpSpawnInterval = 25f;
|
private const float PowerUpSpawnInterval = 25f;
|
||||||
|
|
||||||
public int Score { get; private set; }
|
public int Score { get; private set; }
|
||||||
public int HighScore { get; private set; }
|
public int HighScore { get; private set; }
|
||||||
public bool IsGameOver { get; private set; }
|
public bool IsGameOver { get; private set; }
|
||||||
|
|
||||||
|
public float TimeDilation { get; private set; } = 1.0f;
|
||||||
|
|
||||||
public event Action<int> OnScoreChanged;
|
public event Action<int> OnScoreChanged;
|
||||||
public event Action<string> OnOrbSpawned;
|
public event Action<string> OnOrbSpawned;
|
||||||
public event Action OnOrbReset;
|
public event Action OnOrbReset;
|
||||||
@@ -29,14 +31,21 @@ namespace Core.Domain
|
|||||||
private bool _npcSpawned;
|
private bool _npcSpawned;
|
||||||
private float _powerUpTimer;
|
private float _powerUpTimer;
|
||||||
|
|
||||||
|
private float _timeSlowTimer;
|
||||||
|
|
||||||
|
// Combo System
|
||||||
|
private float _lastOrbTime;
|
||||||
|
public int ComboMultiplier { get; private set; } = 1;
|
||||||
|
public event Action<int> OnComboUpdated;
|
||||||
|
|
||||||
public GameSession(List<Tile> tiles, IPersistenceService persistenceService)
|
public GameSession(List<Tile> tiles, IPersistenceService persistenceService)
|
||||||
{
|
{
|
||||||
_tiles = tiles;
|
_tiles = tiles;
|
||||||
_persistenceService = persistenceService;
|
_persistenceService = persistenceService;
|
||||||
|
|
||||||
Score = 0;
|
Score = 0;
|
||||||
IsGameOver = false;
|
IsGameOver = false;
|
||||||
|
|
||||||
HighScore = _persistenceService.Load(HighScoreKey, 0);
|
HighScore = _persistenceService.Load(HighScoreKey, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,56 +54,88 @@ namespace Core.Domain
|
|||||||
_timeSinceStart = 0f;
|
_timeSinceStart = 0f;
|
||||||
_powerUpTimer = 0f;
|
_powerUpTimer = 0f;
|
||||||
_npcSpawned = false;
|
_npcSpawned = false;
|
||||||
|
TimeDilation = 1.0f;
|
||||||
|
|
||||||
|
ComboMultiplier = 1;
|
||||||
|
_lastOrbTime = -999f;
|
||||||
|
|
||||||
SpawnNextOrb();
|
SpawnNextOrb();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Tick(float deltaTime)
|
public void Tick(float deltaTime)
|
||||||
{
|
{
|
||||||
if (IsGameOver) return;
|
if (IsGameOver) return;
|
||||||
|
|
||||||
_timeSinceStart += deltaTime;
|
_timeSinceStart += deltaTime;
|
||||||
if (!_npcSpawned && _timeSinceStart >= NpcSpawnTime)
|
if (!_npcSpawned && _timeSinceStart >= NpcSpawnTime)
|
||||||
{
|
{
|
||||||
_npcSpawned = true;
|
_npcSpawned = true;
|
||||||
OnSpawnNpc?.Invoke();
|
OnSpawnNpc?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
_powerUpTimer += deltaTime;
|
_powerUpTimer += deltaTime;
|
||||||
if (_powerUpTimer >= PowerUpSpawnInterval)
|
if (_powerUpTimer >= PowerUpSpawnInterval)
|
||||||
{
|
{
|
||||||
_powerUpTimer = 0f;
|
_powerUpTimer = 0f;
|
||||||
SpawnRandomPowerUp();
|
SpawnRandomPowerUp();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_timeSlowTimer > 0)
|
||||||
|
{
|
||||||
|
_timeSlowTimer -= deltaTime;
|
||||||
|
if (_timeSlowTimer <= 0)
|
||||||
|
{
|
||||||
|
TimeDilation = 1.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ActivateTimeSlow(float duration)
|
||||||
|
{
|
||||||
|
_timeSlowTimer = duration;
|
||||||
|
TimeDilation = 0.3f; // Slow down to 30%
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OrbCollected()
|
public void OrbCollected()
|
||||||
{
|
{
|
||||||
if (IsGameOver) return;
|
if (IsGameOver) return;
|
||||||
|
|
||||||
Score += 10;
|
// Combo Check (2 second window)
|
||||||
|
if (_timeSinceStart - _lastOrbTime < 2.0f)
|
||||||
|
{
|
||||||
|
ComboMultiplier++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ComboMultiplier = 1;
|
||||||
|
}
|
||||||
|
_lastOrbTime = _timeSinceStart;
|
||||||
|
|
||||||
|
OnComboUpdated?.Invoke(ComboMultiplier);
|
||||||
|
|
||||||
|
Score += 10 * ComboMultiplier;
|
||||||
OnScoreChanged?.Invoke(Score);
|
OnScoreChanged?.Invoke(Score);
|
||||||
SpawnNextOrb();
|
SpawnNextOrb();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SpawnNextOrb()
|
private void SpawnNextOrb()
|
||||||
{
|
{
|
||||||
var validTiles = _tiles.FindAll(t =>
|
var validTiles = _tiles.FindAll(t =>
|
||||||
t.CurrentState == TileState.Stable &&
|
t.CurrentState == TileState.Stable &&
|
||||||
t.Floor == _playerFloorIndex
|
t.Floor == _playerFloorIndex
|
||||||
);
|
);
|
||||||
|
|
||||||
if (validTiles.Count == 0)
|
if (validTiles.Count == 0)
|
||||||
{
|
{
|
||||||
validTiles = _tiles.FindAll(t => t.CurrentState == TileState.Stable);
|
validTiles = _tiles.FindAll(t => t.CurrentState == TileState.Stable);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (validTiles.Count == 0)
|
if (validTiles.Count == 0)
|
||||||
{
|
{
|
||||||
EndGame();
|
EndGame();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var pick = validTiles[_rng.Next(validTiles.Count)];
|
var pick = validTiles[_rng.Next(validTiles.Count)];
|
||||||
OnOrbSpawned?.Invoke(pick.Id);
|
OnOrbSpawned?.Invoke(pick.Id);
|
||||||
}
|
}
|
||||||
@@ -102,39 +143,56 @@ namespace Core.Domain
|
|||||||
public void EndGame()
|
public void EndGame()
|
||||||
{
|
{
|
||||||
if (IsGameOver) return;
|
if (IsGameOver) return;
|
||||||
|
|
||||||
IsGameOver = true;
|
IsGameOver = true;
|
||||||
|
|
||||||
if (Score > HighScore)
|
if (Score > HighScore)
|
||||||
{
|
{
|
||||||
HighScore = Score;
|
HighScore = Score;
|
||||||
_persistenceService.Save(HighScoreKey, HighScore);
|
_persistenceService.Save(HighScoreKey, HighScore);
|
||||||
}
|
}
|
||||||
|
|
||||||
OnGameOver?.Invoke();
|
OnGameOver?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetPlayerFloor(int floorIndex)
|
public void SetPlayerFloor(int floorIndex)
|
||||||
{
|
{
|
||||||
if (_playerFloorIndex == floorIndex) return;
|
if (_playerFloorIndex == floorIndex) return;
|
||||||
|
|
||||||
_playerFloorIndex = floorIndex;
|
_playerFloorIndex = floorIndex;
|
||||||
|
|
||||||
if (IsGameOver) return;
|
if (IsGameOver) return;
|
||||||
|
|
||||||
OnOrbReset?.Invoke();
|
OnOrbReset?.Invoke();
|
||||||
SpawnNextOrb();
|
SpawnNextOrb();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SpawnRandomPowerUp()
|
private void SpawnRandomPowerUp()
|
||||||
{
|
{
|
||||||
var validTiles = _tiles.FindAll(t => t.CurrentState == TileState.Stable);
|
var validTiles = _tiles.FindAll(t =>
|
||||||
|
t.CurrentState == TileState.Stable &&
|
||||||
|
t.Floor == _playerFloorIndex
|
||||||
|
);
|
||||||
|
|
||||||
|
if (validTiles.Count == 0)
|
||||||
|
{
|
||||||
|
validTiles = _tiles.FindAll(t => t.CurrentState == TileState.Stable);
|
||||||
|
}
|
||||||
|
|
||||||
if (validTiles.Count == 0) return;
|
if (validTiles.Count == 0) return;
|
||||||
|
|
||||||
var tile = validTiles[_rng.Next(validTiles.Count)];
|
var tile = validTiles[_rng.Next(validTiles.Count)];
|
||||||
|
|
||||||
var type = _rng.Next(0, 2) == 0 ? PowerUpType.LightFooted : PowerUpType.SpeedBoost;
|
var rand = _rng.Next(0, 4);
|
||||||
|
var type = PowerUpType.LightFooted;
|
||||||
|
switch (rand)
|
||||||
|
{
|
||||||
|
case 0: type = PowerUpType.LightFooted; break;
|
||||||
|
case 1: type = PowerUpType.SpeedBoost; break;
|
||||||
|
case 2: type = PowerUpType.Hover; break;
|
||||||
|
case 3: type = PowerUpType.TimeSlow; break;
|
||||||
|
}
|
||||||
|
|
||||||
OnSpawnPowerUp?.Invoke(type, tile.Id);
|
OnSpawnPowerUp?.Invoke(type, tile.Id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,5 +4,7 @@ namespace Core.Domain
|
|||||||
{
|
{
|
||||||
LightFooted,
|
LightFooted,
|
||||||
SpeedBoost,
|
SpeedBoost,
|
||||||
|
Hover,
|
||||||
|
TimeSlow
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6,5 +6,7 @@ namespace Core.Domain.Status.Effects
|
|||||||
{
|
{
|
||||||
public static readonly Color LightFootedColor = new Color(0.8f, 0.8f, 0.8f);
|
public static readonly Color LightFootedColor = new Color(0.8f, 0.8f, 0.8f);
|
||||||
public static readonly Color SpeedBoostColor = new Color(1f, 0.5f, 0f);
|
public static readonly Color SpeedBoostColor = new Color(1f, 0.5f, 0f);
|
||||||
|
public static readonly Color HoverColor = new Color(0.5f, 1f, 0.5f); // Green
|
||||||
|
public static readonly Color TimeSlowColor = new Color(0.2f, 0.2f, 1f); // Blue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
32
Assets/Scripts/Core/Domain/Status/Effects/HoverEffect.cs
Normal file
32
Assets/Scripts/Core/Domain/Status/Effects/HoverEffect.cs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
namespace Core.Domain.Status.Effects
|
||||||
|
{
|
||||||
|
public class HoverEffect : IStatusEffect
|
||||||
|
{
|
||||||
|
private float _duration;
|
||||||
|
|
||||||
|
public bool IsExpired => _duration <= 0;
|
||||||
|
|
||||||
|
public HoverEffect(float duration)
|
||||||
|
{
|
||||||
|
_duration = duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Tick(float deltaTime)
|
||||||
|
{
|
||||||
|
_duration -= deltaTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ModifyCapabilities(ref PlayerCapabilities caps)
|
||||||
|
{
|
||||||
|
caps.CanHover = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnApply()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnRemove()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: a774d5cade7c04beba69252a04501099
|
||||||
@@ -4,11 +4,13 @@ namespace Core.Domain.Status
|
|||||||
{
|
{
|
||||||
public bool CanTriggerDecay;
|
public bool CanTriggerDecay;
|
||||||
public float SpeedMultiplier;
|
public float SpeedMultiplier;
|
||||||
|
public bool CanHover;
|
||||||
|
|
||||||
public static PlayerCapabilities Default => new PlayerCapabilities
|
public static PlayerCapabilities Default => new PlayerCapabilities
|
||||||
{
|
{
|
||||||
CanTriggerDecay = true,
|
CanTriggerDecay = true,
|
||||||
SpeedMultiplier = 1f
|
SpeedMultiplier = 1f,
|
||||||
|
CanHover = false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,21 +6,23 @@ namespace Core.Domain
|
|||||||
{
|
{
|
||||||
public string Id { get; }
|
public string Id { get; }
|
||||||
public int Floor { get; }
|
public int Floor { get; }
|
||||||
|
public TileType Type { get; }
|
||||||
|
|
||||||
public TileState CurrentState { get; private set; }
|
public TileState CurrentState { get; private set; }
|
||||||
|
|
||||||
private readonly float _warningDuration;
|
private readonly float _warningDuration;
|
||||||
private readonly float _fallingDuration;
|
private readonly float _fallingDuration;
|
||||||
|
|
||||||
private float _stateTimer;
|
private float _stateTimer;
|
||||||
|
|
||||||
public event Action<Tile> OnStateChanged;
|
public event Action<Tile> OnStateChanged;
|
||||||
|
|
||||||
public Tile(string id, int floor, float warningDuration, float fallingDuration)
|
public Tile(string id, int floor, float warningDuration, float fallingDuration, TileType type = TileType.Normal)
|
||||||
{
|
{
|
||||||
Id = id;
|
Id = id;
|
||||||
Floor = floor;
|
Floor = floor;
|
||||||
|
Type = type;
|
||||||
|
|
||||||
_warningDuration = warningDuration;
|
_warningDuration = warningDuration;
|
||||||
_fallingDuration = fallingDuration;
|
_fallingDuration = fallingDuration;
|
||||||
CurrentState = TileState.Stable;
|
CurrentState = TileState.Stable;
|
||||||
@@ -30,16 +32,23 @@ namespace Core.Domain
|
|||||||
{
|
{
|
||||||
if (CurrentState == TileState.Stable)
|
if (CurrentState == TileState.Stable)
|
||||||
{
|
{
|
||||||
TransitionTo(TileState.Warning);
|
if (Type == TileType.Fragile)
|
||||||
|
{
|
||||||
|
TransitionTo(TileState.Falling);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TransitionTo(TileState.Warning);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Tick(float deltaTime)
|
public void Tick(float deltaTime)
|
||||||
{
|
{
|
||||||
if (CurrentState == TileState.Stable || CurrentState == TileState.Destroyed) return;
|
if (CurrentState == TileState.Stable || CurrentState == TileState.Destroyed) return;
|
||||||
|
|
||||||
_stateTimer += deltaTime;
|
_stateTimer += deltaTime;
|
||||||
|
|
||||||
if (CurrentState == TileState.Warning && _stateTimer >= _warningDuration)
|
if (CurrentState == TileState.Warning && _stateTimer >= _warningDuration)
|
||||||
{
|
{
|
||||||
TransitionTo(TileState.Falling);
|
TransitionTo(TileState.Falling);
|
||||||
|
|||||||
8
Assets/Scripts/Core/Domain/TileType.cs
Normal file
8
Assets/Scripts/Core/Domain/TileType.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
namespace Core.Domain
|
||||||
|
{
|
||||||
|
public enum TileType
|
||||||
|
{
|
||||||
|
Normal,
|
||||||
|
Fragile
|
||||||
|
}
|
||||||
|
}
|
||||||
2
Assets/Scripts/Core/Domain/TileType.cs.meta
Normal file
2
Assets/Scripts/Core/Domain/TileType.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 0ac9ceadb8e587481aa83f4f78997207
|
||||||
@@ -9,6 +9,10 @@ namespace Infrastructure.Unity
|
|||||||
[SerializeField] private Vector3 offset = new(-20, 20, -20);
|
[SerializeField] private Vector3 offset = new(-20, 20, -20);
|
||||||
[SerializeField] private float smoothSpeed = 5f;
|
[SerializeField] private float smoothSpeed = 5f;
|
||||||
|
|
||||||
|
private Vector3 _originalPos; // This field is declared but not used in the provided LateUpdate logic.
|
||||||
|
private float _shakeTimer;
|
||||||
|
private float _shakeMagnitude;
|
||||||
|
|
||||||
private void LateUpdate()
|
private void LateUpdate()
|
||||||
{
|
{
|
||||||
if (!target) return;
|
if (!target) return;
|
||||||
@@ -17,14 +21,30 @@ namespace Infrastructure.Unity
|
|||||||
// so the camera doesn't jitter too much, only tracking Y (falling).
|
// so the camera doesn't jitter too much, only tracking Y (falling).
|
||||||
// For a dynamic feel, let's track everything loosely.
|
// For a dynamic feel, let's track everything loosely.
|
||||||
|
|
||||||
var desiredPos = target.position + offset;
|
var targetPos = target.position + offset;
|
||||||
|
var smoothPos = Vector3.Lerp(transform.position, targetPos, smoothSpeed * Time.deltaTime);
|
||||||
transform.position = Vector3.Lerp(transform.position, desiredPos, Time.deltaTime * smoothSpeed);
|
|
||||||
|
if (_shakeTimer > 0)
|
||||||
|
{
|
||||||
|
_shakeTimer -= Time.deltaTime;
|
||||||
|
var shakeOffset = Random.insideUnitSphere * _shakeMagnitude;
|
||||||
|
transform.position = smoothPos + shakeOffset;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
transform.position = smoothPos;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetTarget(Transform newTarget)
|
public void SetTarget(Transform newTarget)
|
||||||
{
|
{
|
||||||
target = newTarget;
|
target = newTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Shake(float duration, float magnitude)
|
||||||
|
{
|
||||||
|
_shakeTimer = duration;
|
||||||
|
_shakeMagnitude = magnitude;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,7 +10,7 @@ namespace Infrastructure.Unity
|
|||||||
{
|
{
|
||||||
public class GameBootstrap : MonoBehaviour
|
public class GameBootstrap : MonoBehaviour
|
||||||
{
|
{
|
||||||
[Header("Infrastructure")]
|
[Header("Infrastructure")]
|
||||||
[SerializeField] private LevelGenerator levelGenerator;
|
[SerializeField] private LevelGenerator levelGenerator;
|
||||||
[SerializeField] private OrbViewAdapter orbPrefab;
|
[SerializeField] private OrbViewAdapter orbPrefab;
|
||||||
[SerializeField] private PlayerController playerPrefab;
|
[SerializeField] private PlayerController playerPrefab;
|
||||||
@@ -18,23 +18,23 @@ namespace Infrastructure.Unity
|
|||||||
[SerializeField] private SoundManager soundManager;
|
[SerializeField] private SoundManager soundManager;
|
||||||
[SerializeField] private CameraController cameraController;
|
[SerializeField] private CameraController cameraController;
|
||||||
[SerializeField] private NpcController npcPrefab;
|
[SerializeField] private NpcController npcPrefab;
|
||||||
|
[SerializeField] private HunterNpcController hunterNpcPrefab;
|
||||||
|
|
||||||
[Header("Level Generation")]
|
[Header("Level Generation")]
|
||||||
[SerializeField] private int floorsCount = 3;
|
[SerializeField] private int floorsCount = 3;
|
||||||
[SerializeField] private float floorHeightDistance = 15f;
|
[SerializeField] private float floorHeightDistance = 15f;
|
||||||
|
|
||||||
[Header("Ui")]
|
[Header("Ui")]
|
||||||
[SerializeField] private TMP_Text scoreText;
|
[SerializeField] private TMP_Text scoreText;
|
||||||
[SerializeField] private TMP_Text highScoreText;
|
[SerializeField] private TMP_Text highScoreText;
|
||||||
[SerializeField] private GameObject gameOverUi;
|
[SerializeField] private GameObject gameOverUi;
|
||||||
[SerializeField] private GameObject startScreenUi;
|
[SerializeField] private GameObject startScreenUi;
|
||||||
|
|
||||||
[Header("Settings")]
|
[Header("Settings")]
|
||||||
[SerializeField] private float restartTime = 3f;
|
[SerializeField] private float restartTime = 3f;
|
||||||
|
|
||||||
[Header("Power Ups")]
|
[Header("Power Ups")]
|
||||||
[SerializeField] private PowerUpViewAdapter lightFootedPrefab;
|
[SerializeField] private PowerUpViewAdapter powerUpPrefab;
|
||||||
[SerializeField] private PowerUpViewAdapter speedBoostPrefab;
|
|
||||||
|
|
||||||
private readonly List<Tile> _allTiles = new();
|
private readonly List<Tile> _allTiles = new();
|
||||||
private readonly Dictionary<string, TileViewAdapter> _tileViews = new();
|
private readonly Dictionary<string, TileViewAdapter> _tileViews = new();
|
||||||
@@ -59,17 +59,20 @@ namespace Infrastructure.Unity
|
|||||||
|
|
||||||
private void Start()
|
private void Start()
|
||||||
{
|
{
|
||||||
if (levelGenerator) levelGenerator.Generate(soundManager, _allTiles, _tileViews);
|
|
||||||
|
|
||||||
SpawnDeathPlane();
|
|
||||||
SpawnPlayer();
|
|
||||||
|
|
||||||
if (gameOverUi) gameOverUi.SetActive(false);
|
|
||||||
if (startScreenUi) startScreenUi.SetActive(true);
|
|
||||||
|
|
||||||
_persistenceService = new PlayerPrefsPersistenceAdapter();
|
_persistenceService = new PlayerPrefsPersistenceAdapter();
|
||||||
_gameSession = new GameSession(_allTiles, _persistenceService);
|
_gameSession = new GameSession(_allTiles, _persistenceService);
|
||||||
|
|
||||||
|
// Set Theme based on High Score
|
||||||
|
ThemeManager.CurrentTheme = ThemeManager.GetTheme(_gameSession.HighScore);
|
||||||
|
|
||||||
|
if (levelGenerator) levelGenerator.Generate(soundManager, _allTiles, _tileViews, cameraController);
|
||||||
|
|
||||||
|
SpawnDeathPlane();
|
||||||
|
SpawnPlayer();
|
||||||
|
|
||||||
|
if (gameOverUi) gameOverUi.SetActive(false);
|
||||||
|
if (startScreenUi) startScreenUi.SetActive(true);
|
||||||
|
|
||||||
WireEvents();
|
WireEvents();
|
||||||
UpdateScoreUi(_gameSession.Score);
|
UpdateScoreUi(_gameSession.Score);
|
||||||
}
|
}
|
||||||
@@ -90,34 +93,39 @@ namespace Infrastructure.Unity
|
|||||||
{
|
{
|
||||||
var playerY = _playerInstance.transform.position.y;
|
var playerY = _playerInstance.transform.position.y;
|
||||||
var currentFloor = Mathf.RoundToInt(-playerY / floorHeightDistance);
|
var currentFloor = Mathf.RoundToInt(-playerY / floorHeightDistance);
|
||||||
|
|
||||||
currentFloor = Mathf.Clamp(currentFloor, 0, floorsCount - 1);
|
currentFloor = Mathf.Clamp(currentFloor, 0, floorsCount - 1);
|
||||||
|
|
||||||
_gameSession.SetPlayerFloor(currentFloor);
|
_gameSession.SetPlayerFloor(currentFloor);
|
||||||
}
|
}
|
||||||
|
|
||||||
var dt = Time.deltaTime;
|
var dt = Time.deltaTime;
|
||||||
|
|
||||||
if (_isGameRunning) _gameSession.Tick(dt);
|
if (_isGameRunning) _gameSession.Tick(dt);
|
||||||
|
|
||||||
|
var dilation = _gameSession.TimeDilation;
|
||||||
|
|
||||||
|
// Hard Mode: Decay faster as score increases
|
||||||
|
var decayMultiplier = 1.0f + (_gameSession.Score / 500f);
|
||||||
|
|
||||||
for (var i = _allTiles.Count - 1; i >= 0; i--)
|
for (var i = _allTiles.Count - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
_allTiles[i].Tick(dt);
|
_allTiles[i].Tick(dt * dilation * decayMultiplier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SpawnVisualOrb(string tileId)
|
private void SpawnVisualOrb(string tileId)
|
||||||
{
|
{
|
||||||
if (_currentOrbInstance) Destroy(_currentOrbInstance);
|
if (_currentOrbInstance) Destroy(_currentOrbInstance);
|
||||||
|
|
||||||
if (!_tileViews.TryGetValue(tileId, out var tileView)) return;
|
if (!_tileViews.TryGetValue(tileId, out var tileView)) return;
|
||||||
if (!tileView) return;
|
if (!tileView) return;
|
||||||
|
|
||||||
var spawnPos = tileView.transform.position + Vector3.up;
|
var spawnPos = tileView.transform.position + Vector3.up;
|
||||||
var orb = Instantiate(orbPrefab, spawnPos, Quaternion.identity);
|
var orb = Instantiate(orbPrefab, spawnPos, Quaternion.identity);
|
||||||
|
|
||||||
orb.OnCollected += () => _gameSession.OrbCollected();
|
orb.OnCollected += () => _gameSession.OrbCollected();
|
||||||
|
|
||||||
_currentOrbInstance = orb.gameObject;
|
_currentOrbInstance = orb.gameObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,22 +140,25 @@ namespace Infrastructure.Unity
|
|||||||
private void UpdateScoreUi(int newScore)
|
private void UpdateScoreUi(int newScore)
|
||||||
{
|
{
|
||||||
if (!scoreText) return;
|
if (!scoreText) return;
|
||||||
|
|
||||||
scoreText.text = $"Data: {newScore}";
|
var combo = _gameSession?.ComboMultiplier ?? 1;
|
||||||
|
var comboText = combo > 1 ? $" (x{combo})" : "";
|
||||||
if (highScoreText) highScoreText.text = $"BEST: {_gameSession.HighScore}";
|
|
||||||
|
scoreText.text = $"Data: {newScore}{comboText}";
|
||||||
|
|
||||||
|
if (highScoreText && _gameSession != null) highScoreText.text = $"BEST: {_gameSession.HighScore}";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SpawnPlayer()
|
private void SpawnPlayer()
|
||||||
{
|
{
|
||||||
var spawnPos = new Vector3(0f, 5f, 0f);
|
var spawnPos = new Vector3(0f, 5f, 0f);
|
||||||
_playerInstance = Instantiate(playerPrefab, spawnPos, Quaternion.identity);
|
_playerInstance = Instantiate(playerPrefab, spawnPos, Quaternion.identity);
|
||||||
|
|
||||||
_playerInstance.enabled = false;
|
_playerInstance.enabled = false;
|
||||||
|
|
||||||
_playerInstance.Rigidbody.isKinematic = true;
|
_playerInstance.Rigidbody.isKinematic = true;
|
||||||
|
|
||||||
if (cameraController)
|
if (cameraController)
|
||||||
{
|
{
|
||||||
cameraController.SetTarget(_playerInstance.transform);
|
cameraController.SetTarget(_playerInstance.transform);
|
||||||
@@ -162,7 +173,7 @@ namespace Infrastructure.Unity
|
|||||||
var pos = new Vector3(levelGenerator.GridSizeX / 2f, lowestY, levelGenerator.GridSizeY / 2f);
|
var pos = new Vector3(levelGenerator.GridSizeX / 2f, lowestY, levelGenerator.GridSizeY / 2f);
|
||||||
var plane = Instantiate(deathPlanePrefab, pos, Quaternion.identity);
|
var plane = Instantiate(deathPlanePrefab, pos, Quaternion.identity);
|
||||||
plane.transform.localScale = new Vector3(levelGenerator.GridSizeX * 2f, 1f, levelGenerator.GridSizeY * 2f);
|
plane.transform.localScale = new Vector3(levelGenerator.GridSizeX * 2f, 1f, levelGenerator.GridSizeY * 2f);
|
||||||
|
|
||||||
plane.OnPlayerFell += () => _gameSession.EndGame();
|
plane.OnPlayerFell += () => _gameSession.EndGame();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,7 +188,7 @@ namespace Infrastructure.Unity
|
|||||||
private IEnumerator RestartRoutine()
|
private IEnumerator RestartRoutine()
|
||||||
{
|
{
|
||||||
yield return new WaitForSeconds(restartTime);
|
yield return new WaitForSeconds(restartTime);
|
||||||
|
|
||||||
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
|
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,7 +202,7 @@ namespace Infrastructure.Unity
|
|||||||
_gameSession.OnSpawnPowerUp += SpawnPowerUp;
|
_gameSession.OnSpawnPowerUp += SpawnPowerUp;
|
||||||
|
|
||||||
if (!soundManager) return;
|
if (!soundManager) return;
|
||||||
|
|
||||||
_gameSession.OnScoreChanged += _ => soundManager.PlayScore();
|
_gameSession.OnScoreChanged += _ => soundManager.PlayScore();
|
||||||
_gameSession.OnGameOver += () =>
|
_gameSession.OnGameOver += () =>
|
||||||
{
|
{
|
||||||
@@ -202,18 +213,26 @@ namespace Infrastructure.Unity
|
|||||||
|
|
||||||
private void SpawnNpc()
|
private void SpawnNpc()
|
||||||
{
|
{
|
||||||
if (!npcPrefab) return;
|
|
||||||
|
|
||||||
var spawnPos = new Vector3(levelGenerator.GridSizeX / 2f, 7f, levelGenerator.GridSizeY / 2f);
|
var spawnPos = new Vector3(levelGenerator.GridSizeX / 2f, 7f, levelGenerator.GridSizeY / 2f);
|
||||||
Instantiate(npcPrefab, spawnPos, Quaternion.identity);
|
|
||||||
|
// 30% chance for Hunter if player available
|
||||||
|
if (_playerInstance && hunterNpcPrefab && Random.value < 0.3f)
|
||||||
|
{
|
||||||
|
var hunter = Instantiate(hunterNpcPrefab, spawnPos, Quaternion.identity);
|
||||||
|
hunter.Initialize(_playerInstance);
|
||||||
|
}
|
||||||
|
else if (npcPrefab)
|
||||||
|
{
|
||||||
|
Instantiate(npcPrefab, spawnPos, Quaternion.identity);
|
||||||
|
}
|
||||||
|
|
||||||
soundManager.PlayNpcSpawn();
|
soundManager.PlayNpcSpawn();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void StartGameSequence()
|
private void StartGameSequence()
|
||||||
{
|
{
|
||||||
_isGameRunning = true;
|
_isGameRunning = true;
|
||||||
|
|
||||||
if (startScreenUi) startScreenUi.SetActive(false);
|
if (startScreenUi) startScreenUi.SetActive(false);
|
||||||
|
|
||||||
if (soundManager)
|
if (soundManager)
|
||||||
@@ -227,7 +246,7 @@ namespace Infrastructure.Unity
|
|||||||
_playerInstance.enabled = true;
|
_playerInstance.enabled = true;
|
||||||
_playerInstance.Rigidbody.isKinematic = false;
|
_playerInstance.Rigidbody.isKinematic = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_gameSession.StartGame();
|
_gameSession.StartGame();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -237,15 +256,17 @@ namespace Infrastructure.Unity
|
|||||||
if (!tileView) return;
|
if (!tileView) return;
|
||||||
|
|
||||||
var spawnPos = tileView.transform.position + Vector3.up * 0.5f;
|
var spawnPos = tileView.transform.position + Vector3.up * 0.5f;
|
||||||
|
var instance = Instantiate(powerUpPrefab, spawnPos, Quaternion.identity);
|
||||||
var prefabToSpawn = type == PowerUpType.LightFooted
|
|
||||||
? lightFootedPrefab
|
|
||||||
: speedBoostPrefab;
|
|
||||||
|
|
||||||
if (!prefabToSpawn) return;
|
|
||||||
|
|
||||||
var instance = Instantiate(prefabToSpawn, spawnPos, Quaternion.identity);
|
|
||||||
instance.Configure(type);
|
instance.Configure(type);
|
||||||
|
|
||||||
|
instance.OnCollected += (t) =>
|
||||||
|
{
|
||||||
|
if (t == PowerUpType.TimeSlow)
|
||||||
|
{
|
||||||
|
_gameSession.ActivateTimeSlow(10f);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
59
Assets/Scripts/Infrastructure/Unity/HunterNpcController.cs
Normal file
59
Assets/Scripts/Infrastructure/Unity/HunterNpcController.cs
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
using KBCore.Refs;
|
||||||
|
|
||||||
|
namespace Infrastructure.Unity
|
||||||
|
{
|
||||||
|
[RequireComponent(typeof(Rigidbody))]
|
||||||
|
public class HunterNpcController : MonoBehaviour
|
||||||
|
{
|
||||||
|
[SerializeField] private float moveSpeed = 7f;
|
||||||
|
[SerializeField] private LayerMask tileLayer;
|
||||||
|
|
||||||
|
[Self] [SerializeField] private Rigidbody rb;
|
||||||
|
|
||||||
|
private PlayerController _target;
|
||||||
|
|
||||||
|
public void Initialize(PlayerController target)
|
||||||
|
{
|
||||||
|
_target = target;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FixedUpdate()
|
||||||
|
{
|
||||||
|
if (_target == null) return;
|
||||||
|
|
||||||
|
if (IsGrounded())
|
||||||
|
{
|
||||||
|
var direction = (_target.transform.position - transform.position).normalized;
|
||||||
|
// Flatten direction to avoid flying/digging
|
||||||
|
direction.y = 0;
|
||||||
|
direction.Normalize();
|
||||||
|
|
||||||
|
rb.MovePosition(rb.position + direction * (moveSpeed * Time.fixedDeltaTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trigger tiles
|
||||||
|
if (Physics.Raycast(transform.position, Vector3.down, out var hit, 1.5f, tileLayer))
|
||||||
|
{
|
||||||
|
if (hit.collider.TryGetComponent<TileViewAdapter>(out var tile))
|
||||||
|
{
|
||||||
|
tile.OnPlayerStep();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsGrounded()
|
||||||
|
{
|
||||||
|
return Physics.Raycast(transform.position, Vector3.down, out var hit, 1.15f, tileLayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDrawGizmos()
|
||||||
|
{
|
||||||
|
if (_target)
|
||||||
|
{
|
||||||
|
Gizmos.color = Color.red;
|
||||||
|
Gizmos.DrawLine(transform.position, _target.transform.position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d87e12fdb2c23b238910064019f2ad59
|
||||||
@@ -10,6 +10,7 @@ namespace Infrastructure.Unity
|
|||||||
[SerializeField] private TileViewAdapter tilePrefab;
|
[SerializeField] private TileViewAdapter tilePrefab;
|
||||||
[SerializeField] private ParticleSystem tileBreakVfxPrefab;
|
[SerializeField] private ParticleSystem tileBreakVfxPrefab;
|
||||||
[SerializeField] private JumpPadAdapter jumpPadPrefab;
|
[SerializeField] private JumpPadAdapter jumpPadPrefab;
|
||||||
|
[SerializeField] private TeleporterAdapter teleporterPrefab;
|
||||||
|
|
||||||
[Header("Settings")]
|
[Header("Settings")]
|
||||||
[SerializeField] private int gridSizeX = 10;
|
[SerializeField] private int gridSizeX = 10;
|
||||||
@@ -18,23 +19,27 @@ namespace Infrastructure.Unity
|
|||||||
[SerializeField] private float floorHeightDistance = 15f;
|
[SerializeField] private float floorHeightDistance = 15f;
|
||||||
[SerializeField] private float decayTime = 0.5f;
|
[SerializeField] private float decayTime = 0.5f;
|
||||||
[SerializeField] private float fallingTime = 2.0f;
|
[SerializeField] private float fallingTime = 2.0f;
|
||||||
|
|
||||||
public float FloorHeightDistance => floorHeightDistance;
|
public float FloorHeightDistance => floorHeightDistance;
|
||||||
public int FloorsCount => floorsCount;
|
public int FloorsCount => floorsCount;
|
||||||
public int GridSizeX => gridSizeX;
|
public int GridSizeX => gridSizeX;
|
||||||
public int GridSizeY => gridSizeY;
|
public int GridSizeY => gridSizeY;
|
||||||
|
|
||||||
public void Generate(SoundManager soundManager, List<Tile> allTiles, Dictionary<string, TileViewAdapter> tileViews)
|
private TilePool _tilePool;
|
||||||
|
|
||||||
|
public void Generate(SoundManager soundManager, List<Tile> allTiles, Dictionary<string, TileViewAdapter> tileViews, CameraController camera)
|
||||||
{
|
{
|
||||||
GenerateFloor(0, MapPatterns.GenerateSquare(gridSizeX, gridSizeY), soundManager, allTiles, tileViews);
|
_tilePool = new TilePool(tilePrefab, transform);
|
||||||
|
|
||||||
GenerateFloor(1, MapPatterns.GenerateDonut(gridSizeX, Mathf.FloorToInt(gridSizeX / 3f)), soundManager, allTiles, tileViews);
|
GenerateFloor(0, MapPatterns.GenerateSquare(gridSizeX, gridSizeY), soundManager, allTiles, tileViews, camera);
|
||||||
|
|
||||||
GenerateFloor(2, MapPatterns.GenerateCircle(gridSizeX), soundManager, allTiles, tileViews);
|
GenerateFloor(1, MapPatterns.GenerateDonut(gridSizeX, Mathf.FloorToInt(gridSizeX / 3f)), soundManager, allTiles, tileViews, camera);
|
||||||
|
|
||||||
|
GenerateFloor(2, MapPatterns.GenerateCircle(gridSizeX), soundManager, allTiles, tileViews, camera);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GenerateFloor(int floorIndex, List<Vector2Int> coordinates, SoundManager soundManager,
|
private void GenerateFloor(int floorIndex, List<Vector2Int> coordinates, SoundManager soundManager,
|
||||||
List<Tile> allTiles, Dictionary<string, TileViewAdapter> tileViews)
|
List<Tile> allTiles, Dictionary<string, TileViewAdapter> tileViews, CameraController camera)
|
||||||
{
|
{
|
||||||
var yOffset = -(floorIndex * floorHeightDistance);
|
var yOffset = -(floorIndex * floorHeightDistance);
|
||||||
var xOffset = gridSizeX / 2f;
|
var xOffset = gridSizeX / 2f;
|
||||||
@@ -43,46 +48,77 @@ namespace Infrastructure.Unity
|
|||||||
foreach (var coord in coordinates)
|
foreach (var coord in coordinates)
|
||||||
{
|
{
|
||||||
var pos = new Vector3(coord.x - xOffset, yOffset, coord.y - zOffset);
|
var pos = new Vector3(coord.x - xOffset, yOffset, coord.y - zOffset);
|
||||||
CreateTile(pos, $"{floorIndex}_{coord.x}_{coord.y}", floorIndex, soundManager, allTiles, tileViews);
|
CreateTile(pos, $"{floorIndex}_{coord.x}_{coord.y}", floorIndex, soundManager, allTiles, tileViews, camera);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (floorIndex > 0 && jumpPadPrefab)
|
if (floorIndex > 0 && jumpPadPrefab)
|
||||||
{
|
{
|
||||||
var validSpot = coordinates[Random.Range(0, coordinates.Count)];
|
var validSpot = coordinates[Random.Range(0, coordinates.Count)];
|
||||||
var padPos = new Vector3(validSpot.x - xOffset, yOffset + 0.6f, validSpot.y - zOffset);
|
var padPos = new Vector3(validSpot.x - xOffset, yOffset + 0.6f, validSpot.y - zOffset);
|
||||||
|
|
||||||
Instantiate(jumpPadPrefab, padPos, Quaternion.identity, transform);
|
Instantiate(jumpPadPrefab, padPos, Quaternion.identity, transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (floorIndex > 0 && teleporterPrefab && coordinates.Count > 5)
|
||||||
|
{
|
||||||
|
// Spawn a pair of teleporters
|
||||||
|
var indexA = Random.Range(0, coordinates.Count);
|
||||||
|
int indexB;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
indexB = Random.Range(0, coordinates.Count);
|
||||||
|
} while (indexB == indexA);
|
||||||
|
|
||||||
|
var spotA = coordinates[indexA];
|
||||||
|
var spotB = coordinates[indexB];
|
||||||
|
|
||||||
|
var posA = new Vector3(spotA.x - xOffset, yOffset + 0.6f, spotA.y - zOffset);
|
||||||
|
var posB = new Vector3(spotB.x - xOffset, yOffset + 0.6f, spotB.y - zOffset);
|
||||||
|
|
||||||
|
var telA = Instantiate(teleporterPrefab, posA, Quaternion.identity, transform);
|
||||||
|
var telB = Instantiate(teleporterPrefab, posB, Quaternion.identity, transform);
|
||||||
|
|
||||||
|
telA.Initialize(telB.transform);
|
||||||
|
telB.Initialize(telA.transform);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateTile(Vector3 position, string id, int floorIndex, SoundManager soundManager,
|
private void CreateTile(Vector3 position, string id, int floorIndex, SoundManager soundManager,
|
||||||
List<Tile> allTiles, Dictionary<string, TileViewAdapter> tileViews)
|
List<Tile> allTiles, Dictionary<string, TileViewAdapter> tileViews, CameraController camera)
|
||||||
{
|
{
|
||||||
var go = Instantiate(tilePrefab, position, Quaternion.identity, transform);
|
var go = _tilePool.Get();
|
||||||
|
go.transform.position = position;
|
||||||
|
go.transform.rotation = Quaternion.identity;
|
||||||
go.transform.localScale = Vector3.one * 0.95f;
|
go.transform.localScale = Vector3.one * 0.95f;
|
||||||
|
|
||||||
var tileLogic = new Tile(id, floorIndex, decayTime, fallingTime);
|
|
||||||
|
|
||||||
go.Initialize(tileLogic);
|
|
||||||
|
|
||||||
if (soundManager)
|
// 15% chance to be Fragile
|
||||||
|
var isFragile = Random.value < 0.15f;
|
||||||
|
var type = isFragile ? TileType.Fragile : TileType.Normal;
|
||||||
|
|
||||||
|
var tileLogic = new Tile(id, floorIndex, decayTime, fallingTime, type);
|
||||||
|
|
||||||
|
go.Initialize(tileLogic, (t) => _tilePool.Return(t));
|
||||||
|
|
||||||
|
tileLogic.OnStateChanged += (t) =>
|
||||||
{
|
{
|
||||||
tileLogic.OnStateChanged += (t) =>
|
if (t.CurrentState == TileState.Warning)
|
||||||
{
|
{
|
||||||
if (t.CurrentState == TileState.Warning)
|
soundManager?.PlayTileWarning(position);
|
||||||
|
}
|
||||||
|
else if (t.CurrentState == TileState.Falling)
|
||||||
|
{
|
||||||
|
soundManager?.PlayTileBreak(position);
|
||||||
|
if (t.Type == TileType.Fragile)
|
||||||
{
|
{
|
||||||
soundManager.PlayTileWarning(position);
|
camera?.Shake(0.1f, 0.05f);
|
||||||
}
|
}
|
||||||
else if (t.CurrentState == TileState.Falling)
|
|
||||||
|
if (tileBreakVfxPrefab)
|
||||||
{
|
{
|
||||||
soundManager.PlayTileBreak(position);
|
Instantiate(tileBreakVfxPrefab, position, Quaternion.identity);
|
||||||
if (tileBreakVfxPrefab)
|
|
||||||
{
|
|
||||||
Instantiate(tileBreakVfxPrefab, position, Quaternion.identity);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
allTiles.Add(tileLogic);
|
allTiles.Add(tileLogic);
|
||||||
tileViews.Add(id, go);
|
tileViews.Add(id, go);
|
||||||
|
|||||||
@@ -14,27 +14,27 @@ namespace Infrastructure.Unity
|
|||||||
private float moveSpeed = 8f;
|
private float moveSpeed = 8f;
|
||||||
[SerializeField] private float maxVelocityChange = 10f;
|
[SerializeField] private float maxVelocityChange = 10f;
|
||||||
[SerializeField] private float snapForce = 15f;
|
[SerializeField] private float snapForce = 15f;
|
||||||
|
|
||||||
[Header("Controls")]
|
[Header("Controls")]
|
||||||
[SerializeField] private bool useCameraRelativeMovement = true;
|
[SerializeField] private bool useCameraRelativeMovement = true;
|
||||||
|
|
||||||
[Header("Interaction")]
|
[Header("Interaction")]
|
||||||
[SerializeField] private LayerMask tileLayer;
|
[SerializeField] private LayerMask tileLayer;
|
||||||
[SerializeField] private float groundCheckDistance = 1.5f;
|
[SerializeField] private float groundCheckDistance = 1.5f;
|
||||||
|
|
||||||
[Self] [SerializeField] private Rigidbody rb;
|
[Self][SerializeField] private Rigidbody rb;
|
||||||
|
|
||||||
private InputSystem_Actions _actions;
|
private InputSystem_Actions _actions;
|
||||||
private Vector2 _moveInput;
|
private Vector2 _moveInput;
|
||||||
private Transform _camTransform;
|
private Transform _camTransform;
|
||||||
|
|
||||||
public Rigidbody Rigidbody => rb;
|
public Rigidbody Rigidbody => rb;
|
||||||
public StatusManager Status { get; private set; }
|
public StatusManager Status { get; private set; }
|
||||||
|
|
||||||
private void OnEnable()
|
private void OnEnable()
|
||||||
{
|
{
|
||||||
_actions.Player.Enable();
|
_actions.Player.Enable();
|
||||||
|
|
||||||
_actions.Player.Move.performed += OnMovePerformed;
|
_actions.Player.Move.performed += OnMovePerformed;
|
||||||
_actions.Player.Move.canceled += OnMoveCanceled;
|
_actions.Player.Move.canceled += OnMoveCanceled;
|
||||||
}
|
}
|
||||||
@@ -43,7 +43,7 @@ namespace Infrastructure.Unity
|
|||||||
{
|
{
|
||||||
_actions.Player.Move.performed -= OnMovePerformed;
|
_actions.Player.Move.performed -= OnMovePerformed;
|
||||||
_actions.Player.Move.canceled -= OnMoveCanceled;
|
_actions.Player.Move.canceled -= OnMoveCanceled;
|
||||||
|
|
||||||
_actions.Player.Disable();
|
_actions.Player.Disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,19 +51,22 @@ namespace Infrastructure.Unity
|
|||||||
{
|
{
|
||||||
_actions = new InputSystem_Actions();
|
_actions = new InputSystem_Actions();
|
||||||
Status = new StatusManager();
|
Status = new StatusManager();
|
||||||
|
|
||||||
if (Camera.main)
|
if (Camera.main)
|
||||||
{
|
{
|
||||||
_camTransform = Camera.main.transform;
|
_camTransform = Camera.main.transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
rb.freezeRotation = true;
|
rb.freezeRotation = true;
|
||||||
rb.useGravity = true;
|
// RB gravity is controlled by capabilities
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Update()
|
private void Update()
|
||||||
{
|
{
|
||||||
Status.Tick(Time.deltaTime);
|
Status.Tick(Time.deltaTime);
|
||||||
|
|
||||||
|
// Apply Status logic
|
||||||
|
rb.useGravity = !Status.CurrentCapabilities.CanHover;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FixedUpdate()
|
private void FixedUpdate()
|
||||||
@@ -79,7 +82,7 @@ namespace Infrastructure.Unity
|
|||||||
var snapAxis = Vector3.zero;
|
var snapAxis = Vector3.zero;
|
||||||
|
|
||||||
Vector3 desiredDirection;
|
Vector3 desiredDirection;
|
||||||
|
|
||||||
if (_moveInput.sqrMagnitude < 0.01f)
|
if (_moveInput.sqrMagnitude < 0.01f)
|
||||||
{
|
{
|
||||||
desiredDirection = Vector3.zero;
|
desiredDirection = Vector3.zero;
|
||||||
@@ -100,7 +103,7 @@ namespace Infrastructure.Unity
|
|||||||
desiredDirection = new Vector3(_moveInput.x, 0, _moveInput.y).normalized;
|
desiredDirection = new Vector3(_moveInput.x, 0, _moveInput.y).normalized;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (desiredDirection.sqrMagnitude > 0.01f)
|
if (desiredDirection.sqrMagnitude > 0.01f)
|
||||||
{
|
{
|
||||||
if (Mathf.Abs(desiredDirection.x) > Mathf.Abs(desiredDirection.z))
|
if (Mathf.Abs(desiredDirection.x) > Mathf.Abs(desiredDirection.z))
|
||||||
@@ -117,11 +120,11 @@ namespace Infrastructure.Unity
|
|||||||
|
|
||||||
var velocity = rb.linearVelocity;
|
var velocity = rb.linearVelocity;
|
||||||
var velocityChange = (targetVelocity - velocity);
|
var velocityChange = (targetVelocity - velocity);
|
||||||
|
|
||||||
velocityChange.x = Mathf.Clamp(velocityChange.x, -maxVelocityChange, maxVelocityChange);
|
velocityChange.x = Mathf.Clamp(velocityChange.x, -maxVelocityChange, maxVelocityChange);
|
||||||
velocityChange.z = Mathf.Clamp(velocityChange.z, -maxVelocityChange, maxVelocityChange);
|
velocityChange.z = Mathf.Clamp(velocityChange.z, -maxVelocityChange, maxVelocityChange);
|
||||||
velocityChange.y = 0f;
|
velocityChange.y = 0f;
|
||||||
|
|
||||||
rb.AddForce(velocityChange, ForceMode.VelocityChange);
|
rb.AddForce(velocityChange, ForceMode.VelocityChange);
|
||||||
|
|
||||||
if (snapAxis != Vector3.zero)
|
if (snapAxis != Vector3.zero)
|
||||||
@@ -134,14 +137,14 @@ namespace Infrastructure.Unity
|
|||||||
ApplySnapping(Vector3.forward);
|
ApplySnapping(Vector3.forward);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ApplySnapping(Vector3 axis)
|
private void ApplySnapping(Vector3 axis)
|
||||||
{
|
{
|
||||||
var currentPos = Vector3.Dot(transform.position, axis);
|
var currentPos = Vector3.Dot(transform.position, axis);
|
||||||
var targetPos = Mathf.Round(currentPos);
|
var targetPos = Mathf.Round(currentPos);
|
||||||
|
|
||||||
var diff = targetPos - currentPos;
|
var diff = targetPos - currentPos;
|
||||||
|
|
||||||
var correction = axis * (diff * snapForce);
|
var correction = axis * (diff * snapForce);
|
||||||
rb.AddForce(correction, ForceMode.Acceleration);
|
rb.AddForce(correction, ForceMode.Acceleration);
|
||||||
}
|
}
|
||||||
@@ -149,7 +152,7 @@ namespace Infrastructure.Unity
|
|||||||
private void DetectGround()
|
private void DetectGround()
|
||||||
{
|
{
|
||||||
if (!Status.CurrentCapabilities.CanTriggerDecay) return;
|
if (!Status.CurrentCapabilities.CanTriggerDecay) return;
|
||||||
|
|
||||||
if (Physics.Raycast(transform.position, Vector3.down, out var hit, groundCheckDistance, tileLayer))
|
if (Physics.Raycast(transform.position, Vector3.down, out var hit, groundCheckDistance, tileLayer))
|
||||||
{
|
{
|
||||||
if (hit.collider.TryGetComponent<TileViewAdapter>(out var tileAdapter))
|
if (hit.collider.TryGetComponent<TileViewAdapter>(out var tileAdapter))
|
||||||
|
|||||||
@@ -11,12 +11,14 @@ namespace Infrastructure.Unity
|
|||||||
[SerializeField] private PowerUpType type;
|
[SerializeField] private PowerUpType type;
|
||||||
[SerializeField] private float duration = 10f;
|
[SerializeField] private float duration = 10f;
|
||||||
[SerializeField] private ParticleSystem pickupVfx;
|
[SerializeField] private ParticleSystem pickupVfx;
|
||||||
|
|
||||||
[Self] [SerializeField] private MeshRenderer meshRenderer;
|
[Self][SerializeField] private MeshRenderer meshRenderer;
|
||||||
|
|
||||||
private MaterialPropertyBlock _propBlock;
|
private MaterialPropertyBlock _propBlock;
|
||||||
private static readonly int ColorProperty = Shader.PropertyToID("_BaseColor");
|
private static readonly int ColorProperty = Shader.PropertyToID("_BaseColor");
|
||||||
|
|
||||||
|
public event Action<PowerUpType> OnCollected;
|
||||||
|
|
||||||
private void Awake()
|
private void Awake()
|
||||||
{
|
{
|
||||||
_propBlock = new MaterialPropertyBlock();
|
_propBlock = new MaterialPropertyBlock();
|
||||||
@@ -33,6 +35,12 @@ namespace Infrastructure.Unity
|
|||||||
case PowerUpType.SpeedBoost:
|
case PowerUpType.SpeedBoost:
|
||||||
SetColor(EffectColors.SpeedBoostColor);
|
SetColor(EffectColors.SpeedBoostColor);
|
||||||
break;
|
break;
|
||||||
|
case PowerUpType.Hover:
|
||||||
|
SetColor(EffectColors.HoverColor);
|
||||||
|
break;
|
||||||
|
case PowerUpType.TimeSlow:
|
||||||
|
SetColor(EffectColors.TimeSlowColor);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new ArgumentOutOfRangeException();
|
throw new ArgumentOutOfRangeException();
|
||||||
}
|
}
|
||||||
@@ -43,13 +51,14 @@ namespace Infrastructure.Unity
|
|||||||
if (other.TryGetComponent<PlayerController>(out var player))
|
if (other.TryGetComponent<PlayerController>(out var player))
|
||||||
{
|
{
|
||||||
ApplyEffect(player);
|
ApplyEffect(player);
|
||||||
|
OnCollected?.Invoke(type);
|
||||||
|
|
||||||
if (pickupVfx)
|
if (pickupVfx)
|
||||||
{
|
{
|
||||||
var vfx = Instantiate(pickupVfx, transform.position, Quaternion.identity);
|
var vfx = Instantiate(pickupVfx, transform.position, Quaternion.identity);
|
||||||
Destroy(vfx.gameObject, 2f);
|
Destroy(vfx.gameObject, 2f);
|
||||||
}
|
}
|
||||||
|
|
||||||
Destroy(gameObject);
|
Destroy(gameObject);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,6 +73,12 @@ namespace Infrastructure.Unity
|
|||||||
case PowerUpType.SpeedBoost:
|
case PowerUpType.SpeedBoost:
|
||||||
player.Status.AddEffect(new SpeedBoostEffect(duration, 1.5f));
|
player.Status.AddEffect(new SpeedBoostEffect(duration, 1.5f));
|
||||||
break;
|
break;
|
||||||
|
case PowerUpType.Hover:
|
||||||
|
player.Status.AddEffect(new HoverEffect(duration));
|
||||||
|
break;
|
||||||
|
case PowerUpType.TimeSlow:
|
||||||
|
// Handled globally
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new ArgumentOutOfRangeException();
|
throw new ArgumentOutOfRangeException();
|
||||||
}
|
}
|
||||||
@@ -72,6 +87,7 @@ namespace Infrastructure.Unity
|
|||||||
public void Configure(PowerUpType newType)
|
public void Configure(PowerUpType newType)
|
||||||
{
|
{
|
||||||
type = newType;
|
type = newType;
|
||||||
|
ConfigureVisuals();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetColor(Color color)
|
private void SetColor(Color color)
|
||||||
|
|||||||
60
Assets/Scripts/Infrastructure/Unity/TeleporterAdapter.cs
Normal file
60
Assets/Scripts/Infrastructure/Unity/TeleporterAdapter.cs
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Infrastructure.Unity
|
||||||
|
{
|
||||||
|
public class TeleporterAdapter : MonoBehaviour
|
||||||
|
{
|
||||||
|
private Transform _targetDestination;
|
||||||
|
private TeleporterAdapter _targetAdapter;
|
||||||
|
private float _cooldownTimer;
|
||||||
|
|
||||||
|
public void Initialize(Transform target)
|
||||||
|
{
|
||||||
|
_targetDestination = target;
|
||||||
|
_targetAdapter = target.GetComponent<TeleporterAdapter>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Update()
|
||||||
|
{
|
||||||
|
if (_cooldownTimer > 0f)
|
||||||
|
{
|
||||||
|
_cooldownTimer -= Time.deltaTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Lock(float duration)
|
||||||
|
{
|
||||||
|
_cooldownTimer = duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnTriggerEnter(Collider other)
|
||||||
|
{
|
||||||
|
if (!_targetDestination) return;
|
||||||
|
if (_cooldownTimer > 0f) return;
|
||||||
|
|
||||||
|
if (other.TryGetComponent<PlayerController>(out var player))
|
||||||
|
{
|
||||||
|
var dest = _targetDestination.position;
|
||||||
|
player.transform.position = dest + Vector3.up * 1.0f;
|
||||||
|
player.Rigidbody.linearVelocity = Vector3.zero;
|
||||||
|
|
||||||
|
if (_targetAdapter)
|
||||||
|
{
|
||||||
|
_targetAdapter.Lock(1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
Lock(1.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDrawGizmos()
|
||||||
|
{
|
||||||
|
if (_targetDestination)
|
||||||
|
{
|
||||||
|
Gizmos.color = Color.magenta;
|
||||||
|
Gizmos.DrawLine(transform.position, _targetDestination.position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 82fa71545d10e6ee187b00ae7fba2eea
|
||||||
41
Assets/Scripts/Infrastructure/Unity/ThemeManager.cs
Normal file
41
Assets/Scripts/Infrastructure/Unity/ThemeManager.cs
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Infrastructure.Unity
|
||||||
|
{
|
||||||
|
public static class ThemeManager
|
||||||
|
{
|
||||||
|
public struct ThemePalette
|
||||||
|
{
|
||||||
|
public Color StableColor;
|
||||||
|
public Color WarningColor;
|
||||||
|
public Color BackgroundColor; // Not used yet but good to have
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ThemePalette CurrentTheme { get; set; } = DefaultTheme;
|
||||||
|
|
||||||
|
public static ThemePalette DefaultTheme => new ThemePalette
|
||||||
|
{
|
||||||
|
StableColor = new Color(0.2f, 0.2f, 0.2f),
|
||||||
|
WarningColor = new Color(1f, 0.2f, 0.2f)
|
||||||
|
};
|
||||||
|
|
||||||
|
public static ThemePalette CyberpunkTheme => new ThemePalette
|
||||||
|
{
|
||||||
|
StableColor = new Color(0.1f, 0.1f, 0.3f), // Dark Blue
|
||||||
|
WarningColor = new Color(1f, 0f, 1f) // Neon Magenta
|
||||||
|
};
|
||||||
|
|
||||||
|
public static ThemePalette GoldenTheme => new ThemePalette
|
||||||
|
{
|
||||||
|
StableColor = new Color(0.3f, 0.3f, 0.1f), // Dark Gold
|
||||||
|
WarningColor = new Color(1f, 0.8f, 0f) // Gold
|
||||||
|
};
|
||||||
|
|
||||||
|
public static ThemePalette GetTheme(int highScore)
|
||||||
|
{
|
||||||
|
if (highScore >= 500) return GoldenTheme;
|
||||||
|
if (highScore >= 100) return CyberpunkTheme;
|
||||||
|
return DefaultTheme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
2
Assets/Scripts/Infrastructure/Unity/ThemeManager.cs.meta
Normal file
2
Assets/Scripts/Infrastructure/Unity/ThemeManager.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: cef34765e5cfa88c1b6e9d72e6c4fdc9
|
||||||
36
Assets/Scripts/Infrastructure/Unity/TilePool.cs
Normal file
36
Assets/Scripts/Infrastructure/Unity/TilePool.cs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Infrastructure.Unity
|
||||||
|
{
|
||||||
|
public class TilePool
|
||||||
|
{
|
||||||
|
private readonly TileViewAdapter _prefab;
|
||||||
|
private readonly Transform _parent;
|
||||||
|
private readonly Stack<TileViewAdapter> _pool = new();
|
||||||
|
|
||||||
|
public TilePool(TileViewAdapter prefab, Transform parent)
|
||||||
|
{
|
||||||
|
_prefab = prefab;
|
||||||
|
_parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TileViewAdapter Get()
|
||||||
|
{
|
||||||
|
if (_pool.Count > 0)
|
||||||
|
{
|
||||||
|
var item = _pool.Pop();
|
||||||
|
item.gameObject.SetActive(true);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Object.Instantiate(_prefab, _parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Return(TileViewAdapter item)
|
||||||
|
{
|
||||||
|
item.gameObject.SetActive(false);
|
||||||
|
_pool.Push(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
2
Assets/Scripts/Infrastructure/Unity/TilePool.cs.meta
Normal file
2
Assets/Scripts/Infrastructure/Unity/TilePool.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 64b83ab6062e454f5b8765c1d2bfc8a7
|
||||||
@@ -4,7 +4,6 @@ using Core.Domain;
|
|||||||
using Core.Ports;
|
using Core.Ports;
|
||||||
using KBCore.Refs;
|
using KBCore.Refs;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using Random = UnityEngine.Random;
|
|
||||||
|
|
||||||
namespace Infrastructure.Unity
|
namespace Infrastructure.Unity
|
||||||
{
|
{
|
||||||
@@ -12,38 +11,58 @@ namespace Infrastructure.Unity
|
|||||||
public class TileViewAdapter : MonoBehaviour, ITileView
|
public class TileViewAdapter : MonoBehaviour, ITileView
|
||||||
{
|
{
|
||||||
private Tile _linkedTile;
|
private Tile _linkedTile;
|
||||||
|
|
||||||
public string TileId { get; private set; }
|
public string TileId { get; private set; }
|
||||||
|
|
||||||
[Header("Visuals Settings")]
|
[Header("Visuals Settings")]
|
||||||
[SerializeField] private Color stableColor = new Color(0.2f, 0.2f, 0.2f); // Dark Grey
|
[SerializeField] private Color stableColor = new Color(0.2f, 0.2f, 0.2f); // Dark Grey
|
||||||
[SerializeField] private Color warningColor = new Color(1f, 0.2f, 0.2f); // Neon Red
|
[SerializeField] private Color warningColor = new Color(1f, 0.2f, 0.2f); // Neon Red
|
||||||
|
[SerializeField] private Color fragileColor = new Color(0.6f, 0.8f, 1f, 0.5f); // Cyan/Glass
|
||||||
[SerializeField] private float colorSpeed = 2f;
|
[SerializeField] private float colorSpeed = 2f;
|
||||||
|
|
||||||
[Self] [SerializeField] private Rigidbody rb;
|
[Self][SerializeField] private Rigidbody rb;
|
||||||
[Self] [SerializeField] private MeshRenderer meshRenderer;
|
[Self][SerializeField] private MeshRenderer meshRenderer;
|
||||||
|
|
||||||
public Rigidbody Rigidbody => rb;
|
public Rigidbody Rigidbody => rb;
|
||||||
public MeshRenderer MeshRenderer => meshRenderer;
|
public MeshRenderer MeshRenderer => meshRenderer;
|
||||||
|
|
||||||
private MaterialPropertyBlock _propBlock;
|
private MaterialPropertyBlock _propBlock;
|
||||||
private static readonly int ColorProperty = Shader.PropertyToID("_BaseColor");
|
private static readonly int ColorProperty = Shader.PropertyToID("_BaseColor");
|
||||||
|
|
||||||
|
private Action<TileViewAdapter> _onReturnToPool;
|
||||||
|
|
||||||
private void Awake()
|
private void Awake()
|
||||||
{
|
{
|
||||||
_propBlock = new MaterialPropertyBlock();
|
_propBlock = new MaterialPropertyBlock();
|
||||||
|
|
||||||
rb.isKinematic = true;
|
rb.isKinematic = true;
|
||||||
rb.useGravity = false;
|
rb.useGravity = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Initialize(Tile tile)
|
public void Initialize(Tile tile)
|
||||||
|
{
|
||||||
|
Initialize(tile, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Initialize(Tile tile, Action<TileViewAdapter> onReturnToPool = null)
|
||||||
{
|
{
|
||||||
_linkedTile = tile;
|
_linkedTile = tile;
|
||||||
TileId = tile.Id;
|
TileId = tile.Id;
|
||||||
|
_onReturnToPool = onReturnToPool;
|
||||||
SetColor(stableColor);
|
|
||||||
|
// Reset physics
|
||||||
|
rb.isKinematic = true;
|
||||||
|
rb.useGravity = false;
|
||||||
|
|
||||||
|
if (_linkedTile.Type == TileType.Fragile)
|
||||||
|
{
|
||||||
|
SetColor(fragileColor);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetColor(ThemeManager.CurrentTheme.StableColor);
|
||||||
|
}
|
||||||
|
|
||||||
_linkedTile.OnStateChanged += OnTileStateChanged;
|
_linkedTile.OnStateChanged += OnTileStateChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,18 +76,16 @@ namespace Infrastructure.Unity
|
|||||||
switch (state)
|
switch (state)
|
||||||
{
|
{
|
||||||
case TileState.Stable:
|
case TileState.Stable:
|
||||||
StartCoroutine(AnimateColor(stableColor));
|
StartCoroutine(AnimateColor(ThemeManager.CurrentTheme.StableColor));
|
||||||
break;
|
break;
|
||||||
case TileState.Warning:
|
case TileState.Warning:
|
||||||
StartCoroutine(AnimateColor(warningColor));
|
StartCoroutine(AnimateColor(ThemeManager.CurrentTheme.WarningColor));
|
||||||
break;
|
break;
|
||||||
case TileState.Falling:
|
case TileState.Falling:
|
||||||
DropPhysics();
|
DropPhysics();
|
||||||
// Optionally change material or add effects for falling state
|
|
||||||
break;
|
break;
|
||||||
case TileState.Destroyed:
|
case TileState.Destroyed:
|
||||||
Dispose();
|
Dispose();
|
||||||
// Optionally change material or add effects for destroyed state
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new ArgumentOutOfRangeException(nameof(state), state, null);
|
throw new ArgumentOutOfRangeException(nameof(state), state, null);
|
||||||
@@ -79,8 +96,6 @@ namespace Infrastructure.Unity
|
|||||||
{
|
{
|
||||||
rb.isKinematic = false;
|
rb.isKinematic = false;
|
||||||
rb.useGravity = true;
|
rb.useGravity = true;
|
||||||
|
|
||||||
// rb.AddTorque(Random.insideUnitSphere * 5f, ForceMode.Impulse);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
@@ -124,8 +139,15 @@ namespace Infrastructure.Unity
|
|||||||
transform.localScale = Vector3.Lerp(startScale, Vector3.zero, t);
|
transform.localScale = Vector3.Lerp(startScale, Vector3.zero, t);
|
||||||
yield return null;
|
yield return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Destroy(gameObject);
|
if (_onReturnToPool != null)
|
||||||
|
{
|
||||||
|
_onReturnToPool(this);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Destroy(gameObject);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDestroy()
|
private void OnDestroy()
|
||||||
|
|||||||
Reference in New Issue
Block a user