feat: Player

This commit is contained in:
2026-10-07 15:46:51 +02:00
parent 074eb51084
commit d21f0c9b6c
45 changed files with 1801 additions and 74 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7773c1d71eef8b3458b1f5d8870d968f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,20 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
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: b4a4852c6f394a441935fae7b9f9ec82, type: 3}
m_Name: WeaponData_Gun
m_EditorClassIdentifier: Assembly-CSharp::Arena.Combat.WeaponData
_damage: 10
_fireInterval: 0.2
_maxAmmo: 30
_projectilePrefab: {fileID: 1267975713900649858, guid: ab8f44a00f0019943847ff16fd95cdfd, type: 3}
_projectileSpeed: 20
_projectileLifetime: 2

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c26b3ad646cf24c48904c1878f8d37e8
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

BIN
Assets/_Content/Models/Gun.fbx LFS Normal file

Binary file not shown.

View File

@@ -0,0 +1,110 @@
fileFormatVersion: 2
guid: 6fff3f1a06c6aab4fb5e1055f1d22848
ModelImporter:
serializedVersion: 24200
internalIDToNameTable: []
externalObjects: {}
materials:
materialImportMode: 2
materialName: 0
materialSearch: 1
materialLocation: 1
animations:
legacyGenerateAnimations: 4
bakeSimulation: 0
resampleCurves: 1
optimizeGameObjects: 0
removeConstantScaleCurves: 0
motionNodeName:
animationImportErrors:
animationImportWarnings:
animationRetargetingWarnings:
animationDoRetargetingWarnings: 0
importAnimatedCustomProperties: 0
importConstraints: 0
animationCompression: 1
animationRotationError: 0.5
animationPositionError: 0.5
animationScaleError: 0.5
animationWrapMode: 0
extraExposedTransformPaths: []
extraUserProperties: []
clipAnimations: []
isReadable: 0
meshes:
lODScreenPercentages: []
globalScale: 100
meshCompression: 0
addColliders: 0
useSRGBMaterialColor: 1
sortHierarchyByName: 1
importPhysicalCameras: 1
importVisibility: 1
importBlendShapes: 1
importCameras: 1
importLights: 1
nodeNameCollisionStrategy: 1
fileIdsGeneration: 2
swapUVChannels: 0
generateSecondaryUV: 0
useFileUnits: 1
keepQuads: 0
weldVertices: 1
bakeAxisConversion: 0
preserveHierarchy: 0
skinWeightsMode: 0
maxBonesPerVertex: 4
minBoneWeight: 0.001
optimizeBones: 1
generateMeshLods: 0
meshLodGenerationFlags: 0
maximumMeshLod: -1
meshOptimizationFlags: -1
indexFormat: 0
secondaryUVAngleDistortion: 8
secondaryUVAreaDistortion: 15.000001
secondaryUVHardAngle: 88
secondaryUVMarginMethod: 1
secondaryUVMinLightmapResolution: 40
secondaryUVMinObjectScale: 1
secondaryUVPackMargin: 4
useFileScale: 1
strictVertexDataChecks: 0
tangentSpace:
normalSmoothAngle: 60
normalImportMode: 0
tangentImportMode: 3
normalCalculationMode: 4
legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 0
blendShapeNormalImportMode: 1
normalSmoothingSource: 0
referencedClips: []
importAnimation: 1
humanDescription:
serializedVersion: 3
human: []
skeleton: []
armTwist: 0.5
foreArmTwist: 0.5
upperLegTwist: 0.5
legTwist: 0.5
armStretch: 0.05
legStretch: 0.05
feetSpacing: 0
globalScale: 1
rootMotionBoneName:
hasTranslationDoF: 0
hasExtraRoot: 0
skeletonHasParents: 1
lastHumanDescriptionAvatarSource: {instanceID: 0}
autoGenerateAvatarMappingIfUnspecified: 1
animationType: 2
humanoidOversampling: 1
avatarSetup: 0
addHumanoidExtraRootOnlyWhenUsingAvatar: 1
importBlendShapeDeformPercent: 1
remapMaterialsIfMaterialImportModeIsNone: 0
additionalBone: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,110 @@
fileFormatVersion: 2
guid: 353aa13c4cf685d4da0564413baffc19
ModelImporter:
serializedVersion: 24200
internalIDToNameTable: []
externalObjects: {}
materials:
materialImportMode: 2
materialName: 0
materialSearch: 1
materialLocation: 1
animations:
legacyGenerateAnimations: 4
bakeSimulation: 0
resampleCurves: 1
optimizeGameObjects: 0
removeConstantScaleCurves: 0
motionNodeName:
animationImportErrors:
animationImportWarnings:
animationRetargetingWarnings:
animationDoRetargetingWarnings: 0
importAnimatedCustomProperties: 0
importConstraints: 0
animationCompression: 1
animationRotationError: 0.5
animationPositionError: 0.5
animationScaleError: 0.5
animationWrapMode: 0
extraExposedTransformPaths: []
extraUserProperties: []
clipAnimations: []
isReadable: 0
meshes:
lODScreenPercentages: []
globalScale: 100
meshCompression: 0
addColliders: 0
useSRGBMaterialColor: 1
sortHierarchyByName: 1
importPhysicalCameras: 1
importVisibility: 1
importBlendShapes: 1
importCameras: 1
importLights: 1
nodeNameCollisionStrategy: 1
fileIdsGeneration: 2
swapUVChannels: 0
generateSecondaryUV: 0
useFileUnits: 1
keepQuads: 0
weldVertices: 1
bakeAxisConversion: 0
preserveHierarchy: 0
skinWeightsMode: 0
maxBonesPerVertex: 4
minBoneWeight: 0.001
optimizeBones: 1
generateMeshLods: 0
meshLodGenerationFlags: 0
maximumMeshLod: -1
meshOptimizationFlags: -1
indexFormat: 0
secondaryUVAngleDistortion: 8
secondaryUVAreaDistortion: 15.000001
secondaryUVHardAngle: 88
secondaryUVMarginMethod: 1
secondaryUVMinLightmapResolution: 40
secondaryUVMinObjectScale: 1
secondaryUVPackMargin: 4
useFileScale: 1
strictVertexDataChecks: 0
tangentSpace:
normalSmoothAngle: 60
normalImportMode: 0
tangentImportMode: 3
normalCalculationMode: 4
legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 0
blendShapeNormalImportMode: 1
normalSmoothingSource: 0
referencedClips: []
importAnimation: 1
humanDescription:
serializedVersion: 3
human: []
skeleton: []
armTwist: 0.5
foreArmTwist: 0.5
upperLegTwist: 0.5
legTwist: 0.5
armStretch: 0.05
legStretch: 0.05
feetSpacing: 0
globalScale: 1
rootMotionBoneName:
hasTranslationDoF: 0
hasExtraRoot: 0
skeletonHasParents: 1
lastHumanDescriptionAvatarSource: {instanceID: 0}
autoGenerateAvatarMappingIfUnspecified: 1
animationType: 2
humanoidOversampling: 1
avatarSetup: 0
addHumanoidExtraRootOnlyWhenUsingAvatar: 1
importBlendShapeDeformPercent: 1
remapMaterialsIfMaterialImportModeIsNone: 0
additionalBone: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,5 +1,126 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &3321106030899012940
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 635898796213162980}
m_Layer: 0
m_Name: Muzzle
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &635898796213162980
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3321106030899012940}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0.064, z: 0.446}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 4595290834041894522}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &5286650573156461405
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 2648838692056603215}
- component: {fileID: 4433368355904579625}
- component: {fileID: 7841523364635298371}
m_Layer: 0
m_Name: Cube
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &2648838692056603215
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5286650573156461405}
serializedVersion: 2
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0.413, z: 0.46}
m_LocalScale: {x: 0.57788104, y: 0.23092704, z: 0.3382222}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 8656262745496025766}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &4433368355904579625
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5286650573156461405}
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
--- !u!23 &7841523364635298371
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5286650573156461405}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_MaskInteraction: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!1 &5701756709460610233
GameObject:
m_ObjectHideFlags: 0
@@ -9,6 +130,8 @@ GameObject:
serializedVersion: 6
m_Component:
- component: {fileID: 1336261255310037562}
- component: {fileID: 4700255994880078248}
- component: {fileID: 7678313450534884141}
m_Layer: 0
m_Name: Player
m_TagString: Untagged
@@ -30,8 +153,60 @@ Transform:
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 8656262745496025766}
- {fileID: 4595290834041894522}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!143 &4700255994880078248
CharacterController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5701756709460610233}
m_Material: {fileID: 0}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_LayerOverridePriority: 0
m_ProvidesContacts: 0
m_Enabled: 1
serializedVersion: 3
m_Height: 1.64
m_Radius: 0.37
m_SlopeLimit: 45
m_StepOffset: 0.3
m_SkinWidth: 0.08
m_MinMoveDistance: 0.001
m_Center: {x: 0, y: 0.9, z: 0}
--- !u!114 &7678313450534884141
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5701756709460610233}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 502392351c6ed7e4c9a3a895792f5b68, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::PlayerMovero
_settings:
Speed: 10
_references:
Controller: {fileID: 4700255994880078248}
Launcher: {fileID: 6426658406708130876}
MoveAction: {fileID: -1680190386980627800, guid: 052faaac586de48259a63d0c4782560b, type: 3}
LookAction: {fileID: -5630151704836100654, guid: 052faaac586de48259a63d0c4782560b, type: 3}
AttackAction: {fileID: 1120369429361536294, guid: 052faaac586de48259a63d0c4782560b, type: 3}
InteractAction: {fileID: 1781555164194001046, guid: 052faaac586de48259a63d0c4782560b, type: 3}
_state:
IsMoving: 0
_health:
Max: 100
_current: 0
--- !u!1 &7176853314782784158
GameObject:
m_ObjectHideFlags: 0
@@ -59,10 +234,11 @@ Transform:
m_GameObject: {fileID: 7176853314782784158}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 1, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_LocalPosition: {x: 0, y: 0.9, z: 0}
m_LocalScale: {x: 0.9, y: 0.9, z: 0.9}
m_ConstrainProportionsScale: 1
m_Children:
- {fileID: 2648838692056603215}
m_Father: {fileID: 1336261255310037562}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &179238054112632900
@@ -122,3 +298,106 @@ MeshRenderer:
m_SortingOrder: 0
m_MaskInteraction: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!1001 &4057595757166956945
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 1336261255310037562}
m_Modifications:
- target: {fileID: -8679921383154817045, guid: 6fff3f1a06c6aab4fb5e1055f1d22848, type: 3}
propertyPath: m_LocalScale.x
value: 1
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 6fff3f1a06c6aab4fb5e1055f1d22848, type: 3}
propertyPath: m_LocalScale.y
value: 1
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 6fff3f1a06c6aab4fb5e1055f1d22848, type: 3}
propertyPath: m_LocalScale.z
value: 1
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 6fff3f1a06c6aab4fb5e1055f1d22848, type: 3}
propertyPath: m_LocalPosition.x
value: 0.479
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 6fff3f1a06c6aab4fb5e1055f1d22848, type: 3}
propertyPath: m_LocalPosition.y
value: 0.878
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 6fff3f1a06c6aab4fb5e1055f1d22848, type: 3}
propertyPath: m_LocalPosition.z
value: 0.404
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 6fff3f1a06c6aab4fb5e1055f1d22848, type: 3}
propertyPath: m_LocalRotation.w
value: 1
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 6fff3f1a06c6aab4fb5e1055f1d22848, type: 3}
propertyPath: m_LocalRotation.x
value: -0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 6fff3f1a06c6aab4fb5e1055f1d22848, type: 3}
propertyPath: m_LocalRotation.y
value: -0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 6fff3f1a06c6aab4fb5e1055f1d22848, type: 3}
propertyPath: m_LocalRotation.z
value: -0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 6fff3f1a06c6aab4fb5e1055f1d22848, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 6fff3f1a06c6aab4fb5e1055f1d22848, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 6fff3f1a06c6aab4fb5e1055f1d22848, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 919132149155446097, guid: 6fff3f1a06c6aab4fb5e1055f1d22848, type: 3}
propertyPath: m_Name
value: Gun
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects:
- targetCorrespondingSourceObject: {fileID: -8679921383154817045, guid: 6fff3f1a06c6aab4fb5e1055f1d22848, type: 3}
insertIndex: -1
addedObject: {fileID: 635898796213162980}
m_AddedComponents:
- targetCorrespondingSourceObject: {fileID: 919132149155446097, guid: 6fff3f1a06c6aab4fb5e1055f1d22848, type: 3}
insertIndex: -1
addedObject: {fileID: 6426658406708130876}
m_SourcePrefab: {fileID: 100100000, guid: 6fff3f1a06c6aab4fb5e1055f1d22848, type: 3}
--- !u!1 &3786981955428199616 stripped
GameObject:
m_CorrespondingSourceObject: {fileID: 919132149155446097, guid: 6fff3f1a06c6aab4fb5e1055f1d22848, type: 3}
m_PrefabInstance: {fileID: 4057595757166956945}
m_PrefabAsset: {fileID: 0}
--- !u!114 &6426658406708130876
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3786981955428199616}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 1a1a8c56cfabcd648a0967ce7acc5ed3, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::Arena.Combat.ProjectileLauncher
_settings:
Weapon: {fileID: 11400000, guid: c26b3ad646cf24c48904c1878f8d37e8, type: 2}
_references:
Muzzle: {fileID: 635898796213162980}
_state:
Ammo: 0
--- !u!4 &4595290834041894522 stripped
Transform:
m_CorrespondingSourceObject: {fileID: -8679921383154817045, guid: 6fff3f1a06c6aab4fb5e1055f1d22848, type: 3}
m_PrefabInstance: {fileID: 4057595757166956945}
m_PrefabAsset: {fileID: 0}

