From ee7a2fb4cbb3e2ca36e71e2b6c74c5739b3342bf Mon Sep 17 00:00:00 2001 From: Gabriel Kaszewski Date: Fri, 12 Dec 2025 23:05:40 +0100 Subject: [PATCH] Add NPC and Power-Up features with associated prefabs and effects --- Assets/Materials/Npc.mat | 138 +++++++++++++++ Assets/Materials/Npc.mat.meta | 8 + Assets/Materials/PowerUp.mat | 48 ++++++ Assets/Materials/PowerUp.mat.meta | 8 + Assets/Prefabs/Light footed.prefab | 133 ++++++++++++++ Assets/Prefabs/Light footed.prefab.meta | 7 + Assets/Prefabs/Npc.prefab | 163 ++++++++++++++++++ Assets/Prefabs/Npc.prefab.meta | 7 + Assets/Prefabs/Speed Boost.prefab | 133 ++++++++++++++ Assets/Prefabs/Speed Boost.prefab.meta | 7 + Assets/Scenes/SampleScene.unity | 104 ++++++++++- Assets/Scripts/Core/Domain/GameSession.cs | 42 +++++ Assets/Scripts/Core/Domain/PowerUpType.cs | 8 + .../Scripts/Core/Domain/PowerUpType.cs.meta | 3 + .../Domain/Status/Effects/EffectColors.cs | 10 ++ .../Status/Effects/EffectColors.cs.meta | 3 + .../Domain/Status/Effects/SpeedBoostEffect.cs | 29 ++++ .../Status/Effects/SpeedBoostEffect.cs.meta | 3 + .../Infrastructure/Unity/GameBootstrap.cs | 38 +++- .../Infrastructure/Unity/NpcController.cs | 66 +++++++ .../Unity/NpcController.cs.meta | 3 + .../Unity/PowerUpViewAdapter.cs | 84 +++++++++ .../Unity/PowerUpViewAdapter.cs.meta | 3 + .../Infrastructure/Unity/SoundManager.cs | 8 +- 24 files changed, 1051 insertions(+), 5 deletions(-) create mode 100644 Assets/Materials/Npc.mat create mode 100644 Assets/Materials/Npc.mat.meta create mode 100644 Assets/Materials/PowerUp.mat create mode 100644 Assets/Materials/PowerUp.mat.meta create mode 100644 Assets/Prefabs/Light footed.prefab create mode 100644 Assets/Prefabs/Light footed.prefab.meta create mode 100644 Assets/Prefabs/Npc.prefab create mode 100644 Assets/Prefabs/Npc.prefab.meta create mode 100644 Assets/Prefabs/Speed Boost.prefab create mode 100644 Assets/Prefabs/Speed Boost.prefab.meta create mode 100644 Assets/Scripts/Core/Domain/PowerUpType.cs create mode 100644 Assets/Scripts/Core/Domain/PowerUpType.cs.meta create mode 100644 Assets/Scripts/Core/Domain/Status/Effects/EffectColors.cs create mode 100644 Assets/Scripts/Core/Domain/Status/Effects/EffectColors.cs.meta create mode 100644 Assets/Scripts/Core/Domain/Status/Effects/SpeedBoostEffect.cs create mode 100644 Assets/Scripts/Core/Domain/Status/Effects/SpeedBoostEffect.cs.meta create mode 100644 Assets/Scripts/Infrastructure/Unity/NpcController.cs create mode 100644 Assets/Scripts/Infrastructure/Unity/NpcController.cs.meta create mode 100644 Assets/Scripts/Infrastructure/Unity/PowerUpViewAdapter.cs create mode 100644 Assets/Scripts/Infrastructure/Unity/PowerUpViewAdapter.cs.meta diff --git a/Assets/Materials/Npc.mat b/Assets/Materials/Npc.mat new file mode 100644 index 0000000..d543657 --- /dev/null +++ b/Assets/Materials/Npc.mat @@ -0,0 +1,138 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Npc + m_Shader: {fileID: 4800000, guid: 933532a4fcc9baf4fa0491de14d08ed7, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: + - _EMISSION + m_InvalidKeywords: [] + m_LightmapFlags: 6 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: + RenderType: Opaque + disabledShaderPasses: + - MOTIONVECTORS + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BaseMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _SpecGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_Lightmaps: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_LightmapsInd: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_ShadowMasks: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _AddPrecomputedVelocity: 0 + - _AlphaClip: 0 + - _AlphaToMask: 0 + - _Blend: 0 + - _BlendModePreserveSpecular: 1 + - _BumpScale: 1 + - _ClearCoatMask: 0 + - _ClearCoatSmoothness: 0 + - _Cull: 2 + - _Cutoff: 0.5 + - _DetailAlbedoMapScale: 1 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _DstBlendAlpha: 0 + - _EnvironmentReflections: 1 + - _GlossMapScale: 0 + - _Glossiness: 0 + - _GlossyReflections: 0 + - _Metallic: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.005 + - _QueueOffset: 0 + - _ReceiveShadows: 1 + - _Smoothness: 0.5 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _SrcBlendAlpha: 1 + - _Surface: 0 + - _WorkflowMode: 1 + - _XRMotionVectorsPass: 1 + - _ZWrite: 1 + m_Colors: + - _BaseColor: {r: 1, g: 0.18039216, b: 0.3882353, a: 1} + - _Color: {r: 1, g: 0.18039212, b: 0.38823527, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + - _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1} + m_BuildTextureStacks: [] + m_AllowLocking: 1 +--- !u!114 &69646477803621672 +MonoBehaviour: + m_ObjectHideFlags: 11 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} + m_Name: + m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Editor::UnityEditor.Rendering.Universal.AssetVersion + version: 10 diff --git a/Assets/Materials/Npc.mat.meta b/Assets/Materials/Npc.mat.meta new file mode 100644 index 0000000..85f2900 --- /dev/null +++ b/Assets/Materials/Npc.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a64e346b67480caceae337f37543db27 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Materials/PowerUp.mat b/Assets/Materials/PowerUp.mat new file mode 100644 index 0000000..f3651d3 --- /dev/null +++ b/Assets/Materials/PowerUp.mat @@ -0,0 +1,48 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &-8433387689984454123 +MonoBehaviour: + m_ObjectHideFlags: 11 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} + m_Name: + m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Editor::UnityEditor.Rendering.Universal.AssetVersion + version: 10 +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: PowerUp + m_Shader: {fileID: 4800000, guid: 933532a4fcc9baf4fa0491de14d08ed7, type: 3} + m_Parent: {fileID: 2100000, guid: 6f050d9117f771bbbab3e6f1eead9d67, type: 2} + m_ModifiedSerializedProperties: 2 + m_ValidKeywords: + - _EMISSION + m_InvalidKeywords: [] + m_LightmapFlags: 6 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: + RenderType: Opaque + disabledShaderPasses: + - MOTIONVECTORS + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: [] + m_Ints: [] + m_Floats: [] + m_Colors: + - _BaseColor: {r: 1, g: 1, b: 1, a: 1} + - _Color: {r: 1, g: 1, b: 1, a: 1} + m_BuildTextureStacks: [] + m_AllowLocking: 1 diff --git a/Assets/Materials/PowerUp.mat.meta b/Assets/Materials/PowerUp.mat.meta new file mode 100644 index 0000000..91e06bc --- /dev/null +++ b/Assets/Materials/PowerUp.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: aece89a4ea685f6969a31191b980f70b +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Prefabs/Light footed.prefab b/Assets/Prefabs/Light footed.prefab new file mode 100644 index 0000000..b504a4c --- /dev/null +++ b/Assets/Prefabs/Light footed.prefab @@ -0,0 +1,133 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &7219310182397398916 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4070461624121405295} + - component: {fileID: 930667067315408562} + - component: {fileID: 2173926958931993968} + - component: {fileID: 5033597944775254142} + - component: {fileID: 2639250404559520579} + m_Layer: 0 + m_Name: Light footed + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4070461624121405295 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7219310182397398916} + serializedVersion: 2 + 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: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &930667067315408562 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7219310182397398916} + m_Mesh: {fileID: 10208, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &2173926958931993968 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7219310182397398916} + 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: aece89a4ea685f6969a31191b980f70b, 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 &5033597944775254142 +CapsuleCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7219310182397398916} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 1 + 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!114 &2639250404559520579 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7219310182397398916} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5886e2d0e6414ce98bf68f8e5ac887fc, type: 3} + m_Name: + m_EditorClassIdentifier: Assembly-CSharp::Infrastructure.Unity.PowerUpViewAdapter + type: 0 + duration: 10 + pickupVfx: {fileID: 0} + meshRenderer: {fileID: 2173926958931993968} diff --git a/Assets/Prefabs/Light footed.prefab.meta b/Assets/Prefabs/Light footed.prefab.meta new file mode 100644 index 0000000..9355ff9 --- /dev/null +++ b/Assets/Prefabs/Light footed.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 4ce47d492ed71cb5b9390762eab7a749 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Prefabs/Npc.prefab b/Assets/Prefabs/Npc.prefab new file mode 100644 index 0000000..dbfd2ed --- /dev/null +++ b/Assets/Prefabs/Npc.prefab @@ -0,0 +1,163 @@ +%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: 6083523108754401876} + m_Layer: 0 + m_Name: Npc + 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 &6083523108754401876 +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: d8629598f36246c484f046e5ebd69266, type: 3} + m_Name: + m_EditorClassIdentifier: Assembly-CSharp::Infrastructure.Unity.NpcController + moveSpeed: 6 + changeDirInterval: 1 + tileLayer: + serializedVersion: 2 + m_Bits: 8 + rb: {fileID: 283610869708690177} diff --git a/Assets/Prefabs/Npc.prefab.meta b/Assets/Prefabs/Npc.prefab.meta new file mode 100644 index 0000000..1313b6c --- /dev/null +++ b/Assets/Prefabs/Npc.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 4b3d84858334857368bde30df360ae3e +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Prefabs/Speed Boost.prefab b/Assets/Prefabs/Speed Boost.prefab new file mode 100644 index 0000000..ef1c7e3 --- /dev/null +++ b/Assets/Prefabs/Speed Boost.prefab @@ -0,0 +1,133 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &7219310182397398916 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4070461624121405295} + - component: {fileID: 930667067315408562} + - component: {fileID: 2173926958931993968} + - component: {fileID: 5033597944775254142} + - component: {fileID: 2639250404559520579} + m_Layer: 0 + m_Name: Speed Boost + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4070461624121405295 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7219310182397398916} + serializedVersion: 2 + 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: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &930667067315408562 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7219310182397398916} + m_Mesh: {fileID: 10208, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &2173926958931993968 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7219310182397398916} + 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: aece89a4ea685f6969a31191b980f70b, 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 &5033597944775254142 +CapsuleCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7219310182397398916} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 1 + 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!114 &2639250404559520579 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7219310182397398916} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5886e2d0e6414ce98bf68f8e5ac887fc, type: 3} + m_Name: + m_EditorClassIdentifier: Assembly-CSharp::Infrastructure.Unity.PowerUpViewAdapter + type: 1 + duration: 10 + pickupVfx: {fileID: 0} + meshRenderer: {fileID: 2173926958931993968} diff --git a/Assets/Prefabs/Speed Boost.prefab.meta b/Assets/Prefabs/Speed Boost.prefab.meta new file mode 100644 index 0000000..634b6c4 --- /dev/null +++ b/Assets/Prefabs/Speed Boost.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 32d69de3e08c76e63a4b5086b87b12df +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes/SampleScene.unity b/Assets/Scenes/SampleScene.unity index 1fa6bfb..bae6e40 100644 --- a/Assets/Scenes/SampleScene.unity +++ b/Assets/Scenes/SampleScene.unity @@ -632,6 +632,7 @@ MonoBehaviour: deathPlanePrefab: {fileID: 6985639713120889316, guid: b25f4148dc4e46617b9f0cb6403de754, type: 3} soundManager: {fileID: 1341134052} cameraController: {fileID: 1265730430} + npcPrefab: {fileID: 6083523108754401876, guid: 4b3d84858334857368bde30df360ae3e, type: 3} floorsCount: 3 floorHeightDistance: 15 scoreText: {fileID: 412275999} @@ -639,6 +640,8 @@ MonoBehaviour: gameOverUi: {fileID: 87831902} startScreenUi: {fileID: 1763855010} restartTime: 3 + lightFootedPrefab: {fileID: 2639250404559520579, guid: 4ce47d492ed71cb5b9390762eab7a749, type: 3} + speedBoostPrefab: {fileID: 2639250404559520579, guid: 32d69de3e08c76e63a4b5086b87b12df, type: 3} --- !u!4 &453022421 Transform: m_ObjectHideFlags: 0 @@ -882,6 +885,7 @@ GameObject: m_Component: - component: {fileID: 1341134054} - component: {fileID: 1341134053} + - component: {fileID: 1341134055} - component: {fileID: 1341134052} m_Layer: 0 m_Name: Audio System @@ -908,8 +912,9 @@ MonoBehaviour: gameOverClip: {fileID: 0} tileWarningClip: {fileID: 0} tileBreakClip: {fileID: 0} + npcSpawnClip: {fileID: 0} musicSource: {fileID: 1341134053} - sfxSource: {fileID: 1341134053} + sfxSource: {fileID: 1341134055} --- !u!82 &1341134053 AudioSource: m_ObjectHideFlags: 0 @@ -1022,6 +1027,103 @@ Transform: m_Children: [] m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!82 &1341134055 +AudioSource: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1341134051} + m_Enabled: 1 + serializedVersion: 4 + OutputAudioMixerGroup: {fileID: 0} + m_audioClip: {fileID: 0} + m_Resource: {fileID: 0} + m_PlayOnAwake: 1 + m_Volume: 1 + m_Pitch: 1 + Loop: 0 + Mute: 0 + Spatialize: 0 + SpatializePostEffects: 0 + Priority: 128 + DopplerLevel: 1 + MinDistance: 1 + MaxDistance: 500 + Pan2D: 0 + rolloffMode: 0 + BypassEffects: 0 + BypassListenerEffects: 0 + BypassReverbZones: 0 + rolloffCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + panLevelCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + spreadCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + reverbZoneMixCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 --- !u!1 &1454679069 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/Scripts/Core/Domain/GameSession.cs b/Assets/Scripts/Core/Domain/GameSession.cs index 71f8f5b..44f867e 100644 --- a/Assets/Scripts/Core/Domain/GameSession.cs +++ b/Assets/Scripts/Core/Domain/GameSession.cs @@ -7,6 +7,8 @@ namespace Core.Domain public class GameSession { private const string HighScoreKey = "HighScore"; + private const float NpcSpawnTime = 4f; + private const float PowerUpSpawnInterval = 25f; public int Score { get; private set; } public int HighScore { get; private set; } @@ -16,11 +18,16 @@ namespace Core.Domain public event Action OnOrbSpawned; public event Action OnOrbReset; public event Action OnGameOver; + public event Action OnSpawnNpc; + public event Action OnSpawnPowerUp; private readonly List _tiles; private readonly IPersistenceService _persistenceService; private readonly Random _rng = new(); private int _playerFloorIndex = 0; + private float _timeSinceStart; + private bool _npcSpawned; + private float _powerUpTimer; public GameSession(List tiles, IPersistenceService persistenceService) { @@ -35,9 +42,32 @@ namespace Core.Domain public void StartGame() { + _timeSinceStart = 0f; + _powerUpTimer = 0f; + _npcSpawned = false; + SpawnNextOrb(); } + public void Tick(float deltaTime) + { + if (IsGameOver) return; + + _timeSinceStart += deltaTime; + if (!_npcSpawned && _timeSinceStart >= NpcSpawnTime) + { + _npcSpawned = true; + OnSpawnNpc?.Invoke(); + } + + _powerUpTimer += deltaTime; + if (_powerUpTimer >= PowerUpSpawnInterval) + { + _powerUpTimer = 0f; + SpawnRandomPowerUp(); + } + } + public void OrbCollected() { if (IsGameOver) return; @@ -95,5 +125,17 @@ namespace Core.Domain OnOrbReset?.Invoke(); SpawnNextOrb(); } + + private void SpawnRandomPowerUp() + { + var validTiles = _tiles.FindAll(t => t.CurrentState == TileState.Stable); + if (validTiles.Count == 0) return; + + var tile = validTiles[_rng.Next(validTiles.Count)]; + + var type = _rng.Next(0, 2) == 0 ? PowerUpType.LightFooted : PowerUpType.SpeedBoost; + + OnSpawnPowerUp?.Invoke(type, tile.Id); + } } } \ No newline at end of file diff --git a/Assets/Scripts/Core/Domain/PowerUpType.cs b/Assets/Scripts/Core/Domain/PowerUpType.cs new file mode 100644 index 0000000..3fb3d08 --- /dev/null +++ b/Assets/Scripts/Core/Domain/PowerUpType.cs @@ -0,0 +1,8 @@ +namespace Core.Domain +{ + public enum PowerUpType + { + LightFooted, + SpeedBoost, + } +} \ No newline at end of file diff --git a/Assets/Scripts/Core/Domain/PowerUpType.cs.meta b/Assets/Scripts/Core/Domain/PowerUpType.cs.meta new file mode 100644 index 0000000..2595ea2 --- /dev/null +++ b/Assets/Scripts/Core/Domain/PowerUpType.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: bafe72a0931b403fbd668163287d60a3 +timeCreated: 1765576209 \ No newline at end of file diff --git a/Assets/Scripts/Core/Domain/Status/Effects/EffectColors.cs b/Assets/Scripts/Core/Domain/Status/Effects/EffectColors.cs new file mode 100644 index 0000000..74e2ea2 --- /dev/null +++ b/Assets/Scripts/Core/Domain/Status/Effects/EffectColors.cs @@ -0,0 +1,10 @@ +using UnityEngine; + +namespace Core.Domain.Status.Effects +{ + public struct EffectColors + { + public static readonly Color LightFootedColor = new Color(0.8f, 0.8f, 0.8f); + public static readonly Color SpeedBoostColor = new Color(1f, 0.5f, 0f); + } +} \ No newline at end of file diff --git a/Assets/Scripts/Core/Domain/Status/Effects/EffectColors.cs.meta b/Assets/Scripts/Core/Domain/Status/Effects/EffectColors.cs.meta new file mode 100644 index 0000000..d50356f --- /dev/null +++ b/Assets/Scripts/Core/Domain/Status/Effects/EffectColors.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ca5a45bf5f154f009511ace70bfc78aa +timeCreated: 1765576663 \ No newline at end of file diff --git a/Assets/Scripts/Core/Domain/Status/Effects/SpeedBoostEffect.cs b/Assets/Scripts/Core/Domain/Status/Effects/SpeedBoostEffect.cs new file mode 100644 index 0000000..ab54019 --- /dev/null +++ b/Assets/Scripts/Core/Domain/Status/Effects/SpeedBoostEffect.cs @@ -0,0 +1,29 @@ +namespace Core.Domain.Status.Effects +{ + public class SpeedBoostEffect : IStatusEffect + { + private float _duration; + private readonly float _multiplier; + + public bool IsExpired => _duration <= 0; + + public SpeedBoostEffect(float duration, float multiplier = 1.5f) + { + _duration = duration; + _multiplier = multiplier; + } + + public void Tick(float deltaTime) + { + _duration -= deltaTime; + } + + public void ModifyCapabilities(ref PlayerCapabilities caps) + { + caps.SpeedMultiplier = _multiplier; + } + + public void OnApply() { } + public void OnRemove() { } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Core/Domain/Status/Effects/SpeedBoostEffect.cs.meta b/Assets/Scripts/Core/Domain/Status/Effects/SpeedBoostEffect.cs.meta new file mode 100644 index 0000000..06b80ce --- /dev/null +++ b/Assets/Scripts/Core/Domain/Status/Effects/SpeedBoostEffect.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 8fdc1e67835247f6a2afc26cc4ed27a8 +timeCreated: 1765576232 \ No newline at end of file diff --git a/Assets/Scripts/Infrastructure/Unity/GameBootstrap.cs b/Assets/Scripts/Infrastructure/Unity/GameBootstrap.cs index 093adb3..616455f 100644 --- a/Assets/Scripts/Infrastructure/Unity/GameBootstrap.cs +++ b/Assets/Scripts/Infrastructure/Unity/GameBootstrap.cs @@ -17,6 +17,7 @@ namespace Infrastructure.Unity [SerializeField] private DeathPlaneAdapter deathPlanePrefab; [SerializeField] private SoundManager soundManager; [SerializeField] private CameraController cameraController; + [SerializeField] private NpcController npcPrefab; [Header("Level Generation")] [SerializeField] private int floorsCount = 3; @@ -30,7 +31,10 @@ namespace Infrastructure.Unity [Header("Settings")] [SerializeField] private float restartTime = 3f; - + + [Header("Power Ups")] + [SerializeField] private PowerUpViewAdapter lightFootedPrefab; + [SerializeField] private PowerUpViewAdapter speedBoostPrefab; private readonly List _allTiles = new(); private readonly Dictionary _tileViews = new(); @@ -93,6 +97,9 @@ namespace Infrastructure.Unity } var dt = Time.deltaTime; + + if (_isGameRunning) _gameSession.Tick(dt); + for (var i = _allTiles.Count - 1; i >= 0; i--) { _allTiles[i].Tick(dt); @@ -180,6 +187,8 @@ namespace Infrastructure.Unity _gameSession.OnOrbSpawned += SpawnVisualOrb; _gameSession.OnOrbReset += HandleOrbReset; _gameSession.OnGameOver += HandleGameOver; + _gameSession.OnSpawnNpc += SpawnNpc; + _gameSession.OnSpawnPowerUp += SpawnPowerUp; if (!soundManager) return; @@ -191,6 +200,16 @@ namespace Infrastructure.Unity }; } + private void SpawnNpc() + { + if (!npcPrefab) return; + + var spawnPos = new Vector3(levelGenerator.GridSizeX / 2f, 7f, levelGenerator.GridSizeY / 2f); + Instantiate(npcPrefab, spawnPos, Quaternion.identity); + + soundManager.PlayNpcSpawn(); + } + private void StartGameSequence() { _isGameRunning = true; @@ -211,5 +230,22 @@ namespace Infrastructure.Unity _gameSession.StartGame(); } + + private void SpawnPowerUp(PowerUpType type, string tileId) + { + if (!_tileViews.TryGetValue(tileId, out var tileView)) return; + if (!tileView) return; + + var spawnPos = tileView.transform.position + Vector3.up * 0.5f; + + var prefabToSpawn = type == PowerUpType.LightFooted + ? lightFootedPrefab + : speedBoostPrefab; + + if (!prefabToSpawn) return; + + var instance = Instantiate(prefabToSpawn, spawnPos, Quaternion.identity); + instance.Configure(type); + } } } \ No newline at end of file diff --git a/Assets/Scripts/Infrastructure/Unity/NpcController.cs b/Assets/Scripts/Infrastructure/Unity/NpcController.cs new file mode 100644 index 0000000..a98f04c --- /dev/null +++ b/Assets/Scripts/Infrastructure/Unity/NpcController.cs @@ -0,0 +1,66 @@ +using System; +using KBCore.Refs; +using UnityEngine; +using UnityEngine.AI; +using Random = UnityEngine.Random; + +namespace Infrastructure.Unity +{ + [RequireComponent(typeof(Rigidbody))] + public class NpcController : MonoBehaviour + { + [SerializeField] private float moveSpeed = 6f; + [SerializeField] private float changeDirInterval = 1f; + [SerializeField] private LayerMask tileLayer; + + [Self] [SerializeField] private Rigidbody rb; + + private Vector3 _currentDir; + private float _timer; + + private void Awake() + { + PickNewDirection(); + } + + private void Update() + { + _timer += Time.deltaTime; + if (_timer >= changeDirInterval) + { + _timer = 0; + PickNewDirection(); + } + } + + private void FixedUpdate() + { + if (IsGrounded()) rb.MovePosition(rb.position + _currentDir * (moveSpeed * Time.fixedDeltaTime)); + + if (Physics.Raycast(transform.position, Vector3.down, out var hit, 1.5f, tileLayer)) + { + if (hit.collider.TryGetComponent(out var tile)) + { + tile.OnPlayerStep(); + } + } + } + + private bool IsGrounded() + { + return Physics.Raycast(transform.position, Vector3.down, out var hit, 1.15f, tileLayer); + } + + private void PickNewDirection() + { + var rand = Random.Range(0, 4); + switch (rand) + { + case 0: _currentDir = Vector3.forward; break; + case 1: _currentDir = Vector3.back; break; + case 2: _currentDir = Vector3.left; break; + case 3: _currentDir = Vector3.right; break; + } + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Infrastructure/Unity/NpcController.cs.meta b/Assets/Scripts/Infrastructure/Unity/NpcController.cs.meta new file mode 100644 index 0000000..3c6d5b1 --- /dev/null +++ b/Assets/Scripts/Infrastructure/Unity/NpcController.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d8629598f36246c484f046e5ebd69266 +timeCreated: 1765575497 \ No newline at end of file diff --git a/Assets/Scripts/Infrastructure/Unity/PowerUpViewAdapter.cs b/Assets/Scripts/Infrastructure/Unity/PowerUpViewAdapter.cs new file mode 100644 index 0000000..4df2b15 --- /dev/null +++ b/Assets/Scripts/Infrastructure/Unity/PowerUpViewAdapter.cs @@ -0,0 +1,84 @@ +using System; +using Core.Domain; +using Core.Domain.Status.Effects; +using KBCore.Refs; +using UnityEngine; + +namespace Infrastructure.Unity +{ + public class PowerUpViewAdapter : MonoBehaviour + { + [SerializeField] private PowerUpType type; + [SerializeField] private float duration = 10f; + [SerializeField] private ParticleSystem pickupVfx; + + [Self] [SerializeField] private MeshRenderer meshRenderer; + + private MaterialPropertyBlock _propBlock; + private static readonly int ColorProperty = Shader.PropertyToID("_BaseColor"); + + private void Awake() + { + _propBlock = new MaterialPropertyBlock(); + ConfigureVisuals(); + } + + private void ConfigureVisuals() + { + switch (type) + { + case PowerUpType.LightFooted: + SetColor(EffectColors.LightFootedColor); + break; + case PowerUpType.SpeedBoost: + SetColor(EffectColors.SpeedBoostColor); + break; + default: + throw new ArgumentOutOfRangeException(); + } + } + + private void OnTriggerEnter(Collider other) + { + if (other.TryGetComponent(out var player)) + { + ApplyEffect(player); + + if (pickupVfx) + { + var vfx = Instantiate(pickupVfx, transform.position, Quaternion.identity); + Destroy(vfx.gameObject, 2f); + } + + Destroy(gameObject); + } + } + + private void ApplyEffect(PlayerController player) + { + switch (type) + { + case PowerUpType.LightFooted: + player.Status.AddEffect(new LightFootedEffect(duration)); + break; + case PowerUpType.SpeedBoost: + player.Status.AddEffect(new SpeedBoostEffect(duration, 1.5f)); + break; + default: + throw new ArgumentOutOfRangeException(); + } + } + + public void Configure(PowerUpType newType) + { + type = newType; + } + + private void SetColor(Color color) + { + meshRenderer.GetPropertyBlock(_propBlock); + _propBlock.SetColor(ColorProperty, color); + meshRenderer.SetPropertyBlock(_propBlock); + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Infrastructure/Unity/PowerUpViewAdapter.cs.meta b/Assets/Scripts/Infrastructure/Unity/PowerUpViewAdapter.cs.meta new file mode 100644 index 0000000..7dcd710 --- /dev/null +++ b/Assets/Scripts/Infrastructure/Unity/PowerUpViewAdapter.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5886e2d0e6414ce98bf68f8e5ac887fc +timeCreated: 1765576409 \ No newline at end of file diff --git a/Assets/Scripts/Infrastructure/Unity/SoundManager.cs b/Assets/Scripts/Infrastructure/Unity/SoundManager.cs index c4397ac..734812a 100644 --- a/Assets/Scripts/Infrastructure/Unity/SoundManager.cs +++ b/Assets/Scripts/Infrastructure/Unity/SoundManager.cs @@ -12,14 +12,14 @@ namespace Infrastructure.Unity [Header("Sound Effects")] [SerializeField] private AudioClip startClip; - [SerializeField] private AudioClip scoreClip; [SerializeField] private AudioClip gameOverClip; [SerializeField] private AudioClip tileWarningClip; [SerializeField] private AudioClip tileBreakClip; + [SerializeField] private AudioClip npcSpawnClip; - [Self] [SerializeField] private AudioSource musicSource; - [Self] [SerializeField] private AudioSource sfxSource; + [SerializeField] private AudioSource musicSource; + [SerializeField] private AudioSource sfxSource; private void Awake() { @@ -43,6 +43,8 @@ namespace Infrastructure.Unity public void PlayGameStart() => PlaySfx(startClip); public void PlayScore() => PlaySfx(scoreClip); public void PlayGameOver() => PlaySfx(gameOverClip); + + public void PlayNpcSpawn() => PlaySfx(npcSpawnClip); public void PlayTileBreak(Vector3 position) {