feat: add state machine

This commit is contained in:
Bragin Stepan
2026-03-02 19:00:06 +05:00
parent 99c88c071f
commit 7737ee3158
50 changed files with 828 additions and 128 deletions

View File

@@ -31,11 +31,11 @@ namespace _Project.Develop.Runtime.Entities
_monoEntitiesFactory = container.Resolve<MonoEntitiesFactory>();
_playerInput = container.Resolve<IPlayerInput>();
}
public Entity CreateHero(Vector3 position)
{
Entity entity = CreateEmpty();
_monoEntitiesFactory.Create(entity, position, PathToResources.Entity.Hero);
entity
@@ -65,29 +65,29 @@ namespace _Project.Develop.Runtime.Entities
.AddAttackCooldownInitialTime()
.AddAttackCooldownCurrentTime()
.AddInAttackCooldown();
ICompositeCondition canMove = new CompositeCondition()
.Add(new FuncCondition(() => entity.IsDead.Value == false));
ICompositeCondition canRotate = new CompositeCondition()
.Add(new FuncCondition(() => entity.IsDead.Value == false));
ICompositeCondition mustDie = new CompositeCondition()
.Add(new FuncCondition(() => entity.CurrentHealth.Value <= 0));
ICompositeCondition mustSelfRelease = new CompositeCondition()
.Add(new FuncCondition(() => entity.IsDead.Value))
.Add(new FuncCondition(() => entity.InDeathProcess.Value == false));
ICompositeCondition canApplyDamage = new CompositeCondition()
.Add(new FuncCondition(() => entity.IsDead.Value == false));
ICompositeCondition canStartAttack = new CompositeCondition()
.Add(new FuncCondition(() => entity.IsDead.Value == false))
.Add(new FuncCondition(() => entity.InAttackProcess.Value == false))
.Add(new FuncCondition(() => entity.IsMoving.Value == false))
.Add(new FuncCondition(() => entity.InAttackCooldown.Value == false));
ICompositeCondition mustCancelAttack = new CompositeCondition(LogicOperationsUtils.Or)
.Add(new FuncCondition(() => entity.IsDead.Value))
.Add(new FuncCondition(() => entity.IsMoving.Value));
@@ -107,33 +107,33 @@ namespace _Project.Develop.Runtime.Entities
.AddSystem(new RotateDirectionByMoveInputSystem(_playerInput))
.AddSystem(new RigidbodyMovementSystem())
.AddSystem(new RigidbodyRotationSystem())
.AddSystem(new AttackCancelSystem())
.AddSystem(new StartAttackSystem())
.AddSystem(new ProcessAttackTimerSystem())
.AddSystem(new AttackDelayEndTriggerSystem())
.AddSystem(new InstantShootSystem(this))
.AddSystem(new EndAttackSystem())
.AddSystem(new AttackCooldownTimerSystem())
.AddSystem(new ApplyDamageSystem())
.AddSystem(new DeathSwitcherSystem())
.AddSystem(new DeathProcessTimerSystem())
.AddSystem(new DisableCollidersOnDeathSystem())
.AddSystem(new SelfReleaseSystem(_entitiesLifeContext));
_entitiesLifeContext.Add(entity);
return entity;
}
public Entity CreateGhost(Vector3 position)
{
Entity entity = CreateEmpty();
_monoEntitiesFactory.Create(entity, position, PathToResources.Entity.Ghost);
entity
@@ -154,20 +154,20 @@ namespace _Project.Develop.Runtime.Entities
.AddInDeathProcess()
.AddDeathProcessInitialTime(new ReactiveVariable<float>(2))
.AddDeathProcessCurrentTime();
ICompositeCondition canMove = new CompositeCondition()
.Add(new FuncCondition(() => entity.IsDead.Value == false));
ICompositeCondition canRotate = new CompositeCondition()
.Add(new FuncCondition(() => entity.IsDead.Value == false));
ICompositeCondition mustDie = new CompositeCondition()
.Add(new FuncCondition(() => entity.CurrentHealth.Value <= 0));
ICompositeCondition mustSelfRelease = new CompositeCondition()
.Add(new FuncCondition(() => entity.IsDead.Value))
.Add(new FuncCondition(() => entity.InDeathProcess.Value == false));
ICompositeCondition canApplyDamage = new CompositeCondition()
.Add(new FuncCondition(() => entity.IsDead.Value == false));
@@ -181,38 +181,38 @@ namespace _Project.Develop.Runtime.Entities
entity
.AddSystem(new RigidbodyMovementSystem())
.AddSystem(new RigidbodyRotationSystem())
.AddSystem(new BodyContactsDetectingSystem())
.AddSystem(new BodyContactsEntitiesFilterSystem(_collidersRegistryService))
.AddSystem(new DealDamageOnContactSystem())
.AddSystem(new ApplyDamageSystem())
.AddSystem(new DeathSwitcherSystem())
.AddSystem(new DeathProcessTimerSystem())
.AddSystem(new DisableCollidersOnDeathSystem())
.AddSystem(new SelfReleaseSystem(_entitiesLifeContext));
_entitiesLifeContext.Add(entity);
return entity;
}
public Entity CreateTeleportWizard(Vector3 position)
{
Entity entity = CreateEmpty();
_monoEntitiesFactory.Create(entity, position, PathToResources.Entity.Mage);
entity
.AddContactsDetectingMask(Layers.CharactersMask)
.AddContactCollidersBuffer(new Buffer<Collider>(32))
.AddContactEntitiesBuffer(new Buffer<Entity>(32))
.AddMaxHealth(new ReactiveVariable<float>(150))
.AddCurrentHealth(new ReactiveVariable<float>(150))
.AddTeleportTarget(entity.Transform)
.AddTeleportToPoint(entity.Transform)
.AddStartTeleportEvent()
@@ -221,14 +221,14 @@ namespace _Project.Develop.Runtime.Entities
.AddFindTeleportPointEvent()
.AddFindTeleportPointRequest()
.AddEndTeleportEvent()
.AddTeleportDamage(new ReactiveVariable<float>(50))
.AddTeleportDamageRadius(new ReactiveVariable<float>(6))
.AddTeleportDamageMask(Layers.CharactersMask)
.AddTeleportEnergyCost(new ReactiveVariable<int>(20))
.AddTeleportSearchRadius(new ReactiveVariable<float>(6))
.AddCurrentEnergy(new ReactiveVariable<int>(60))
.AddMaxEnergy(new ReactiveVariable<int>(60))
.AddUseEnergyEvent()
@@ -239,7 +239,7 @@ namespace _Project.Develop.Runtime.Entities
.AddIsAutoRegenEnergy(new ReactiveVariable<bool>(true))
.AddEnergyAutoRegenCurrentTime()
.AddEnergyAutoRegenInitialTime(new ReactiveVariable<float>(3))
.AddBodyContactDamage(new ReactiveVariable<float>(50))
.AddTakeDamageRequest()
.AddTakeDamageEvent()
@@ -247,24 +247,24 @@ namespace _Project.Develop.Runtime.Entities
.AddInDeathProcess()
.AddDeathProcessInitialTime(new ReactiveVariable<float>(2))
.AddDeathProcessCurrentTime();
ICompositeCondition canRegenEnergy = new CompositeCondition()
.Add(new FuncCondition(() => entity.IsDead.Value == false));
ICompositeCondition canUseEnergy = new CompositeCondition()
.Add(new FuncCondition(() => entity.IsDead.Value == false));
ICompositeCondition canStartTeleport = new CompositeCondition()
.Add(new FuncCondition(() => entity.IsDead.Value == false))
.Add(new FuncCondition(() => entity.CurrentEnergy.Value >= entity.TeleportEnergyCost.Value));
ICompositeCondition mustDie = new CompositeCondition()
.Add(new FuncCondition(() => entity.CurrentHealth.Value <= 0));
ICompositeCondition mustSelfRelease = new CompositeCondition()
.Add(new FuncCondition(() => entity.IsDead.Value))
.Add(new FuncCondition(() => entity.InDeathProcess.Value == false));
ICompositeCondition canApplyDamage = new CompositeCondition()
.Add(new FuncCondition(() => entity.IsDead.Value == false));
@@ -278,40 +278,40 @@ namespace _Project.Develop.Runtime.Entities
entity
.AddSystem(new TeleportByInputSystem(_playerInput))
// .AddSystem(new RegenEnergyByValueSystem())
.AddSystem(new RegenEnergyByPercentageSystem())
.AddSystem(new UseEnergySystem())
.AddSystem(new AutoRegenEnergyTimerSystem())
.AddSystem(new TeleportStartByEnergySystem())
.AddSystem(new TeleportProcessSystem())
.AddSystem(new FindRandomPointForTeleportSystem())
.AddSystem(new EndTeleportSystem())
.AddSystem(new InstantTeleportSystem())
.AddSystem(new DealDamageAfterTeleportSystem(_collidersRegistryService))
.AddSystem(new BodyContactsDetectingSystem())
.AddSystem(new BodyContactsEntitiesFilterSystem(_collidersRegistryService))
.AddSystem(new DealDamageOnContactSystem())
.AddSystem(new ApplyDamageSystem())
.AddSystem(new DeathSwitcherSystem())
.AddSystem(new DeathProcessTimerSystem())
.AddSystem(new DisableCollidersOnDeathSystem())
.AddSystem(new SelfReleaseSystem(_entitiesLifeContext));
_entitiesLifeContext.Add(entity);
return entity;
}
public Entity CreateProjectile(Vector3 position, Vector3 direction, float damage)
{
Entity entity = CreateEmpty();
_monoEntitiesFactory.Create(entity, position, PathToResources.Entity.Projectile);
entity
@@ -327,13 +327,13 @@ namespace _Project.Develop.Runtime.Entities
.AddIsMoving()
.AddDeathMask(Layers.CharactersMask | Layers.EnvironmentMask)
.AddIsTouchDeathMask();
ICompositeCondition canMove = new CompositeCondition()
.Add(new FuncCondition(() => entity.IsDead.Value == false));
ICompositeCondition canRotate = new CompositeCondition()
.Add(new FuncCondition(() => entity.IsDead.Value == false));
ICompositeCondition mustDie = new CompositeCondition()
.Add(new FuncCondition(() => entity.IsTouchDeathMask.Value));
@@ -349,19 +349,19 @@ namespace _Project.Develop.Runtime.Entities
entity
.AddSystem(new RigidbodyMovementSystem())
.AddSystem(new RigidbodyRotationSystem())
.AddSystem(new BodyContactsDetectingSystem())
.AddSystem(new BodyContactsEntitiesFilterSystem(_collidersRegistryService))
.AddSystem(new DealDamageOnContactSystem())
.AddSystem(new DeathMaskTouchDetectorSystem())
.AddSystem(new DeathSwitcherSystem())
.AddSystem(new DisableCollidersOnDeathSystem())
.AddSystem(new SelfReleaseSystem(_entitiesLifeContext));
_entitiesLifeContext.Add(entity);
return entity;
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d79e4112f0c64a90b05cae78e957a829
timeCreated: 1772454294

View File

@@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;
using _Project.Develop.Runtime.Entities;
namespace _Project.Develop.Runtime.Logic.Gameplay.Features.AI
{
public class AIBrainsContext : IDisposable
{
private readonly List<EntityToBrain> _entityToBrains = new ();
public void SetFor(Entity entity, IBrain brain)
{
foreach (EntityToBrain item in _entityToBrains)
{
if (item.Entity == entity)
{
item.Brain.Disable();
item.Brain.Dispose();
item.Brain = brain;
item.Brain.Enable();
return;
}
}
_entityToBrains.Add(new EntityToBrain(brain, entity));
brain.Enable();
}
public void Update(float deltaTime)
{
for (int i = 0; i < _entityToBrains.Count; i++)
{
if (_entityToBrains[i].Entity.IsInit == false)
{
int lastIndex = _entityToBrains.Count - 1;
_entityToBrains[i].Brain.Dispose();
_entityToBrains[i] = _entityToBrains[lastIndex];
_entityToBrains.RemoveAt(lastIndex);
i--;
continue;
}
_entityToBrains[i].Brain.Update(deltaTime);
}
}
public void Dispose()
{
foreach (EntityToBrain entityToBrain in _entityToBrains)
entityToBrain.Brain.Dispose();
_entityToBrains.Clear();
}
private class EntityToBrain
{
public Entity Entity;
public IBrain Brain;
public EntityToBrain(IBrain brain, Entity entity)
{
Brain = brain;
Entity = entity;
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 647b53823c00413081b7c9221d5bb5c1
timeCreated: 1772458604

View File

@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using Assets._Project.Develop.Runtime.Utilities.StateMachineCore;
namespace _Project.Develop.Runtime.Logic.Gameplay.Features.AI
{
public class AIStateMachine : StateMachine<IUpdatableState>
{
public AIStateMachine(List<IDisposable> disposables) : base(disposables)
{
}
public AIStateMachine() : base (new List<IDisposable>())
{
}
protected override void UpdateLogic(float deltaTime)
{
base.UpdateLogic(deltaTime);
CurrentState?.Update(deltaTime);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1e225964fa5a4120a1e4bf1cc8d47641
timeCreated: 1772455227

View File

@@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using _Project.Develop.Runtime.Entities;
using _Project.Develop.Runtime.Logic.Gameplay.Features.AI.States;
using _Project.Develop.Runtime.Utilities.Conditions;
using Assets._Project.Develop.Runtime.Infrastructure.DI;
using Assets._Project.Develop.Runtime.Utilities.Timer;
namespace _Project.Develop.Runtime.Logic.Gameplay.Features.AI
{
public class BrainsFactory
{
private readonly DIContainer _container;
private readonly AIBrainsContext _aiBrainsContext;
private readonly TimerServiceFactory _timerServiceFactory;
public BrainsFactory(DIContainer container)
{
_container = container;
_aiBrainsContext = _container.Resolve<AIBrainsContext>();
_timerServiceFactory = _container.Resolve<TimerServiceFactory>();
}
public StateMachineBrain CreateGhostBrain(Entity entity)
{
AIStateMachine stateMachine = CreateRandomMovementStateMachine(entity);
StateMachineBrain brain = new (stateMachine);
_aiBrainsContext.SetFor(entity, brain);
return brain;
}
private AIStateMachine CreateRandomMovementStateMachine(Entity entity)
{
List<IDisposable> disposables = new ();
RandomMovementState randomMovementState = new (entity, 0.5f);
EmptyState emptyState = new ();
TimerService movementTimer = _timerServiceFactory.Create(2f);
disposables.Add(randomMovementState.Entered.Subscribe(movementTimer.Restart));
disposables.Add(movementTimer);
TimerService idleTimer = _timerServiceFactory.Create(3f);
disposables.Add(emptyState.Entered.Subscribe(idleTimer.Restart));
disposables.Add(idleTimer);
FuncCondition movementTimerEndedCondition = new (() => movementTimer.IsOver);
FuncCondition idleTimerEndedCondition = new (() => idleTimer.IsOver);
AIStateMachine stateMachine = new (disposables);
stateMachine.AddState(randomMovementState);
stateMachine.AddState(emptyState);
stateMachine.AddTransition(randomMovementState, emptyState, movementTimerEndedCondition);
stateMachine.AddTransition(emptyState, randomMovementState, idleTimerEndedCondition);
return stateMachine;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0b566da239ac47d5b8c828cc1ac54cbe
timeCreated: 1772455908

View File

@@ -0,0 +1,14 @@
using System;
namespace _Project.Develop.Runtime.Logic.Gameplay.Features.AI
{
public interface IBrain : IDisposable
{
void Enable();
void Disable();
void Update(float deltaTime);
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 77beb88ee43645a5b0f85bf7d1518e4a
timeCreated: 1772458164

View File

@@ -0,0 +1,41 @@
namespace _Project.Develop.Runtime.Logic.Gameplay.Features.AI
{
public class StateMachineBrain : IBrain
{
private readonly AIStateMachine _stateMachine;
private bool _isEnabled;
public StateMachineBrain(AIStateMachine stateMachine)
{
_stateMachine = stateMachine;
}
public void Enable()
{
_stateMachine.Enter();
_isEnabled = true;
}
public void Update(float deltaTime)
{
if (_isEnabled == false)
return;
_stateMachine.Update(deltaTime);
}
public void Disable()
{
_stateMachine.Exit();
_stateMachine.Dispose();
_isEnabled = false;
}
public void Dispose()
{
_stateMachine.Dispose();
_isEnabled = false;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 45f2a68dedcb4a61a4ae6dc8a50227e4
timeCreated: 1772458266

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a0534b2062654595bef4d1e59081a533
timeCreated: 1772454304

View File

@@ -0,0 +1,12 @@
using Assets._Project.Develop.Runtime.Utilities.StateMachineCore;
namespace _Project.Develop.Runtime.Logic.Gameplay.Features.AI.States
{
public class EmptyState : State, IUpdatableState
{
public void Update(float deltaTime)
{
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3f40181e821046968e6c69ecef7e2384
timeCreated: 1772454318

View File

@@ -0,0 +1,67 @@
using _Project.Develop.Runtime.Entities;
using _Project.Develop.Runtime.Utils.ReactiveManagement;
using Assets._Project.Develop.Runtime.Utilities.StateMachineCore;
using UnityEngine;
namespace _Project.Develop.Runtime.Logic.Gameplay.Features.AI.States
{
public class RandomMovementState : State, IUpdatableState
{
private ReactiveVariable<Vector3> _moveDirection;
private ReactiveVariable<Vector3> _rotateDirection;
private float _cooldownBetweenDirection;
private float _time;
public RandomMovementState(Entity entity, float cooldownBetweenDirection)
{
_moveDirection = entity.MoveDirection;
_rotateDirection = entity.RotateDirection;
_cooldownBetweenDirection = cooldownBetweenDirection;
}
public override void Enter()
{
base.Enter();
Vector3 randomDirection = new Vector3(Random.Range(-1f, 1f), 0, Random.Range(-1f, 1f)).normalized;
_moveDirection.Value = randomDirection;
_rotateDirection.Value = randomDirection;
_time = 0;
}
public void Update(float deltaTime)
{
_time += deltaTime;
if (_time >= _cooldownBetweenDirection)
{
Vector3 newDirection = GenerateNewDirection();
_moveDirection.Value = newDirection;
_rotateDirection.Value = newDirection;
_time = 0;
}
}
public override void Exit()
{
base.Exit();
_moveDirection.Value = Vector3.zero;
}
private Vector3 GenerateNewDirection()
{
Vector3 inverseDirection = -_moveDirection.Value.normalized;
Quaternion randomTurn = Quaternion.Euler(0, Random.Range(-30, 30), 0);
return randomTurn * inverseDirection;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: dd6446a9b2f646bc870251ae870904b3
timeCreated: 1772454385

View File

@@ -3,7 +3,7 @@ using _Project.Develop.Runtime.Entities;
using _Project.Develop.Runtime.Utilities.Conditions;
using _Project.Develop.Runtime.Utils.ReactiveManagement;
using _Project.Develop.Runtime.Utils.ReactiveManagement.Event;
using Unity.Mathematics;
using UnityEngine;
namespace _Project.Develop.Runtime.Logic.Gameplay.Features.Energy.Systems
{
@@ -11,52 +11,52 @@ namespace _Project.Develop.Runtime.Logic.Gameplay.Features.Energy.Systems
{
private ReactiveEvent<int> _regenEnergyRequest;
private ReactiveEvent<int> _regenEnergyEvent;
private ReactiveVariable<int> _currentEnergy;
private ReactiveVariable<int> _maxEnergy;
private ICompositeCondition _canRegen;
private IDisposable _regenRequestDispose;
public void OnInit(Entity entity)
{
_currentEnergy = entity.CurrentEnergy;
_maxEnergy = entity.MaxEnergy;
_regenEnergyRequest = entity.RegenEnergyRequest;
_regenEnergyEvent = entity.RegenEnergyEvent;
_canRegen = entity.CanRegenEnergy;
_regenRequestDispose = _regenEnergyRequest.Subscribe(OnRegenRequest);
}
private void OnRegenRequest(int percentage)
{
if (percentage <= 0)
throw new ArgumentException("Energy regen percentage must be positive", nameof(percentage));
if (_canRegen.Evaluate() == false)
return;
int energyDifference = _maxEnergy.Value - _currentEnergy.Value;
if (energyDifference <= 0)
return;
int regenAmount= (int)math.floor(_maxEnergy.Value * (percentage / 100f));
int regenAmount = (int)Mathf.Floor(_maxEnergy.Value * (percentage / 100f));
if (regenAmount < 1 && _maxEnergy.Value > 0)
regenAmount = 1;
int valueAdded = math.min(regenAmount, energyDifference);
int valueAdded = Mathf.Min(regenAmount, energyDifference);
_currentEnergy.Value += valueAdded;
_regenEnergyEvent.Invoke(valueAdded);
}
public void OnDispose()
{
_regenRequestDispose.Dispose();

View File

@@ -3,7 +3,6 @@ using _Project.Develop.Runtime.Entities;
using _Project.Develop.Runtime.Utilities.Conditions;
using _Project.Develop.Runtime.Utils.ReactiveManagement;
using _Project.Develop.Runtime.Utils.ReactiveManagement.Event;
using Unity.Mathematics;
using UnityEngine;
namespace _Project.Develop.Runtime.Logic.Gameplay.Features.Energy.Systems
@@ -12,47 +11,47 @@ namespace _Project.Develop.Runtime.Logic.Gameplay.Features.Energy.Systems
{
private ReactiveEvent<int> _regenEnergyRequest;
private ReactiveEvent<int> _regenEnergyEvent;
private ReactiveVariable<int> _currentEnergy;
private ReactiveVariable<int> _maxEnergy;
private ICompositeCondition _canRegen;
private IDisposable _regenRequestDispose;
public void OnInit(Entity entity)
{
_currentEnergy = entity.CurrentEnergy;
_maxEnergy = entity.MaxEnergy;
_regenEnergyRequest = entity.RegenEnergyRequest;
_regenEnergyEvent = entity.RegenEnergyEvent;
_canRegen = entity.CanRegenEnergy;
_regenRequestDispose = _regenEnergyRequest.Subscribe(OnRegenRequest);
}
private void OnRegenRequest(int value)
{
if (value <= 0)
throw new ArgumentException("Energy regen value must be positive", nameof(value));
if (_canRegen.Evaluate() == false)
return;
int energyDifference = _maxEnergy.Value - _currentEnergy.Value;
if (energyDifference <= 0)
return;
int valueAdded = math.min(value, energyDifference);
int valueAdded = Mathf.Min(value, energyDifference);
_currentEnergy.Value += valueAdded;
_regenEnergyEvent.Invoke(valueAdded);
}
public void OnDispose()
{
_regenRequestDispose.Dispose();

View File

@@ -5,6 +5,7 @@ using System;
using System.Collections;
using _Project.Develop.Runtime.Entities;
using _Project.Develop.Runtime.Logic.Gameplay.Features;
using _Project.Develop.Runtime.Logic.Gameplay.Features.AI;
using _Project.Develop.Runtime.Utils.InputManagement;
using UnityEngine;
@@ -16,7 +17,7 @@ namespace Assets._Project.Develop.Runtime.Gameplay.Infrastructure
private DIContainer _container;
private EntitiesLifeContext _entitiesLifeContext;
private GameplayInputArgs _gameplayArgs;
private AIBrainsContext _aiBrainsContext;
private IPlayerInput _playerInput;
@@ -28,12 +29,12 @@ namespace Assets._Project.Develop.Runtime.Gameplay.Infrastructure
throw new ArgumentException($"{nameof(sceneArgs)} is not match with {typeof(GameplayInputArgs)} type");
GameplayContextRegistrations.Process(_container);
_gameplayArgs = gameplayInputArgs;
}
public override IEnumerator Initialize()
{
_entitiesLifeContext = _container.Resolve<EntitiesLifeContext>();
_aiBrainsContext = _container.Resolve<AIBrainsContext>();
_testGameplay.Initialize(_container);
yield break;
@@ -46,6 +47,7 @@ namespace Assets._Project.Develop.Runtime.Gameplay.Infrastructure
private void Update()
{
_aiBrainsContext?.Update(Time.deltaTime);
_entitiesLifeContext?.Update(Time.deltaTime);
}
}

View File

@@ -1,4 +1,5 @@
using _Project.Develop.Runtime.Entities;
using _Project.Develop.Runtime.Logic.Gameplay.Features.AI;
using _Project.Develop.Runtime.UI;
using _Project.Develop.Runtime.UI.Core;
using _Project.Develop.Runtime.UI.Screens.Gameplay;
@@ -21,9 +22,13 @@ namespace Assets._Project.Develop.Runtime.Gameplay.Infrastructure
container.RegisterAsSingle(CreateEntitiesFactory);
container.RegisterAsSingle(CreateEntitiesLifeContext);
container.RegisterAsSingle(CreateCollidersRegistryService);
container.RegisterAsSingle(CreateAIBrainContext);
container.RegisterAsSingle(CreateBrainsFactory);
container.RegisterAsSingle(CreateMonoEntitiesFactory).NonLazy();
}
private static AIBrainsContext CreateAIBrainContext(DIContainer c) => new();
private static BrainsFactory CreateBrainsFactory(DIContainer c) => new(c);
private static EntitiesLifeContext CreateEntitiesLifeContext(DIContainer c) => new();
private static EntitiesFactory CreateEntitiesFactory(DIContainer c) => new(c);

View File

@@ -1,5 +1,6 @@
using System;
using _Project.Develop.Runtime.Entities;
using _Project.Develop.Runtime.Logic.Gameplay.Features.AI;
using _Project.Develop.Runtime.Utils.InputManagement;
using Assets._Project.Develop.Runtime.Infrastructure.DI;
using UnityEngine;
@@ -10,8 +11,11 @@ namespace _Project.Develop.Runtime.Logic.Gameplay.Features
{
private DIContainer _container;
private EntitiesFactory _entitiesFactory;
private BrainsFactory _brainsFactory;
private Entity _entity;
private Entity _hero;
private Entity _ghost;
private bool _isRunning;
public void Initialize(DIContainer container)
@@ -20,15 +24,15 @@ namespace _Project.Develop.Runtime.Logic.Gameplay.Features
_container.Resolve<IPlayerInput>().Enable();
_entitiesFactory = _container.Resolve<EntitiesFactory>();
_brainsFactory = _container.Resolve<BrainsFactory>();
}
public void Run()
{
_entity = _entitiesFactory.CreateTeleportWizard(Vector3.zero);
_entitiesFactory.CreateGhost(Vector3.zero + Vector3.forward * 5);
_entitiesFactory.CreateGhost(Vector3.zero + Vector3.right * 5);
_entitiesFactory.CreateGhost(Vector3.zero + Vector3.left * 5);
_hero = _entitiesFactory.CreateTeleportWizard(Vector3.zero);
_ghost = _entitiesFactory.CreateGhost(Vector3.zero + Vector3.forward * 5);
_brainsFactory.CreateGhostBrain(_ghost);
_isRunning = true;
}
@@ -41,11 +45,11 @@ namespace _Project.Develop.Runtime.Logic.Gameplay.Features
private void OnGUI()
{
if (_entity == null)
if (_hero == null)
return;
GUI.Label(new Rect(10, 20, 200, 50), $"Health: {_entity.CurrentHealth.Value}/{_entity.MaxHealth.Value}");
GUI.Label(new Rect(10, 40, 200, 50), $"Energy: {_entity.CurrentEnergy.Value}/{_entity.MaxEnergy.Value}");
GUI.Label(new Rect(10, 20, 200, 50), $"Health: {_hero.CurrentHealth.Value}/{_hero.MaxHealth.Value}");
GUI.Label(new Rect(10, 40, 200, 50), $"Energy: {_hero.CurrentEnergy.Value}/{_hero.MaxEnergy.Value}");
}
}
}