feat: Player
This commit is contained in:
8
Assets/_Content/Data/Weapon.meta
Normal file
8
Assets/_Content/Data/Weapon.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7773c1d71eef8b3458b1f5d8870d968f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
20
Assets/_Content/Data/Weapon/WeaponData_Gun.asset
Normal file
20
Assets/_Content/Data/Weapon/WeaponData_Gun.asset
Normal 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
|
||||
8
Assets/_Content/Data/Weapon/WeaponData_Gun.asset.meta
Normal file
8
Assets/_Content/Data/Weapon/WeaponData_Gun.asset.meta
Normal 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
BIN
Assets/_Content/Models/Gun.fbx
LFS
Normal file
Binary file not shown.
110
Assets/_Content/Models/Gun.fbx.meta
Normal file
110
Assets/_Content/Models/Gun.fbx.meta
Normal 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:
|
||||
BIN
Assets/_Content/Models/Projectile.fbx
LFS
Normal file
BIN
Assets/_Content/Models/Projectile.fbx
LFS
Normal file
Binary file not shown.
110
Assets/_Content/Models/Projectile.fbx.meta
Normal file
110
Assets/_Content/Models/Projectile.fbx.meta
Normal 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:
|
||||
@@ -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}
|
||||
|
||||
148
Assets/_Content/Prefabs/Projectile.prefab
Normal file
148
Assets/_Content/Prefabs/Projectile.prefab
Normal 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
|
||||
7
Assets/_Content/Prefabs/Projectile.prefab.meta
Normal file
7
Assets/_Content/Prefabs/Projectile.prefab.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ab8f44a00f0019943847ff16fd95cdfd
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
@@ -1,13 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
[ExecuteAlways]
|
||||
public class CameraFollower : MonoBehaviour
|
||||
{
|
||||
public GameObject Player;
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (Player)
|
||||
transform.position = Player.transform.position;
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4ae4fbdc595247448b3d604825bd07fe
|
||||
8
Assets/_Content/Scripts/Characters.meta
Normal file
8
Assets/_Content/Scripts/Characters.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 00d5f0f5167a1a243a9972a98593b122
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
276
Assets/_Content/Scripts/Characters/Player.cs
Normal file
276
Assets/_Content/Scripts/Characters/Player.cs
Normal 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
|
||||
}
|
||||
}
|
||||
89
Assets/_Content/Scripts/Characters/PlayerCamera.cs
Normal file
89
Assets/_Content/Scripts/Characters/PlayerCamera.cs
Normal 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
|
||||
}
|
||||
}
|
||||
2
Assets/_Content/Scripts/Characters/PlayerCamera.cs.meta
Normal file
2
Assets/_Content/Scripts/Characters/PlayerCamera.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bd78e931d0126914e8206e9f6bb2b9de
|
||||
96
Assets/_Content/Scripts/Characters/PlayerEvent.cs
Normal file
96
Assets/_Content/Scripts/Characters/PlayerEvent.cs
Normal 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
|
||||
}
|
||||
}
|
||||
2
Assets/_Content/Scripts/Characters/PlayerEvent.cs.meta
Normal file
2
Assets/_Content/Scripts/Characters/PlayerEvent.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d3c874cb9bc4c364d87e100aada2b434
|
||||
8
Assets/_Content/Scripts/Combat.meta
Normal file
8
Assets/_Content/Scripts/Combat.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d5ab3689e81574b4c8d1b37201093edf
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
34
Assets/_Content/Scripts/Combat/AmmoEffect.cs
Normal file
34
Assets/_Content/Scripts/Combat/AmmoEffect.cs
Normal 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
|
||||
}
|
||||
}
|
||||
2
Assets/_Content/Scripts/Combat/AmmoEffect.cs.meta
Normal file
2
Assets/_Content/Scripts/Combat/AmmoEffect.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3831749972a75dc4dbe47f8a551785fc
|
||||
34
Assets/_Content/Scripts/Combat/HealEffect.cs
Normal file
34
Assets/_Content/Scripts/Combat/HealEffect.cs
Normal 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
|
||||
}
|
||||
}
|
||||
2
Assets/_Content/Scripts/Combat/HealEffect.cs.meta
Normal file
2
Assets/_Content/Scripts/Combat/HealEffect.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3b9353836241da04e9bb64cc87f89745
|
||||
83
Assets/_Content/Scripts/Combat/Health.cs
Normal file
83
Assets/_Content/Scripts/Combat/Health.cs
Normal 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
|
||||
}
|
||||
}
|
||||
2
Assets/_Content/Scripts/Combat/Health.cs.meta
Normal file
2
Assets/_Content/Scripts/Combat/Health.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 220d6096ae28c12449f72c38860cbc2e
|
||||
10
Assets/_Content/Scripts/Combat/IDamageable.cs
Normal file
10
Assets/_Content/Scripts/Combat/IDamageable.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
2
Assets/_Content/Scripts/Combat/IDamageable.cs.meta
Normal file
2
Assets/_Content/Scripts/Combat/IDamageable.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 14df4410feff3d044afb4ec552a18997
|
||||
68
Assets/_Content/Scripts/Combat/Projectile.cs
Normal file
68
Assets/_Content/Scripts/Combat/Projectile.cs
Normal 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
|
||||
}
|
||||
}
|
||||
2
Assets/_Content/Scripts/Combat/Projectile.cs.meta
Normal file
2
Assets/_Content/Scripts/Combat/Projectile.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7671f358930703f4683397845e17e460
|
||||
107
Assets/_Content/Scripts/Combat/ProjectileLauncher.cs
Normal file
107
Assets/_Content/Scripts/Combat/ProjectileLauncher.cs
Normal 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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1a1a8c56cfabcd648a0967ce7acc5ed3
|
||||
68
Assets/_Content/Scripts/Combat/UiManager.cs
Normal file
68
Assets/_Content/Scripts/Combat/UiManager.cs
Normal 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
|
||||
}
|
||||
}
|
||||
2
Assets/_Content/Scripts/Combat/UiManager.cs.meta
Normal file
2
Assets/_Content/Scripts/Combat/UiManager.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4c6cb5ac8e4f8d0479afda241378ff0b
|
||||
32
Assets/_Content/Scripts/Combat/WeaponData.cs
Normal file
32
Assets/_Content/Scripts/Combat/WeaponData.cs
Normal 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
|
||||
}
|
||||
}
|
||||
2
Assets/_Content/Scripts/Combat/WeaponData.cs.meta
Normal file
2
Assets/_Content/Scripts/Combat/WeaponData.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b4a4852c6f394a441935fae7b9f9ec82
|
||||
@@ -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
|
||||
|
||||
|
||||
}
|
||||
8
Assets/_Content/Scripts/UI.meta
Normal file
8
Assets/_Content/Scripts/UI.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e11b6fbe420e7b94b8000b7e9c608900
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
59
Assets/_Content/Scripts/UI/AmmoView.cs
Normal file
59
Assets/_Content/Scripts/UI/AmmoView.cs
Normal 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
|
||||
}
|
||||
}
|
||||
2
Assets/_Content/Scripts/UI/AmmoView.cs.meta
Normal file
2
Assets/_Content/Scripts/UI/AmmoView.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ca9ade34ced9c264fad512c9408d61d8
|
||||
33
Assets/_Content/Scripts/UI/GameOverView.cs
Normal file
33
Assets/_Content/Scripts/UI/GameOverView.cs
Normal 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
|
||||
}
|
||||
}
|
||||
2
Assets/_Content/Scripts/UI/GameOverView.cs.meta
Normal file
2
Assets/_Content/Scripts/UI/GameOverView.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 78d77256975d6d7499a20292c00b0649
|
||||
60
Assets/_Content/Scripts/UI/HealthView.cs
Normal file
60
Assets/_Content/Scripts/UI/HealthView.cs
Normal 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
|
||||
}
|
||||
}
|
||||
2
Assets/_Content/Scripts/UI/HealthView.cs.meta
Normal file
2
Assets/_Content/Scripts/UI/HealthView.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c96e24dd38a22b546a15f929ee0f0c91
|
||||
Reference in New Issue
Block a user