From a7e8ef1a1f3734ae3069b947ce92d73f4face811 Mon Sep 17 00:00:00 2001 From: Alexandre Coirier Date: Thu, 8 Oct 2026 15:12:19 +0200 Subject: [PATCH] feat: Player & Camera --- Assets/_Content/Models/Gun.fbx | 3 + Assets/_Content/Models/Gun.fbx.meta | 110 ++++++++++++++ Assets/_Content/Models/Projectile.fbx | 3 + Assets/_Content/Models/Projectile.fbx.meta | 110 ++++++++++++++ Assets/_Content/Scenes/SampleScene.unity | 4 +- Assets/_Content/Scripts/CameraFollower.cs | 13 -- .../_Content/Scripts/CameraFollower.cs.meta | 2 - Assets/_Content/Scripts/Characters.meta | 8 + Assets/_Content/Scripts/Characters/Player.cs | 140 ++++++++++++++++++ .../Player.cs.meta} | 0 .../Scripts/Characters/PlayerCamera.cs | 75 ++++++++++ .../Scripts/Characters/PlayerCamera.cs.meta | 2 + .../Scripts/Characters/PlayerEvent.cs | 16 ++ .../Scripts/Characters/PlayerEvent.cs.meta | 2 + Assets/_Content/Scripts/Combat.meta | 8 + Assets/_Content/Scripts/Combat/Health.cs | 83 +++++++++++ Assets/_Content/Scripts/Combat/Health.cs.meta | 2 + Assets/_Content/Scripts/Combat/IDamageable.cs | 10 ++ .../Scripts/Combat/IDamageable.cs.meta | 2 + Assets/_Content/Scripts/PlayerMover.cs | 53 ------- 20 files changed, 576 insertions(+), 70 deletions(-) create mode 100644 Assets/_Content/Models/Gun.fbx create mode 100644 Assets/_Content/Models/Gun.fbx.meta create mode 100644 Assets/_Content/Models/Projectile.fbx create mode 100644 Assets/_Content/Models/Projectile.fbx.meta delete mode 100644 Assets/_Content/Scripts/CameraFollower.cs delete mode 100644 Assets/_Content/Scripts/CameraFollower.cs.meta create mode 100644 Assets/_Content/Scripts/Characters.meta create mode 100644 Assets/_Content/Scripts/Characters/Player.cs rename Assets/_Content/Scripts/{PlayerMover.cs.meta => Characters/Player.cs.meta} (100%) create mode 100644 Assets/_Content/Scripts/Characters/PlayerCamera.cs create mode 100644 Assets/_Content/Scripts/Characters/PlayerCamera.cs.meta create mode 100644 Assets/_Content/Scripts/Characters/PlayerEvent.cs create mode 100644 Assets/_Content/Scripts/Characters/PlayerEvent.cs.meta create mode 100644 Assets/_Content/Scripts/Combat.meta create mode 100644 Assets/_Content/Scripts/Combat/Health.cs create mode 100644 Assets/_Content/Scripts/Combat/Health.cs.meta create mode 100644 Assets/_Content/Scripts/Combat/IDamageable.cs create mode 100644 Assets/_Content/Scripts/Combat/IDamageable.cs.meta delete mode 100644 Assets/_Content/Scripts/PlayerMover.cs diff --git a/Assets/_Content/Models/Gun.fbx b/Assets/_Content/Models/Gun.fbx new file mode 100644 index 0000000..658ad46 --- /dev/null +++ b/Assets/_Content/Models/Gun.fbx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:840c484baff5f480cc4432726770198dd5752db548b7fa9aaee8d6b7d4734eb3 +size 16716 diff --git a/Assets/_Content/Models/Gun.fbx.meta b/Assets/_Content/Models/Gun.fbx.meta new file mode 100644 index 0000000..d60cb3f --- /dev/null +++ b/Assets/_Content/Models/Gun.fbx.meta @@ -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: diff --git a/Assets/_Content/Models/Projectile.fbx b/Assets/_Content/Models/Projectile.fbx new file mode 100644 index 0000000..168d3b5 --- /dev/null +++ b/Assets/_Content/Models/Projectile.fbx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:890af87fbd01bae150144343d530b73aa4c6eda3ff3ff56fffcdb69bd02f1540 +size 16108 diff --git a/Assets/_Content/Models/Projectile.fbx.meta b/Assets/_Content/Models/Projectile.fbx.meta new file mode 100644 index 0000000..0f064ec --- /dev/null +++ b/Assets/_Content/Models/Projectile.fbx.meta @@ -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: diff --git a/Assets/_Content/Scenes/SampleScene.unity b/Assets/_Content/Scenes/SampleScene.unity index f2ceb8c..be7633e 100644 --- a/Assets/_Content/Scenes/SampleScene.unity +++ b/Assets/_Content/Scenes/SampleScene.unity @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d7308cb7ab832f786810414a0de37ddafc469ca50dc16d5af2d312d79df4d2a5 -size 21305 +oid sha256:0c2e903027e23f2dd1493fa5a1501abafc8de635728a7b86bfca5c4f0a34911f +size 26740 diff --git a/Assets/_Content/Scripts/CameraFollower.cs b/Assets/_Content/Scripts/CameraFollower.cs deleted file mode 100644 index 2c0c22a..0000000 --- a/Assets/_Content/Scripts/CameraFollower.cs +++ /dev/null @@ -1,13 +0,0 @@ -using UnityEngine; - -[ExecuteAlways] -public class CameraFollower : MonoBehaviour -{ - public GameObject Player; - - void Update() - { - if (Player) - transform.position = Player.transform.position; - } -} diff --git a/Assets/_Content/Scripts/CameraFollower.cs.meta b/Assets/_Content/Scripts/CameraFollower.cs.meta deleted file mode 100644 index a54b07e..0000000 --- a/Assets/_Content/Scripts/CameraFollower.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 4ae4fbdc595247448b3d604825bd07fe \ No newline at end of file diff --git a/Assets/_Content/Scripts/Characters.meta b/Assets/_Content/Scripts/Characters.meta new file mode 100644 index 0000000..e8ceff7 --- /dev/null +++ b/Assets/_Content/Scripts/Characters.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 00d5f0f5167a1a243a9972a98593b122 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/_Content/Scripts/Characters/Player.cs b/Assets/_Content/Scripts/Characters/Player.cs new file mode 100644 index 0000000..ee1649a --- /dev/null +++ b/Assets/_Content/Scripts/Characters/Player.cs @@ -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(); + } + + 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 + + + } +} \ No newline at end of file diff --git a/Assets/_Content/Scripts/PlayerMover.cs.meta b/Assets/_Content/Scripts/Characters/Player.cs.meta similarity index 100% rename from Assets/_Content/Scripts/PlayerMover.cs.meta rename to Assets/_Content/Scripts/Characters/Player.cs.meta diff --git a/Assets/_Content/Scripts/Characters/PlayerCamera.cs b/Assets/_Content/Scripts/Characters/PlayerCamera.cs new file mode 100644 index 0000000..f90a8cb --- /dev/null +++ b/Assets/_Content/Scripts/Characters/PlayerCamera.cs @@ -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(); + + 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; + } + } +} \ No newline at end of file diff --git a/Assets/_Content/Scripts/Characters/PlayerCamera.cs.meta b/Assets/_Content/Scripts/Characters/PlayerCamera.cs.meta new file mode 100644 index 0000000..8c07fab --- /dev/null +++ b/Assets/_Content/Scripts/Characters/PlayerCamera.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: bd78e931d0126914e8206e9f6bb2b9de \ No newline at end of file diff --git a/Assets/_Content/Scripts/Characters/PlayerEvent.cs b/Assets/_Content/Scripts/Characters/PlayerEvent.cs new file mode 100644 index 0000000..7b30cb5 --- /dev/null +++ b/Assets/_Content/Scripts/Characters/PlayerEvent.cs @@ -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() + { + + } +} diff --git a/Assets/_Content/Scripts/Characters/PlayerEvent.cs.meta b/Assets/_Content/Scripts/Characters/PlayerEvent.cs.meta new file mode 100644 index 0000000..5ad767d --- /dev/null +++ b/Assets/_Content/Scripts/Characters/PlayerEvent.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: d3c874cb9bc4c364d87e100aada2b434 \ No newline at end of file diff --git a/Assets/_Content/Scripts/Combat.meta b/Assets/_Content/Scripts/Combat.meta new file mode 100644 index 0000000..251db50 --- /dev/null +++ b/Assets/_Content/Scripts/Combat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d5ab3689e81574b4c8d1b37201093edf +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/_Content/Scripts/Combat/Health.cs b/Assets/_Content/Scripts/Combat/Health.cs new file mode 100644 index 0000000..98be4ad --- /dev/null +++ b/Assets/_Content/Scripts/Combat/Health.cs @@ -0,0 +1,83 @@ +using System; +using UnityEngine; + +namespace Arena.Combat +{ + /// + /// Hit points of an entity. Serialized inside the component that owns it (Player, Enemy), + /// which calls Initialize in its Awake. + /// + [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; + + /// + /// Raised with the current and max hit points each time they change. + /// + public event Action OnChange; + + /// + /// Raised once, when the hit points reach zero. + /// + public event Action OnDied; + + public int Current => _current; + public bool IsDead => _current <= 0; + + #endregion + + #region Public Methods + + /// + /// Fills the hit points. Called by the owner in its Awake. + /// + public void Initialize() + { + SetCurrent(Max); + } + + /// + /// Removes hit points and raises OnDied the first time they reach zero. + /// + public void TakeDamage(int amount) + { + if (IsDead || amount <= 0) + return; + + SetCurrent(_current - amount); + + if (IsDead) + OnDied?.Invoke(); + } + + /// + /// Gives hit points back without exceeding Max. Has no effect once dead. + /// + 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 + } +} \ No newline at end of file diff --git a/Assets/_Content/Scripts/Combat/Health.cs.meta b/Assets/_Content/Scripts/Combat/Health.cs.meta new file mode 100644 index 0000000..7767857 --- /dev/null +++ b/Assets/_Content/Scripts/Combat/Health.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 220d6096ae28c12449f72c38860cbc2e \ No newline at end of file diff --git a/Assets/_Content/Scripts/Combat/IDamageable.cs b/Assets/_Content/Scripts/Combat/IDamageable.cs new file mode 100644 index 0000000..187f4b7 --- /dev/null +++ b/Assets/_Content/Scripts/Combat/IDamageable.cs @@ -0,0 +1,10 @@ +namespace Arena.Combat +{ + /// + /// Anything that can receive damage: player, enemy, destructible object. + /// + public interface IDamageable + { + void TakeDamage(int amount); + } +} \ No newline at end of file diff --git a/Assets/_Content/Scripts/Combat/IDamageable.cs.meta b/Assets/_Content/Scripts/Combat/IDamageable.cs.meta new file mode 100644 index 0000000..734341b --- /dev/null +++ b/Assets/_Content/Scripts/Combat/IDamageable.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 14df4410feff3d044afb4ec552a18997 \ No newline at end of file diff --git a/Assets/_Content/Scripts/PlayerMover.cs b/Assets/_Content/Scripts/PlayerMover.cs deleted file mode 100644 index 0a4cd08..0000000 --- a/Assets/_Content/Scripts/PlayerMover.cs +++ /dev/null @@ -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 - - -} \ No newline at end of file