View File

@@ -0,0 +1,148 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1001 &6417798391929613390
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 0}
m_Modifications:
- target: {fileID: -8679921383154817045, guid: 353aa13c4cf685d4da0564413baffc19, type: 3}
propertyPath: m_LocalScale.x
value: 1
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 353aa13c4cf685d4da0564413baffc19, type: 3}
propertyPath: m_LocalScale.y
value: 1
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 353aa13c4cf685d4da0564413baffc19, type: 3}
propertyPath: m_LocalScale.z
value: 1
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 353aa13c4cf685d4da0564413baffc19, type: 3}
propertyPath: m_LocalPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 353aa13c4cf685d4da0564413baffc19, type: 3}
propertyPath: m_LocalPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 353aa13c4cf685d4da0564413baffc19, type: 3}
propertyPath: m_LocalPosition.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 353aa13c4cf685d4da0564413baffc19, type: 3}
propertyPath: m_LocalRotation.w
value: 1
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 353aa13c4cf685d4da0564413baffc19, type: 3}
propertyPath: m_LocalRotation.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 353aa13c4cf685d4da0564413baffc19, type: 3}
propertyPath: m_LocalRotation.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 353aa13c4cf685d4da0564413baffc19, type: 3}
propertyPath: m_LocalRotation.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 353aa13c4cf685d4da0564413baffc19, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 353aa13c4cf685d4da0564413baffc19, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 353aa13c4cf685d4da0564413baffc19, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 919132149155446097, guid: 353aa13c4cf685d4da0564413baffc19, type: 3}
propertyPath: m_Name
value: Projectile
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents:
- targetCorrespondingSourceObject: {fileID: 919132149155446097, guid: 353aa13c4cf685d4da0564413baffc19, type: 3}
insertIndex: -1
addedObject: {fileID: 367274961135860047}
- targetCorrespondingSourceObject: {fileID: 919132149155446097, guid: 353aa13c4cf685d4da0564413baffc19, type: 3}
insertIndex: -1
addedObject: {fileID: 976289565335777750}
- targetCorrespondingSourceObject: {fileID: 919132149155446097, guid: 353aa13c4cf685d4da0564413baffc19, type: 3}
insertIndex: -1
addedObject: {fileID: 1267975713900649858}
m_SourcePrefab: {fileID: 100100000, guid: 353aa13c4cf685d4da0564413baffc19, type: 3}
--- !u!1 &6183988142400639263 stripped
GameObject:
m_CorrespondingSourceObject: {fileID: 919132149155446097, guid: 353aa13c4cf685d4da0564413baffc19, type: 3}
m_PrefabInstance: {fileID: 6417798391929613390}
m_PrefabAsset: {fileID: 0}
--- !u!135 &367274961135860047
SphereCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6183988142400639263}
m_Material: {fileID: 0}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_LayerOverridePriority: 0
m_IsTrigger: 0
m_ProvidesContacts: 0
m_Enabled: 1
serializedVersion: 3
m_Radius: 0.3
m_Center: {x: 0, y: 0, z: 0}
--- !u!54 &976289565335777750
Rigidbody:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6183988142400639263}
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 &1267975713900649858
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6183988142400639263}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 7671f358930703f4683397845e17e460, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::Arena.Combat.Projectile
_settings:
Speed: 20
Lifetime: 2

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: ab8f44a00f0019943847ff16fd95cdfd
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -1,13 +0,0 @@
using UnityEngine;
[ExecuteAlways]
public class CameraFollower : MonoBehaviour
{
public GameObject Player;
void Update()
{
if (Player)
transform.position = Player.transform.position;
}
}

