feat: Player & Camera
This commit is contained in:
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: 0e4d319eaf75fc24dac24e27d167ce9a
|
||||||
|
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: 1
|
||||||
|
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: 0c0ea1e86f9450642966454d2baaebee
|
||||||
|
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: 1
|
||||||
|
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.
@@ -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:
|
||||||
140
Assets/_Content/Scripts/Characters/Player.cs
Normal file
140
Assets/_Content/Scripts/Characters/Player.cs
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
using Arena.Combat;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.InputSystem;
|
||||||
|
|
||||||
|
namespace Arena.Characters
|
||||||
|
{
|
||||||
|
public class Player : MonoBehaviour, IDamageable
|
||||||
|
{
|
||||||
|
[System.Serializable]
|
||||||
|
private class Settings
|
||||||
|
{
|
||||||
|
[Tooltip("Movement speed, in km/h.")]
|
||||||
|
public float Speed = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
[System.Serializable]
|
||||||
|
private struct References
|
||||||
|
{
|
||||||
|
public CharacterController Controller;
|
||||||
|
public InputActionReference MoveAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
[System.Serializable]
|
||||||
|
public class StateContainer
|
||||||
|
{
|
||||||
|
public bool IsMoving = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region FIELDS
|
||||||
|
|
||||||
|
public static Player Instance { get; private set; }
|
||||||
|
|
||||||
|
const float KMH_TO_MS = 1 / 3.6f;
|
||||||
|
|
||||||
|
[SerializeField] private Settings _settings;
|
||||||
|
[SerializeField] private References _references;
|
||||||
|
[SerializeField] private StateContainer _state;
|
||||||
|
[SerializeField] private Health _health;
|
||||||
|
|
||||||
|
public StateContainer State => _state;
|
||||||
|
|
||||||
|
private Vector2 _moveInput;
|
||||||
|
private Camera _camera;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region UNITY LIFECYCLES
|
||||||
|
|
||||||
|
void Awake()
|
||||||
|
{
|
||||||
|
if (Instance && Instance != this)
|
||||||
|
{
|
||||||
|
Debug.LogWarning($"A second Player was found on {name}, it is destroyed.");
|
||||||
|
Destroy(gameObject);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Instance = this;
|
||||||
|
|
||||||
|
_health.Initialize();
|
||||||
|
|
||||||
|
_camera = Camera.main;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnEnable()
|
||||||
|
{
|
||||||
|
_references.MoveAction.action.Enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnDisable()
|
||||||
|
{
|
||||||
|
if (Instance == this)
|
||||||
|
_references.MoveAction.action.Disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnDestroy()
|
||||||
|
{
|
||||||
|
if (Instance == this)
|
||||||
|
Instance = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Update()
|
||||||
|
{
|
||||||
|
if (_health.IsDead)
|
||||||
|
return;
|
||||||
|
|
||||||
|
float t = Time.deltaTime;
|
||||||
|
|
||||||
|
GetInputs();
|
||||||
|
Move(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Public Methods
|
||||||
|
|
||||||
|
public void TakeDamage(int amount)
|
||||||
|
{
|
||||||
|
_health.TakeDamage(amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Private Methods
|
||||||
|
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
[ContextMenu("Debug/Take 25 Damage")]
|
||||||
|
private void DebugTakeDamage()
|
||||||
|
{
|
||||||
|
TakeDamage(25);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private void GetInputs()
|
||||||
|
{
|
||||||
|
_moveInput = _references.MoveAction.action.ReadValue<Vector2>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Move(float t)
|
||||||
|
{
|
||||||
|
Vector3 direction = ToWorldDirection(_moveInput);
|
||||||
|
Vector3 velocity = direction * KMH_TO_MS * _settings.Speed;
|
||||||
|
|
||||||
|
_state.IsMoving = velocity.sqrMagnitude > .01f;
|
||||||
|
|
||||||
|
_references.Controller.Move(velocity * t);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
75
Assets/_Content/Scripts/Characters/PlayerCamera.cs
Normal file
75
Assets/_Content/Scripts/Characters/PlayerCamera.cs
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.InputSystem;
|
||||||
|
|
||||||
|
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(7f, 8f);
|
||||||
|
|
||||||
|
[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]
|
||||||
|
private struct References
|
||||||
|
{
|
||||||
|
public Player Player;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region FIELDS
|
||||||
|
|
||||||
|
[SerializeField] private Settings _settings;
|
||||||
|
[SerializeField] private References _references;
|
||||||
|
|
||||||
|
private Vector3 _velocity;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
void Update()
|
||||||
|
{
|
||||||
|
if (!GetPlayer())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Vector3 targetPos = GetTargetPosition();
|
||||||
|
|
||||||
|
if (!Application.isPlaying || _settings.Smooth == 0)
|
||||||
|
{
|
||||||
|
transform.position = targetPos;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
transform.position = Vector3.SmoothDamp(transform.position, targetPos, ref _velocity, _settings.Smooth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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(0, _settings.Angle, 0);
|
||||||
|
Vector3 offset = rotation * new Vector3(0, _settings.Offset.y, -_settings.Offset.x);
|
||||||
|
return _references.Player.transform.position + offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
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
|
||||||
16
Assets/_Content/Scripts/Characters/PlayerEvent.cs
Normal file
16
Assets/_Content/Scripts/Characters/PlayerEvent.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
public class PlayerEvent : MonoBehaviour
|
||||||
|
{
|
||||||
|
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
||||||
|
void Start()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update is called once per frame
|
||||||
|
void Update()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
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:
|
||||||
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
|
||||||
@@ -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
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user