Платформер враги, инфраструктура, герой

This commit is contained in:
ThomasCharester committed 2026-03-09 16:28:40 +03:00
1 parent 28125eb382
commit 93819c1dd3
61 files changed
+1463 -423

No files matched your search

@@ -13,14 +13,15 @@ namespace Code.Example.Platformer.Entity.Enemies
protected override void Move()
{
if (_target)
{
_directionRight = (transform.position - _target.position).magnitude < float.Epsilon;
_directionRight = ((_target.position - transform.position)).x > float.Epsilon;
UnityEngine.Debug.DrawLine(transform.position, (transform.position + (_target.position - transform.position)), Color.salmon);
CheckupDirection();
rigidbody2D.linearVelocityX = _directionRight ? 0.5f : -0.5f;
rigidbody2D.linearVelocity *= _acceleration;
rigidbody2D.linearVelocityX *= _acceleration;
}
else
{
@@ -14,6 +14,15 @@ namespace Code.Example.Platformer.Entity
[SerializeField] protected Animator animator;
[SerializeField] protected SpriteRenderer spriteRenderer;
[SerializeField] private Vector2 groundPoint;
private EntityHealth _health;
private PlatformerEntityData _data;
public void SetData(PlatformerEntityData data)
{
_data = data;
_health = new(data.maxHealth);
}
protected bool onGround;
@@ -29,7 +38,9 @@ namespace Code.Example.Platformer.Entity
{
onGround = CheckGround();
animator.SetBool(OnGround, onGround);
Move();
if(rigidbody2D.linearVelocity.x is > 0.01f or < -0.01f) HandleFlipX();
}
@@ -40,5 +51,7 @@ namespace Code.Example.Platformer.Entity
}
protected abstract void Move();
public virtual void GetDamage(int damage) => _health.GiveDamage(damage);
}
}
@@ -0,0 +1,27 @@
namespace Code.Example.Platformer.Entity
{
public class EntityHealth
{
private int _health, _maxHealth;
public bool IsDead { get; private set; }
public EntityHealth(int initialHealth)
{
_health = initialHealth;
}
public void GiveDamage(int damage)
{
_health -= damage;
if(_health <= 0) IsDead = true;
}
public void Heal(int heal)
{
if (IsDead) return;
if (_health + heal > _maxHealth) _health = _maxHealth;
else _health += heal;
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a3078030faef42b5bddd46a7c5c91d95
timeCreated: 1773058870
@@ -1,32 +1,115 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Code.Infrastructure.Configs;
using Code.Infrastructure.EventBus;
using Code.Infrastructure.Generators;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
namespace Code.Example.Platformer.Entity
{
[Config("Configs/Gameplay/Platformer/EnemySettings", true)]
public class PlatformerEnemySettings
[Config("Configs/Gameplay/Platformer/EntitySettings", true)]
public class PlatformerEntitySettings
{
[ToConfig] public PlatformerEnemyData racerData;
[ToConfig] public PlatformerEntityData EntityData;
[ToConfig] public AssetReference prefabReference;
}
[Serializable]
public struct PlatformerEnemyData
public struct PlatformerEntityData
{
public string name;
public float speed;
public float acceleration;
public int damage;
public PlatformerEnemyType type;
public PlatformerEntityType type;
public int maxHealth;
}
public enum PlatformerEnemyType
public enum PlatformerEntityType
{
Dummy
Player,
Boar,
Bee,
Snail
}
public class PlatformerEnemyFactory
{
private EventBus _eventBus;
private string _enemyConfigsLabel;
private AsyncOperationHandle<IList<PlatformerEntitySettingsConfig>> _enemyConfigsHandle;
private Dictionary<PlatformerEntityType, AsyncOperationHandle<GameObject>> _enemyPrefabsHandle = new();
private Dictionary<PlatformerEntityType, PlatformerEntitySettingsConfig> _enemyConfigs;
public PlatformerEnemyFactory(IConfigLocator configLocator, EventBus eventBus)
{
_eventBus = eventBus;
_enemyConfigsLabel = configLocator.TryGetManyConfigAssetReferences<PlatformerEntitySettingsConfig>();
LoadConfigs().Forget();
}
private async UniTaskVoid LoadConfigs()
{
_enemyConfigsHandle = Addressables.LoadAssetsAsync<PlatformerEntitySettingsConfig>(_enemyConfigsLabel);
await _enemyConfigsHandle.ToUniTask();
_enemyConfigs = _enemyConfigsHandle.Result.ToDictionary(x => x.racerData.type);
_enemyConfigs.Remove(PlatformerEntityType.Player);
_eventBus.RaiseEvent<IPlatformerFactoryInitializedHandle>(x => x.PlatformerFactoryInitialized());
}
public async UniTaskVoid LoadRacer(PlatformerEntityType racerType)
{
if (racerType == PlatformerEntityType.Player) return;
if (_enemyPrefabsHandle.ContainsKey(racerType))
{
_eventBus.RaiseEvent<IPlatformerEnemyLoadedHandle>(x => x.PlatformerEnemyLoaded(racerType, null));
return;
}
UnityEngine.Debug.LogWarning($"Racer loaded {racerType}");
_enemyPrefabsHandle.Add(racerType,
Addressables.LoadAssetAsync<GameObject>(_enemyConfigs[racerType].prefabReference));
await _enemyPrefabsHandle[racerType].ToUniTask();
var racer = _enemyPrefabsHandle[racerType].Result.GetComponent<Entity>();
racer.SetData(_enemyConfigs[racerType].racerData);
_eventBus.RaiseEvent<IPlatformerEnemyLoadedHandle>(x => x.PlatformerEnemyLoaded(racerType, racer));
}
public void ReleaseRacer(PlatformerEntityType racerType)
{
_enemyPrefabsHandle[racerType].Release();
_enemyPrefabsHandle.Remove(racerType);
}
public void Dispose()
{
UnityEngine.Debug.LogWarning($"Racers released");
foreach (var prefab in _enemyPrefabsHandle)
prefab.Value.Release();
_enemyPrefabsHandle.Clear();
_enemyConfigsHandle.Release();
}
}
public interface IPlatformerFactoryInitializedHandle : IGlobalSubscriber
{
public void PlatformerFactoryInitialized();
}
public interface IPlatformerEnemyLoadedHandle : IGlobalSubscriber
{
public void PlatformerEnemyLoaded(PlatformerEntityType type, Entity entity);
}
}
@@ -1,4 +1,6 @@
using System;
using Code.Infrastructure.Audio;
using Code.Infrastructure.Camera;
using Code.Infrastructure.Configs;
using Code.Infrastructure.Input;
using Reflex.Attributes;
using UnityEngine;
@@ -8,34 +10,48 @@ namespace Code.Example.Platformer.Entity
{
public class PlayerEntity : Entity
{
private static readonly int OnAttack = Animator.StringToHash("OnAttack");
private IInputService _inputService;
[Inject]
private void Construct(IInputService inputService)
private void Construct(IInputService inputService, IAudioService audioService)
{
_audioService = audioService;
_inputService = inputService;
_inputService.BindActionPerformed((int)ActionMappings.Gameplay, (int)GameplayActions.Move,
_inputService.BindActionPerformed((int)ActionMappings.Platformer, (int)PlatformerActions.Move,
MovementPerformed);
_inputService.BindActionCancelled((int)ActionMappings.Gameplay, (int)GameplayActions.Move,
_inputService.BindActionCancelled((int)ActionMappings.Platformer, (int)PlatformerActions.Move,
MovementCancelled);
_inputService.BindActionPerformed((int)ActionMappings.Gameplay, (int)GameplayActions.Brake, JumpPerformed);
_inputService.BindActionPerformed((int)ActionMappings.Platformer, (int)PlatformerActions.Jump, JumpPerformed);
_inputService.BindActionPerformed((int)ActionMappings.Platformer, (int)PlatformerActions.Attack, AttackPerformed);
_inputService.BindActionPerformed((int)ActionMappings.Platformer, (int)PlatformerActions.Sprint, SprintPerformed);
_inputService.BindActionCancelled((int)ActionMappings.Platformer, (int)PlatformerActions.Sprint, SprintCancelled);
//cameraFactory.GetCinematicCamera(CameraMode.Platformer).Follow = transform; , CameraFactory cameraFactory
}
private void OnDestroy()
{
_inputService.UnbindActionPerformed((int)ActionMappings.Gameplay, (int)GameplayActions.Move,
_inputService.UnbindActionPerformed((int)ActionMappings.Platformer, (int)PlatformerActions.Move,
MovementPerformed);
_inputService.UnbindActionCancelled((int)ActionMappings.Gameplay, (int)GameplayActions.Move,
_inputService.UnbindActionCancelled((int)ActionMappings.Platformer, (int)PlatformerActions.Move,
MovementCancelled);
_inputService.UnbindActionPerformed((int)ActionMappings.Gameplay, (int)GameplayActions.Brake, JumpPerformed);
_inputService.UnbindActionPerformed((int)ActionMappings.Platformer, (int)PlatformerActions.Jump, JumpPerformed);
_inputService.UnbindActionPerformed((int)ActionMappings.Platformer, (int)PlatformerActions.Attack, AttackPerformed);
_inputService.UnbindActionPerformed((int)ActionMappings.Platformer, (int)PlatformerActions.Sprint, SprintPerformed);
_inputService.UnbindActionCancelled((int)ActionMappings.Platformer, (int)PlatformerActions.Sprint, SprintCancelled);
}
private float _acceleration = 1f;
protected override void Move()
{
rigidbody2D.linearVelocityX = _moveDirection.x * 5f;
rigidbody2D.linearVelocityX = _moveDirection.x * 2f * _acceleration;
}
private Vector2 _moveDirection;
private IAudioService _audioService;
private void MovementPerformed(InputAction.CallbackContext callbackContext) =>
_moveDirection = callbackContext.ReadValue<Vector2>();
@@ -46,7 +62,48 @@ namespace Code.Example.Platformer.Entity
private void JumpPerformed(InputAction.CallbackContext callbackContext)
{
if (!onGround) return;
rigidbody2D.AddForceY(100f);
rigidbody2D.AddForceY(150f);
_acceleration = 1f;
}
[SerializeField] private Vector2 attackOffset;
private void AttackPerformed(InputAction.CallbackContext callbackContext)
{
if (!onGround) return;
//
//
_audioService.PlayOneShot(AudioNames.UISounds, 1);
animator.SetBool(OnAttack, true);
}
public void CastAttack()
{
var damagedOnes =
Physics2D.OverlapPointAll((Vector2)transform.position + attackOffset, LayerMasks.Masks[LayerMaskType.PlatformerEnemy]);
if (damagedOnes == null) return;
foreach (var damaged in damagedOnes)
{
damaged.gameObject.GetComponent<Entity>().GetDamage(1);
_audioService.PlayOneShot(AudioNames.UISounds, 2);
}
}
private void SprintPerformed(InputAction.CallbackContext callbackContext)
{
if (!onGround) return;
//
_acceleration = 3f;
}
private void SprintCancelled(InputAction.CallbackContext callbackContext)
{
_acceleration = 1f;
}
public void AttackEnd() => animator.SetBool(OnAttack, false);
}
}
@@ -30,7 +30,7 @@ namespace Code.Example.Platformer
Context.UIService.OpenPanel(UIPanelType.Loading);
Context.SceneLoader.LoadSceneAsync(SceneId.Platformer, LoadSceneMode.Single).Forget();
Context.InputService.EnableMap(ActionMappings.Gameplay);
Context.InputService.EnableMap(ActionMappings.Platformer);
Context.CameraFactory.LoadCinemachineCamera(CameraMode.Platformer).Forget();
}
private Loading _loading;
@@ -45,7 +45,7 @@ namespace Code.Example.Platformer
protected override void OnExitState()
{
Context.CameraFactory.ReleaseCinemachineCamera(CameraMode.Platformer);
Context.InputService.DisableMap(ActionMappings.Gameplay);
Context.InputService.DisableMap(ActionMappings.Platformer);
EventBus.Unsubscribe(this);
}
@@ -15,10 +15,10 @@ namespace Code.Example.Race.Racer.Player
public void Construct(IInputService inputService)
{
_inputService = inputService;
_inputService.BindActionPerformed((int)ActionMappings.Gameplay, (int)GameplayActions.Move, MovementPerformed);
_inputService.BindActionCancelled((int)ActionMappings.Gameplay, (int)GameplayActions.Move, MovementEnded);
_inputService.BindActionPerformed((int)ActionMappings.Gameplay, (int)GameplayActions.Brake, BrakePerformed);
_inputService.BindActionCancelled((int)ActionMappings.Gameplay, (int)GameplayActions.Brake, BrakeEnded);
_inputService.BindActionPerformed((int)ActionMappings.Race, (int)RaceActions.Move, MovementPerformed);
_inputService.BindActionCancelled((int)ActionMappings.Race, (int)RaceActions.Move, MovementEnded);
_inputService.BindActionPerformed((int)ActionMappings.Race, (int)RaceActions.Brake, BrakePerformed);
_inputService.BindActionCancelled((int)ActionMappings.Race, (int)RaceActions.Brake, BrakeEnded);
}
private void MovementPerformed(InputAction.CallbackContext context) => MovementInput = context.ReadValue<Vector2>();
@@ -32,10 +32,10 @@ namespace Code.Example.Race.Racer.Player
private void OnDestroy()
{
if (_inputService == null) return;
_inputService.UnbindActionPerformed((int)ActionMappings.Gameplay, (int)GameplayActions.Move, MovementPerformed);
_inputService.UnbindActionCancelled((int)ActionMappings.Gameplay, (int)GameplayActions.Move, MovementEnded);
_inputService.UnbindActionPerformed((int)ActionMappings.Gameplay, (int)GameplayActions.Brake, BrakePerformed);
_inputService.UnbindActionCancelled((int)ActionMappings.Gameplay, (int)GameplayActions.Brake, BrakeEnded);
_inputService.UnbindActionPerformed((int)ActionMappings.Race, (int)RaceActions.Move, MovementPerformed);
_inputService.UnbindActionCancelled((int)ActionMappings.Race, (int)RaceActions.Move, MovementEnded);
_inputService.UnbindActionPerformed((int)ActionMappings.Race, (int)RaceActions.Brake, BrakePerformed);
_inputService.UnbindActionCancelled((int)ActionMappings.Race, (int)RaceActions.Brake, BrakeEnded);
}
}
}
@@ -8,7 +8,7 @@ using UnityEngine;
namespace Code.Example.Race.UI
{
public class PlayerScoreCounter : UIPanel, IScoreChangedHandle
public partial class PlayerScoreCounter : UIPanel, IScoreChangedHandle
{
[SerializeField] private TMP_Text playerScore;
private EventBus _eventBus;
+1 -1
View File
@@ -8,7 +8,7 @@ using UnityEngine.UI;
namespace Code.Example.Race.UI
{
public class PlayerScores : UIPanel
public partial class PlayerScores : UIPanel
{
[SerializeField] private Image image;
[SerializeField] private TMP_Text scoreText;
+1 -1
View File
@@ -7,7 +7,7 @@ using UnityEngine.UI;
namespace Code.Example.Race.UI
{
public class WinScreen : UIPanel
public partial class WinScreen : UIPanel
{
[SerializeField] private Image image;
[SerializeField] private TMP_Text winText;