View File

@@ -1,2 +0,0 @@
fileFormatVersion: 2
guid: 4ae4fbdc595247448b3d604825bd07fe

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 00d5f0f5167a1a243a9972a98593b122
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,276 @@
using System;
using UnityEngine;
using UnityEngine.InputSystem;
using Arena.Combat;
namespace Arena.Characters
{
public class Player : MonoBehaviour, IDamageable
{
[System.Serializable]
public class Settings
{
[Tooltip("Movement speed, in km/h.")]
[Min(0f)] public float Speed = 5f;
}
[System.Serializable]
public struct References
{
public CharacterController Controller;
public ProjectileLauncher Launcher;
public InputActionReference MoveAction;
public InputActionReference LookAction;
public InputActionReference AttackAction;
public InputActionReference InteractAction;
}
[System.Serializable]
public class StateContainer
{
public bool IsMoving;
}
#region Fields
private const float KMH_TO_MS = 1f / 3.6f;
private const float AIM_STICK_DEADZONE = 0.2f;
[SerializeField] private Settings _settings;
[SerializeField] private References _references;
[SerializeField] private StateContainer _state;
[SerializeField] private Health _health;
/// <summary>
/// Raised when the interact action is performed.
/// </summary>
public event Action OnInteract;
/// <summary>
/// The only player of the scene.
/// </summary>
public static Player Instance { get; private set; }
public StateContainer State => _state;
public Health Health => _health;
public ProjectileLauncher Launcher => _references.Launcher;
private Camera _camera;
private Vector2 _moveInput;
private Vector2 _aimStickInput;
private bool _isAimingWithStick;
private bool _isAttacking;
private bool _isInteracting;
private Vector3 _aimDirection = Vector3.forward;
#endregion
#region Unity Lifecycle
void Awake()
{
// Only one player can exist: a second one is removed
if (Instance && Instance != this)
{
Debug.LogWarning($"A second Player was found on {name}, it is destroyed.");
Destroy(gameObject);
return;
}
Instance = this;
// Camera.main is the camera tagged MainCamera
_camera = Camera.main;
_health.Initialize();
}
void OnEnable()
{
SetInputsEnabled(true);
}
void OnDisable()
{
SetInputsEnabled(false);
}
void OnDestroy()
{
if (Instance == this)
Instance = null;
}
void Update()
{
// A dead player no longer moves nor shoots
if (_health.IsDead)
return;
float deltaTime = Time.deltaTime;
GetInputs();
Move(deltaTime);
Aim();
Attack();
Interact();
}
#endregion
#region Public Methods
public void TakeDamage(int amount)
{
_health.TakeDamage(amount);
}
/// <summary>
/// Teleports the player.
/// </summary>
/// <param name="pose">x, y, z: position. w: angle around the vertical axis, in degrees.</param>
public void Teleport(Vector4 pose)
{
// An enabled CharacterController would overwrite the new position
_references.Controller.enabled = false;
Vector3 position = new Vector3(pose.x, pose.y, pose.z);
Quaternion rotation = Quaternion.Euler(0f, pose.w, 0f);
transform.SetPositionAndRotation(position, rotation);
_references.Controller.enabled = true;
}
/// <summary>
/// Teleports the player to the position and heading of a target, such as a spawn point.
/// </summary>
public void Teleport(Transform target)
{
Vector3 position = target.position;
Vector4 pose = new Vector4(position.x, position.y, position.z, target.eulerAngles.y);
Teleport(pose);
}
#endregion
#region Private Methods
private void SetInputsEnabled(bool isEnabled)
{
InputActionReference[] actions =
{
_references.MoveAction,
_references.LookAction,
_references.AttackAction,
_references.InteractAction
};
foreach (InputActionReference action in actions)
{
if (isEnabled)
action.action.Enable();
else
action.action.Disable();
}
}
private void GetInputs()
{
_moveInput = _references.MoveAction.action.ReadValue<Vector2>();
_isAttacking = _references.AttackAction.action.IsPressed();
_isInteracting = _references.InteractAction.action.WasPerformedThisFrame();
InputAction look = _references.LookAction.action;
_aimStickInput = look.ReadValue<Vector2>();
// Look is also bound to the mouse delta: only the gamepad counts as a stick
bool isStick = look.activeControl != null && look.activeControl.device is Gamepad;
// The last aiming device used wins: the stick when pushed, the mouse when moved
if (isStick && IsStickPushed())
_isAimingWithStick = true;
else if (Pointer.current != null && Pointer.current.delta.ReadValue().sqrMagnitude > 0f)
_isAimingWithStick = false;
}
private void Move(float deltaTime)
{
Vector3 direction = ToWorldDirection(_moveInput);
_state.IsMoving = direction.sqrMagnitude > 0f;
Vector3 velocity = direction * _settings.Speed * KMH_TO_MS;
_references.Controller.Move(velocity * deltaTime);
}
private void Aim()
{
if (_isAimingWithStick)
{
// Released stick: the player keeps its last direction
if (IsStickPushed())
_aimDirection = ToWorldDirection(_aimStickInput);
}
else if (TryGetPointerDirection(out Vector3 direction))
{
_aimDirection = direction;
}
transform.rotation = Quaternion.LookRotation(_aimDirection);
}
private void Attack()
{
if (_isAttacking)
_references.Launcher.TryFire();
}
private void Interact()
{
if (_isInteracting)
OnInteract?.Invoke();
}
private bool IsStickPushed()
{
return _aimStickInput.sqrMagnitude > AIM_STICK_DEADZONE * AIM_STICK_DEADZONE;
}
/// <summary>
/// Converts a 2D input into a world direction on the ground, relative to the camera heading.
/// </summary>
private Vector3 ToWorldDirection(Vector2 input)
{
// Only the camera rotation around the vertical axis is kept
Quaternion cameraHeading = Quaternion.Euler(0f, _camera.transform.eulerAngles.y, 0f);
return cameraHeading * new Vector3(input.x, 0f, input.y);
}
/// <summary>
/// Direction from the player to the point under the pointer, on a horizontal plane at the player's height.
/// </summary>
private bool TryGetPointerDirection(out Vector3 direction)
{
direction = Vector3.zero;
if (Pointer.current == null)
return false;
// Mouse position read directly: the Look action only gives its movement
Ray ray = _camera.ScreenPointToRay(Pointer.current.position.ReadValue());
Plane ground = new Plane(Vector3.up, transform.position);
if (!ground.Raycast(ray, out float distance))
return false;
direction = ray.GetPoint(distance) - transform.position;
direction.y = 0f;
return direction.sqrMagnitude > 0.01f;
}
[ContextMenu("Debug/Take 25 Damage")]
private void DebugTakeDamage()
{
TakeDamage(25);
}
#endregion
}
}

View File

@@ -0,0 +1,89 @@
using UnityEngine;
namespace Arena.Characters
{
[ExecuteAlways]
public class PlayerCamera : MonoBehaviour
{
[System.Serializable]
public class Settings
{
[Tooltip("x: horizontal distance from the player, y: height above the player, in meters.")]
public Vector2 Offset = new Vector2(8f, 12f);
[Tooltip("Rotation of the offset around the player, in degrees.")]
public float Angle = 0f;
[Tooltip("Time to catch up with the player, in seconds. 0: no smoothing.")]
[Range(0f, 1f)] public float Smooth = 0.2f;
}
[System.Serializable]
public struct References
{
[Tooltip("Followed player. Found automatically when empty.")]
public Player Player;
}
#region Fields
[SerializeField] private Settings _settings;
[SerializeField] private References _references;
private Vector3 _velocity;
#endregion
#region Unity Lifecycle
// LateUpdate: the player has already moved this frame
void LateUpdate()
{
if (!GetPlayer())
return;
Vector3 targetPos = GetTargetPosition();
// No smoothing in edit mode: the camera snaps while the scene is edited
if (!Application.isPlaying || _settings.Smooth <= 0f)
{
transform.position = targetPos;
_velocity = Vector3.zero;
}
else
{
transform.position = Vector3.SmoothDamp(transform.position, targetPos, ref _velocity, _settings.Smooth);
}
}
#endregion
#region Private Methods
/// <summary>
/// Looks for the player: singleton first, then a search in the scene. Returns false if none is found.
/// </summary>
private bool GetPlayer()
{
if (_references.Player)
return true;
// In edit mode, Player.Awake has not run, so the singleton is empty
else if (Player.Instance)
_references.Player = Player.Instance;
else
_references.Player = FindFirstObjectByType<Player>();
return _references.Player != null;
}
private Vector3 GetTargetPosition()
{
Quaternion rotation = Quaternion.Euler(0f, _settings.Angle, 0f);
Vector3 offset = rotation * new Vector3(0f, _settings.Offset.y, -_settings.Offset.x);
return _references.Player.transform.position + offset;
}
#endregion
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: bd78e931d0126914e8206e9f6bb2b9de

View File

@@ -0,0 +1,96 @@
using UnityEngine;
using UnityEngine.Events;
using Arena.Characters;
namespace Arena.Interactions
{
/// <summary>
/// Zone that raises OnPlayer when the player enters it, or when the player interacts inside it.
/// It never acts on the player itself: the actions are set up in the Inspector.
/// </summary>
[RequireComponent(typeof(Collider))]
public class PlayerEvent : MonoBehaviour
{
public enum Trigger
{
OnPlayerEnter,
OnPlayerInteract
}
[System.Serializable]
public class Settings
{
[Tooltip("OnPlayerEnter: as soon as the player enters. OnPlayerInteract: when the player interacts inside the zone.")]
public Trigger Trigger;
}
#region Fields
[SerializeField] private Settings _settings;
[Tooltip("Actions raised for the player: heal, ammo, sound, hide this object...")]
[SerializeField] private UnityEvent _onPlayer;
private bool _isListening;
#endregion
#region Unity Lifecycle
private void OnDisable()
{
// The object can be hidden while the player is inside
StopListening();
}
private void OnTriggerEnter(Collider other)
{
if (!IsPlayer(other))
return;
if (_settings.Trigger == Trigger.OnPlayerEnter)
_onPlayer.Invoke();
else
StartListening();
}
private void OnTriggerExit(Collider other)
{
if (IsPlayer(other))
StopListening();
}
#endregion
#region Private Methods
private bool IsPlayer(Collider other)
{
return Player.Instance != null && other.gameObject == Player.Instance.gameObject;
}
private void StartListening()
{
Player.Instance.OnInteract += HandleInteract;
_isListening = true;
}
private void StopListening()
{
if (!_isListening)
return;
if (Player.Instance != null)
Player.Instance.OnInteract -= HandleInteract;
_isListening = false;
}
private void HandleInteract()
{
_onPlayer.Invoke();
}
#endregion
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: d3c874cb9bc4c364d87e100aada2b434

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d5ab3689e81574b4c8d1b37201093edf
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,34 @@
using UnityEngine;
using Arena.Characters;
namespace Arena.Interactions
{
/// <summary>
/// Gives ammo to the player. Apply is meant to be linked to a PlayerEvent.
/// </summary>
public class AmmoEffect : MonoBehaviour
{
[System.Serializable]
public class Settings
{
[Tooltip("Ammo given to the player.")]
[Min(1)] public int Amount = 10;
}
#region Fields
[SerializeField] private Settings _settings;
#endregion
#region Public Methods
public void Apply()
{
if (Player.Instance != null)
Player.Instance.Launcher.AddAmmo(_settings.Amount);
}
#endregion
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 3831749972a75dc4dbe47f8a551785fc

View File

@@ -0,0 +1,34 @@
using UnityEngine;
using Arena.Characters;
namespace Arena.Interactions
{
/// <summary>
/// Heals the player. Apply is meant to be linked to a PlayerEvent.
/// </summary>
public class HealEffect : MonoBehaviour
{
[System.Serializable]
public class Settings
{
[Tooltip("Hit points given to the player.")]
[Min(1)] public int Amount = 25;
}
#region Fields
[SerializeField] private Settings _settings;
#endregion
#region Public Methods
public void Apply()
{
if (Player.Instance != null)
Player.Instance.Health.Heal(_settings.Amount);
}
#endregion
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 3b9353836241da04e9bb64cc87f89745

View File

@@ -0,0 +1,83 @@
using System;
using UnityEngine;
namespace Arena.Combat
{
/// <summary>
/// Hit points of an entity. Serialized inside the component that owns it (Player, Enemy),
/// which calls Initialize in its Awake.
/// </summary>
[System.Serializable]
public class Health
{
#region Fields
[Tooltip("Hit points when full.")]
[Min(1)] public int Max = 100;
[Tooltip("Current hit points, visible for debugging.")]
[SerializeField] private int _current;
/// <summary>
/// Raised with the current and max hit points each time they change.
/// </summary>
public event Action<int, int> OnChange;
/// <summary>
/// Raised once, when the hit points reach zero.
/// </summary>
public event Action OnDied;
public int Current => _current;
public bool IsDead => _current <= 0;
#endregion
#region Public Methods
/// <summary>
/// Fills the hit points. Called by the owner in its Awake.
/// </summary>
public void Initialize()
{
SetCurrent(Max);
}
/// <summary>
/// Removes hit points and raises OnDied the first time they reach zero.
/// </summary>
public void TakeDamage(int amount)
{
if (IsDead || amount <= 0)
return;
SetCurrent(_current - amount);
if (IsDead)
OnDied?.Invoke();
}
/// <summary>
/// Gives hit points back without exceeding Max. Has no effect once dead.
/// </summary>
public void Heal(int amount)
{
if (IsDead || amount <= 0)
return;
SetCurrent(_current + amount);
}
#endregion
#region Private Methods
private void SetCurrent(int value)
{
_current = Mathf.Clamp(value, 0, Max);
OnChange?.Invoke(_current, Max);
}
#endregion
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 220d6096ae28c12449f72c38860cbc2e

View File

@@ -0,0 +1,10 @@
namespace Arena.Combat
{
/// <summary>
/// Anything that can receive damage: player, enemy, destructible object.
/// </summary>
public interface IDamageable
{
void TakeDamage(int amount);
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 14df4410feff3d044afb4ec552a18997

View File

@@ -0,0 +1,68 @@
using UnityEngine;
namespace Arena.Combat
{
/// <summary>
/// Moves straight ahead and damages the first IDamageable it touches.
/// Needs a trigger collider and a kinematic Rigidbody.
/// </summary>
[RequireComponent(typeof(Rigidbody))]
public class Projectile : MonoBehaviour
{
[System.Serializable]
public class Settings
{
[Tooltip("Speed, in meters per second.")]
[Min(0f)] public float Speed = 20f;
[Tooltip("Time before an unused projectile is destroyed, in seconds.")]
[Min(0.1f)] public float Lifetime = 2f;
}
#region Fields
[SerializeField] private Settings _settings;
private int _damage;
private GameObject _owner;
#endregion
#region Unity Lifecycle
private void Update()
{
transform.position += transform.forward * _settings.Speed * Time.deltaTime;
}
private void OnTriggerEnter(Collider other)
{
// Ignore the shooter and the other trigger zones
if (other.isTrigger || other.gameObject == _owner)
return;
if (other.TryGetComponent(out IDamageable target))
target.TakeDamage(_damage);
Destroy(gameObject);
}
#endregion
#region Public Methods
/// <summary>
/// Starts the projectile. Called right after Instantiate by whoever fires it.
/// </summary>
/// <param name="damage">Damage dealt to the IDamageable it touches.</param>
/// <param name="owner">Shooter, ignored by the projectile.</param>
public void Launch(int damage, GameObject owner)
{
_damage = damage;
_owner = owner;
Destroy(gameObject, _settings.Lifetime);
}
#endregion
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 7671f358930703f4683397845e17e460

View File

@@ -0,0 +1,107 @@
using System;
using UnityEngine;
namespace Arena.Combat
{
/// <summary>
/// Fires projectiles from a muzzle, limited by the fire interval and the ammo count.
/// Placed on the root of the shooter, which the projectiles ignore.
/// </summary>
public class ProjectileLauncher : MonoBehaviour
{
[System.Serializable]
public class Settings
{
[Tooltip("Weapon data: damage, fire interval, ammo, projectile.")]
public WeaponData Weapon;
}
[System.Serializable]
public struct References
{
[Tooltip("Spawn point of the projectiles. Its forward axis gives the direction.")]
public Transform Muzzle;
}
[System.Serializable]
public class StateContainer
{
public int Ammo;
}
#region Fields
[SerializeField] private Settings _settings;
[SerializeField] private References _references;
[SerializeField] private StateContainer _state;
/// <summary>
/// Raised with the current and max ammo each time the ammo changes.
/// </summary>
public event Action<int, int> OnAmmoChange;
public StateContainer State => _state;
public int MaxAmmo => _settings.Weapon.MaxAmmo;
private float _nextFireTime;
#endregion
#region Unity Lifecycle
private void Awake()
{
_state.Ammo = MaxAmmo;
}
#endregion
#region Public Methods
/// <summary>
/// Fires one projectile if the weapon is ready and has ammo. Returns true if a shot was fired.
/// </summary>
public bool TryFire()
{
if (Time.time < _nextFireTime || _state.Ammo <= 0)
return false;
_nextFireTime = Time.time + _settings.Weapon.FireInterval;
SetAmmo(_state.Ammo - 1);
Transform muzzle = _references.Muzzle;
Projectile projectile = Instantiate(_settings.Weapon.ProjectilePrefab, muzzle.position, muzzle.rotation);
projectile.Launch(_settings.Weapon.Damage, gameObject);
return true;
}
/// <summary>
/// Adds ammo without exceeding the weapon maximum.
/// </summary>
public void AddAmmo(int amount)
{
if (amount <= 0)
return;
SetAmmo(Mathf.Min(_state.Ammo + amount, MaxAmmo));
}
#endregion
#region Private Methods
private void SetAmmo(int value)
{
_state.Ammo = value;
OnAmmoChange?.Invoke(_state.Ammo, MaxAmmo);
}
[ContextMenu("Debug/Try Fire")]
private void DebugTryFire()
{
TryFire();
}
#endregion
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 1a1a8c56cfabcd648a0967ce7acc5ed3

View File

@@ -0,0 +1,68 @@
using UnityEngine;
using Arena.Characters;
namespace Arena.UI
{
/// <summary>
/// Single entry point of the UI: connects the views to the player and switches screens.
/// </summary>
public class UiManager : MonoBehaviour
{
[System.Serializable]
public struct References
{
[Tooltip("In-game screen: health, ammo.")]
public GameObject Hud;
public HealthView HealthView;
public AmmoView AmmoView;
public GameOverView GameOverView;
}
#region Fields
[SerializeField] private References _references;
private Player _player;
#endregion
#region Unity Lifecycle
private void Start()
{
// Start: every Awake has run, so Player.Instance is set
_player = Player.Instance;
if (_player == null)
{
Debug.LogError("UiManager: no Player in the scene.");
return;
}
_references.HealthView.Bind(_player.Health);
_references.AmmoView.Bind(_player.Launcher);
_player.Health.OnDied += HandlePlayerDied;
_references.Hud.SetActive(true);
_references.GameOverView.Hide();
}
private void OnDestroy()
{
if (_player != null)
_player.Health.OnDied -= HandlePlayerDied;
}
#endregion
#region Private Methods
private void HandlePlayerDied()
{
_references.Hud.SetActive(false);
_references.GameOverView.Show();
}
#endregion
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 4c6cb5ac8e4f8d0479afda241378ff0b

View File

@@ -0,0 +1,32 @@
using UnityEngine;
namespace Arena.Combat
{
/// <summary>
/// Settings of a weapon, shared by every launcher that uses it.
/// </summary>
[CreateAssetMenu(fileName = "WeaponData_new", menuName = "Arena/Combat/Weapon Data")]
public class WeaponData : ScriptableObject
{
#region Fields
[Tooltip("Damage dealt by one projectile.")]
[SerializeField, Min(0)] private int _damage = 10;
[Tooltip("Time between two shots, in seconds.")]
[SerializeField, Min(0.05f)] private float _fireInterval = 0.2f;
[Tooltip("Ammo when the weapon is full.")]
[SerializeField, Min(1)] private int _maxAmmo = 30;
[Tooltip("Prefab fired by the weapon.")]
[SerializeField] private Projectile _projectilePrefab;
public int Damage => _damage;
public float FireInterval => _fireInterval;
public int MaxAmmo => _maxAmmo;
public Projectile ProjectilePrefab => _projectilePrefab;
#endregion
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: b4a4852c6f394a441935fae7b9f9ec82

View File

@@ -1,53 +0,0 @@
using System.ComponentModel;
using UnityEngine;
public class PlayerMover : MonoBehaviour
{
[System.Serializable]
private class Settings
{
public float Speed = 5;
}
[System.Serializable]
private struct References
{
public CharacterController Controller;
}
[System.Serializable]
public class StateContainer
{
public bool IsJumping = false;
}
#region FIELDS
const float MS_TO_KMH = 1 / 3.6f;
[SerializeField] private Settings _settings;
[SerializeField] private References _references;
[SerializeField] private StateContainer _state;
public StateContainer State => _state;
#endregion
#region UNITY LIFECYCLES
void Update()
{
float t = Time.deltaTime;
Move(t);
}
private void Move(float t)
{
transform.position += Vector3.forward * t * MS_TO_KMH * _settings.Speed;
}
#endregion
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e11b6fbe420e7b94b8000b7e9c608900
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,59 @@
using TMPro;
using UnityEngine;
using Arena.Combat;
namespace Arena.UI
{
/// <summary>
/// Displays the ammo of a launcher as "current / max".
/// </summary>
public class AmmoView : MonoBehaviour
{
[System.Serializable]
public struct References
{
public TMP_Text Label;
}
#region Fields
[SerializeField] private References _references;
private ProjectileLauncher _launcher;
#endregion
#region Unity Lifecycle
private void OnDestroy()
{
if (_launcher != null)
_launcher.OnAmmoChange -= HandleAmmoChange;
}
#endregion
#region Public Methods
/// <summary>
/// Starts displaying the ammo of a launcher. Called by the UiManager.
/// </summary>
public void Bind(ProjectileLauncher launcher)
{
_launcher = launcher;
_launcher.OnAmmoChange += HandleAmmoChange;
HandleAmmoChange(_launcher.State.Ammo, _launcher.MaxAmmo);
}
#endregion
#region Private Methods
private void HandleAmmoChange(int current, int max)
{
_references.Label.SetText("{0} / {1}", current, max);
}
#endregion
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: ca9ade34ced9c264fad512c9408d61d8

View File

@@ -0,0 +1,33 @@
using UnityEngine;
using UnityEngine.SceneManagement;
namespace Arena.UI
{
/// <summary>
/// Game over screen. Its Restart button reloads the scene.
/// </summary>
public class GameOverView : MonoBehaviour
{
#region Public Methods
public void Show()
{
gameObject.SetActive(true);
}
public void Hide()
{
gameObject.SetActive(false);
}
/// <summary>
/// Called by the Restart button (OnClick in the Inspector).
/// </summary>
public void Restart()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
#endregion
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 78d77256975d6d7499a20292c00b0649

View File

@@ -0,0 +1,60 @@
using TMPro;
using UnityEngine;
using Arena.Combat;
namespace Arena.UI
{
/// <summary>
/// Displays a Health as "current / max".
/// </summary>
public class HealthView : MonoBehaviour
{
[System.Serializable]
public struct References
{
public TMP_Text Label;
}
#region Fields
[SerializeField] private References _references;
private Health _health;
#endregion
#region Unity Lifecycle
private void OnDestroy()
{
// Every subscription has its unsubscription
if (_health != null)
_health.OnChange -= HandleHealthChange;
}
#endregion
#region Public Methods
/// <summary>
/// Starts displaying a Health. Called by the UiManager.
/// </summary>
public void Bind(Health health)
{
_health = health;
_health.OnChange += HandleHealthChange;
HandleHealthChange(_health.Current, _health.Max);
}
#endregion
#region Private Methods
private void HandleHealthChange(int current, int max)
{
_references.Label.SetText("{0} / {1}", current, max);
}
#endregion
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: c96e24dd38a22b546a15f929ee0f0c91