mirror of
https://github.com/Bragin-Stepan/project-entity.git
synced 2026-03-02 14:29:23 +00:00
feat: add state machine
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
# Visual Studio cache directory
|
# Visual Studio cache directory
|
||||||
.vs/
|
.vs/
|
||||||
|
.agent/
|
||||||
|
|
||||||
# Gradle cache directory
|
# Gradle cache directory
|
||||||
.gradle/
|
.gradle/
|
||||||
|
|||||||
5
.vscode/extensions.json
vendored
Normal file
5
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"recommendations": [
|
||||||
|
"visualstudiotoolsforunity.vstuc"
|
||||||
|
]
|
||||||
|
}
|
||||||
10
.vscode/launch.json
vendored
Normal file
10
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Attach to Unity",
|
||||||
|
"type": "vstuc",
|
||||||
|
"request": "attach"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
8
.vscode/settings.json
vendored
8
.vscode/settings.json
vendored
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"dotrush.roslyn.projectOrSolutionFiles": [
|
"dotrush.roslyn.projectOrSolutionFiles": [
|
||||||
"e:\\_Programming\\Unity\\UnityGames\\project-entity\\project-entity.sln"
|
"e:\\_Programming\\Unity\\UnityGames\\project-entity\\project-entity.sln"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ using Assets._Project.Develop.Runtime.Utilities.DataManagement;
|
|||||||
using Assets._Project.Develop.Runtime.Utilities.DataManagement.DataProviders;
|
using Assets._Project.Develop.Runtime.Utilities.DataManagement.DataProviders;
|
||||||
using Assets._Project.Develop.Runtime.Utilities.LoadingScreen;
|
using Assets._Project.Develop.Runtime.Utilities.LoadingScreen;
|
||||||
using Assets._Project.Develop.Runtime.Utilities.SceneManagement;
|
using Assets._Project.Develop.Runtime.Utilities.SceneManagement;
|
||||||
|
using Assets._Project.Develop.Runtime.Utilities.Timer;
|
||||||
using Object = UnityEngine.Object;
|
using Object = UnityEngine.Object;
|
||||||
|
|
||||||
namespace Assets._Project.Develop.Runtime.Infrastructure.EntryPoint
|
namespace Assets._Project.Develop.Runtime.Infrastructure.EntryPoint
|
||||||
@@ -24,6 +25,7 @@ namespace Assets._Project.Develop.Runtime.Infrastructure.EntryPoint
|
|||||||
public static void Process(DIContainer container)
|
public static void Process(DIContainer container)
|
||||||
{
|
{
|
||||||
container.RegisterAsSingle<ICoroutinesPerformer>(CreateCoroutinesPerformer);
|
container.RegisterAsSingle<ICoroutinesPerformer>(CreateCoroutinesPerformer);
|
||||||
|
container.RegisterAsSingle(CreateTimerServiceFactory);
|
||||||
container.RegisterAsSingle(CreateConfigsProviderService);
|
container.RegisterAsSingle(CreateConfigsProviderService);
|
||||||
container.RegisterAsSingle(CreateResourcesAssetsLoader);
|
container.RegisterAsSingle(CreateResourcesAssetsLoader);
|
||||||
container.RegisterAsSingle(CreateSceneLoaderService);
|
container.RegisterAsSingle(CreateSceneLoaderService);
|
||||||
@@ -43,7 +45,7 @@ namespace Assets._Project.Develop.Runtime.Infrastructure.EntryPoint
|
|||||||
container.RegisterAsSingle(CreateViewsFactory);
|
container.RegisterAsSingle(CreateViewsFactory);
|
||||||
container.RegisterAsSingle<ILoadingScreen>(CreateLoadingScreen);
|
container.RegisterAsSingle<ILoadingScreen>(CreateLoadingScreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ConfigsProviderService CreateConfigsProviderService(DIContainer c)
|
private static ConfigsProviderService CreateConfigsProviderService(DIContainer c)
|
||||||
{
|
{
|
||||||
ResourcesAssetsLoader resourcesAssetsLoader = c.Resolve<ResourcesAssetsLoader>();
|
ResourcesAssetsLoader resourcesAssetsLoader = c.Resolve<ResourcesAssetsLoader>();
|
||||||
@@ -64,6 +66,8 @@ namespace Assets._Project.Develop.Runtime.Infrastructure.EntryPoint
|
|||||||
|
|
||||||
private static InputFactory CreateInputFactory(DIContainer c) => new();
|
private static InputFactory CreateInputFactory(DIContainer c) => new();
|
||||||
|
|
||||||
|
private static TimerServiceFactory CreateTimerServiceFactory(DIContainer c) => new (c);
|
||||||
|
|
||||||
private static PlayerInput CreatePlayerInput(DIContainer c) => c.Resolve<InputFactory>().CreatePlayerInput();
|
private static PlayerInput CreatePlayerInput(DIContainer c) => c.Resolve<InputFactory>().CreatePlayerInput();
|
||||||
|
|
||||||
private static UIInput CreateUIInput(DIContainer c) => c.Resolve<InputFactory>().CreateUIInput();
|
private static UIInput CreateUIInput(DIContainer c) => c.Resolve<InputFactory>().CreateUIInput();
|
||||||
|
|||||||
@@ -31,11 +31,11 @@ namespace _Project.Develop.Runtime.Entities
|
|||||||
_monoEntitiesFactory = container.Resolve<MonoEntitiesFactory>();
|
_monoEntitiesFactory = container.Resolve<MonoEntitiesFactory>();
|
||||||
_playerInput = container.Resolve<IPlayerInput>();
|
_playerInput = container.Resolve<IPlayerInput>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Entity CreateHero(Vector3 position)
|
public Entity CreateHero(Vector3 position)
|
||||||
{
|
{
|
||||||
Entity entity = CreateEmpty();
|
Entity entity = CreateEmpty();
|
||||||
|
|
||||||
_monoEntitiesFactory.Create(entity, position, PathToResources.Entity.Hero);
|
_monoEntitiesFactory.Create(entity, position, PathToResources.Entity.Hero);
|
||||||
|
|
||||||
entity
|
entity
|
||||||
@@ -65,29 +65,29 @@ namespace _Project.Develop.Runtime.Entities
|
|||||||
.AddAttackCooldownInitialTime()
|
.AddAttackCooldownInitialTime()
|
||||||
.AddAttackCooldownCurrentTime()
|
.AddAttackCooldownCurrentTime()
|
||||||
.AddInAttackCooldown();
|
.AddInAttackCooldown();
|
||||||
|
|
||||||
ICompositeCondition canMove = new CompositeCondition()
|
ICompositeCondition canMove = new CompositeCondition()
|
||||||
.Add(new FuncCondition(() => entity.IsDead.Value == false));
|
.Add(new FuncCondition(() => entity.IsDead.Value == false));
|
||||||
|
|
||||||
ICompositeCondition canRotate = new CompositeCondition()
|
ICompositeCondition canRotate = new CompositeCondition()
|
||||||
.Add(new FuncCondition(() => entity.IsDead.Value == false));
|
.Add(new FuncCondition(() => entity.IsDead.Value == false));
|
||||||
|
|
||||||
ICompositeCondition mustDie = new CompositeCondition()
|
ICompositeCondition mustDie = new CompositeCondition()
|
||||||
.Add(new FuncCondition(() => entity.CurrentHealth.Value <= 0));
|
.Add(new FuncCondition(() => entity.CurrentHealth.Value <= 0));
|
||||||
|
|
||||||
ICompositeCondition mustSelfRelease = new CompositeCondition()
|
ICompositeCondition mustSelfRelease = new CompositeCondition()
|
||||||
.Add(new FuncCondition(() => entity.IsDead.Value))
|
.Add(new FuncCondition(() => entity.IsDead.Value))
|
||||||
.Add(new FuncCondition(() => entity.InDeathProcess.Value == false));
|
.Add(new FuncCondition(() => entity.InDeathProcess.Value == false));
|
||||||
|
|
||||||
ICompositeCondition canApplyDamage = new CompositeCondition()
|
ICompositeCondition canApplyDamage = new CompositeCondition()
|
||||||
.Add(new FuncCondition(() => entity.IsDead.Value == false));
|
.Add(new FuncCondition(() => entity.IsDead.Value == false));
|
||||||
|
|
||||||
ICompositeCondition canStartAttack = new CompositeCondition()
|
ICompositeCondition canStartAttack = new CompositeCondition()
|
||||||
.Add(new FuncCondition(() => entity.IsDead.Value == false))
|
.Add(new FuncCondition(() => entity.IsDead.Value == false))
|
||||||
.Add(new FuncCondition(() => entity.InAttackProcess.Value == false))
|
.Add(new FuncCondition(() => entity.InAttackProcess.Value == false))
|
||||||
.Add(new FuncCondition(() => entity.IsMoving.Value == false))
|
.Add(new FuncCondition(() => entity.IsMoving.Value == false))
|
||||||
.Add(new FuncCondition(() => entity.InAttackCooldown.Value == false));
|
.Add(new FuncCondition(() => entity.InAttackCooldown.Value == false));
|
||||||
|
|
||||||
ICompositeCondition mustCancelAttack = new CompositeCondition(LogicOperationsUtils.Or)
|
ICompositeCondition mustCancelAttack = new CompositeCondition(LogicOperationsUtils.Or)
|
||||||
.Add(new FuncCondition(() => entity.IsDead.Value))
|
.Add(new FuncCondition(() => entity.IsDead.Value))
|
||||||
.Add(new FuncCondition(() => entity.IsMoving.Value));
|
.Add(new FuncCondition(() => entity.IsMoving.Value));
|
||||||
@@ -107,33 +107,33 @@ namespace _Project.Develop.Runtime.Entities
|
|||||||
.AddSystem(new RotateDirectionByMoveInputSystem(_playerInput))
|
.AddSystem(new RotateDirectionByMoveInputSystem(_playerInput))
|
||||||
.AddSystem(new RigidbodyMovementSystem())
|
.AddSystem(new RigidbodyMovementSystem())
|
||||||
.AddSystem(new RigidbodyRotationSystem())
|
.AddSystem(new RigidbodyRotationSystem())
|
||||||
|
|
||||||
.AddSystem(new AttackCancelSystem())
|
.AddSystem(new AttackCancelSystem())
|
||||||
|
|
||||||
.AddSystem(new StartAttackSystem())
|
.AddSystem(new StartAttackSystem())
|
||||||
.AddSystem(new ProcessAttackTimerSystem())
|
.AddSystem(new ProcessAttackTimerSystem())
|
||||||
.AddSystem(new AttackDelayEndTriggerSystem())
|
.AddSystem(new AttackDelayEndTriggerSystem())
|
||||||
.AddSystem(new InstantShootSystem(this))
|
.AddSystem(new InstantShootSystem(this))
|
||||||
.AddSystem(new EndAttackSystem())
|
.AddSystem(new EndAttackSystem())
|
||||||
.AddSystem(new AttackCooldownTimerSystem())
|
.AddSystem(new AttackCooldownTimerSystem())
|
||||||
|
|
||||||
.AddSystem(new ApplyDamageSystem())
|
.AddSystem(new ApplyDamageSystem())
|
||||||
|
|
||||||
.AddSystem(new DeathSwitcherSystem())
|
.AddSystem(new DeathSwitcherSystem())
|
||||||
.AddSystem(new DeathProcessTimerSystem())
|
.AddSystem(new DeathProcessTimerSystem())
|
||||||
|
|
||||||
.AddSystem(new DisableCollidersOnDeathSystem())
|
.AddSystem(new DisableCollidersOnDeathSystem())
|
||||||
.AddSystem(new SelfReleaseSystem(_entitiesLifeContext));
|
.AddSystem(new SelfReleaseSystem(_entitiesLifeContext));
|
||||||
|
|
||||||
_entitiesLifeContext.Add(entity);
|
_entitiesLifeContext.Add(entity);
|
||||||
|
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Entity CreateGhost(Vector3 position)
|
public Entity CreateGhost(Vector3 position)
|
||||||
{
|
{
|
||||||
Entity entity = CreateEmpty();
|
Entity entity = CreateEmpty();
|
||||||
|
|
||||||
_monoEntitiesFactory.Create(entity, position, PathToResources.Entity.Ghost);
|
_monoEntitiesFactory.Create(entity, position, PathToResources.Entity.Ghost);
|
||||||
|
|
||||||
entity
|
entity
|
||||||
@@ -154,20 +154,20 @@ namespace _Project.Develop.Runtime.Entities
|
|||||||
.AddInDeathProcess()
|
.AddInDeathProcess()
|
||||||
.AddDeathProcessInitialTime(new ReactiveVariable<float>(2))
|
.AddDeathProcessInitialTime(new ReactiveVariable<float>(2))
|
||||||
.AddDeathProcessCurrentTime();
|
.AddDeathProcessCurrentTime();
|
||||||
|
|
||||||
ICompositeCondition canMove = new CompositeCondition()
|
ICompositeCondition canMove = new CompositeCondition()
|
||||||
.Add(new FuncCondition(() => entity.IsDead.Value == false));
|
.Add(new FuncCondition(() => entity.IsDead.Value == false));
|
||||||
|
|
||||||
ICompositeCondition canRotate = new CompositeCondition()
|
ICompositeCondition canRotate = new CompositeCondition()
|
||||||
.Add(new FuncCondition(() => entity.IsDead.Value == false));
|
.Add(new FuncCondition(() => entity.IsDead.Value == false));
|
||||||
|
|
||||||
ICompositeCondition mustDie = new CompositeCondition()
|
ICompositeCondition mustDie = new CompositeCondition()
|
||||||
.Add(new FuncCondition(() => entity.CurrentHealth.Value <= 0));
|
.Add(new FuncCondition(() => entity.CurrentHealth.Value <= 0));
|
||||||
|
|
||||||
ICompositeCondition mustSelfRelease = new CompositeCondition()
|
ICompositeCondition mustSelfRelease = new CompositeCondition()
|
||||||
.Add(new FuncCondition(() => entity.IsDead.Value))
|
.Add(new FuncCondition(() => entity.IsDead.Value))
|
||||||
.Add(new FuncCondition(() => entity.InDeathProcess.Value == false));
|
.Add(new FuncCondition(() => entity.InDeathProcess.Value == false));
|
||||||
|
|
||||||
ICompositeCondition canApplyDamage = new CompositeCondition()
|
ICompositeCondition canApplyDamage = new CompositeCondition()
|
||||||
.Add(new FuncCondition(() => entity.IsDead.Value == false));
|
.Add(new FuncCondition(() => entity.IsDead.Value == false));
|
||||||
|
|
||||||
@@ -181,38 +181,38 @@ namespace _Project.Develop.Runtime.Entities
|
|||||||
entity
|
entity
|
||||||
.AddSystem(new RigidbodyMovementSystem())
|
.AddSystem(new RigidbodyMovementSystem())
|
||||||
.AddSystem(new RigidbodyRotationSystem())
|
.AddSystem(new RigidbodyRotationSystem())
|
||||||
|
|
||||||
.AddSystem(new BodyContactsDetectingSystem())
|
.AddSystem(new BodyContactsDetectingSystem())
|
||||||
.AddSystem(new BodyContactsEntitiesFilterSystem(_collidersRegistryService))
|
.AddSystem(new BodyContactsEntitiesFilterSystem(_collidersRegistryService))
|
||||||
|
|
||||||
.AddSystem(new DealDamageOnContactSystem())
|
.AddSystem(new DealDamageOnContactSystem())
|
||||||
.AddSystem(new ApplyDamageSystem())
|
.AddSystem(new ApplyDamageSystem())
|
||||||
|
|
||||||
.AddSystem(new DeathSwitcherSystem())
|
.AddSystem(new DeathSwitcherSystem())
|
||||||
.AddSystem(new DeathProcessTimerSystem())
|
.AddSystem(new DeathProcessTimerSystem())
|
||||||
|
|
||||||
.AddSystem(new DisableCollidersOnDeathSystem())
|
.AddSystem(new DisableCollidersOnDeathSystem())
|
||||||
.AddSystem(new SelfReleaseSystem(_entitiesLifeContext));
|
.AddSystem(new SelfReleaseSystem(_entitiesLifeContext));
|
||||||
|
|
||||||
_entitiesLifeContext.Add(entity);
|
_entitiesLifeContext.Add(entity);
|
||||||
|
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Entity CreateTeleportWizard(Vector3 position)
|
public Entity CreateTeleportWizard(Vector3 position)
|
||||||
{
|
{
|
||||||
Entity entity = CreateEmpty();
|
Entity entity = CreateEmpty();
|
||||||
|
|
||||||
_monoEntitiesFactory.Create(entity, position, PathToResources.Entity.Mage);
|
_monoEntitiesFactory.Create(entity, position, PathToResources.Entity.Mage);
|
||||||
|
|
||||||
entity
|
entity
|
||||||
.AddContactsDetectingMask(Layers.CharactersMask)
|
.AddContactsDetectingMask(Layers.CharactersMask)
|
||||||
.AddContactCollidersBuffer(new Buffer<Collider>(32))
|
.AddContactCollidersBuffer(new Buffer<Collider>(32))
|
||||||
.AddContactEntitiesBuffer(new Buffer<Entity>(32))
|
.AddContactEntitiesBuffer(new Buffer<Entity>(32))
|
||||||
|
|
||||||
.AddMaxHealth(new ReactiveVariable<float>(150))
|
.AddMaxHealth(new ReactiveVariable<float>(150))
|
||||||
.AddCurrentHealth(new ReactiveVariable<float>(150))
|
.AddCurrentHealth(new ReactiveVariable<float>(150))
|
||||||
|
|
||||||
.AddTeleportTarget(entity.Transform)
|
.AddTeleportTarget(entity.Transform)
|
||||||
.AddTeleportToPoint(entity.Transform)
|
.AddTeleportToPoint(entity.Transform)
|
||||||
.AddStartTeleportEvent()
|
.AddStartTeleportEvent()
|
||||||
@@ -221,14 +221,14 @@ namespace _Project.Develop.Runtime.Entities
|
|||||||
.AddFindTeleportPointEvent()
|
.AddFindTeleportPointEvent()
|
||||||
.AddFindTeleportPointRequest()
|
.AddFindTeleportPointRequest()
|
||||||
.AddEndTeleportEvent()
|
.AddEndTeleportEvent()
|
||||||
|
|
||||||
.AddTeleportDamage(new ReactiveVariable<float>(50))
|
.AddTeleportDamage(new ReactiveVariable<float>(50))
|
||||||
.AddTeleportDamageRadius(new ReactiveVariable<float>(6))
|
.AddTeleportDamageRadius(new ReactiveVariable<float>(6))
|
||||||
.AddTeleportDamageMask(Layers.CharactersMask)
|
.AddTeleportDamageMask(Layers.CharactersMask)
|
||||||
|
|
||||||
.AddTeleportEnergyCost(new ReactiveVariable<int>(20))
|
.AddTeleportEnergyCost(new ReactiveVariable<int>(20))
|
||||||
.AddTeleportSearchRadius(new ReactiveVariable<float>(6))
|
.AddTeleportSearchRadius(new ReactiveVariable<float>(6))
|
||||||
|
|
||||||
.AddCurrentEnergy(new ReactiveVariable<int>(60))
|
.AddCurrentEnergy(new ReactiveVariable<int>(60))
|
||||||
.AddMaxEnergy(new ReactiveVariable<int>(60))
|
.AddMaxEnergy(new ReactiveVariable<int>(60))
|
||||||
.AddUseEnergyEvent()
|
.AddUseEnergyEvent()
|
||||||
@@ -239,7 +239,7 @@ namespace _Project.Develop.Runtime.Entities
|
|||||||
.AddIsAutoRegenEnergy(new ReactiveVariable<bool>(true))
|
.AddIsAutoRegenEnergy(new ReactiveVariable<bool>(true))
|
||||||
.AddEnergyAutoRegenCurrentTime()
|
.AddEnergyAutoRegenCurrentTime()
|
||||||
.AddEnergyAutoRegenInitialTime(new ReactiveVariable<float>(3))
|
.AddEnergyAutoRegenInitialTime(new ReactiveVariable<float>(3))
|
||||||
|
|
||||||
.AddBodyContactDamage(new ReactiveVariable<float>(50))
|
.AddBodyContactDamage(new ReactiveVariable<float>(50))
|
||||||
.AddTakeDamageRequest()
|
.AddTakeDamageRequest()
|
||||||
.AddTakeDamageEvent()
|
.AddTakeDamageEvent()
|
||||||
@@ -247,24 +247,24 @@ namespace _Project.Develop.Runtime.Entities
|
|||||||
.AddInDeathProcess()
|
.AddInDeathProcess()
|
||||||
.AddDeathProcessInitialTime(new ReactiveVariable<float>(2))
|
.AddDeathProcessInitialTime(new ReactiveVariable<float>(2))
|
||||||
.AddDeathProcessCurrentTime();
|
.AddDeathProcessCurrentTime();
|
||||||
|
|
||||||
ICompositeCondition canRegenEnergy = new CompositeCondition()
|
ICompositeCondition canRegenEnergy = new CompositeCondition()
|
||||||
.Add(new FuncCondition(() => entity.IsDead.Value == false));
|
.Add(new FuncCondition(() => entity.IsDead.Value == false));
|
||||||
|
|
||||||
ICompositeCondition canUseEnergy = new CompositeCondition()
|
ICompositeCondition canUseEnergy = new CompositeCondition()
|
||||||
.Add(new FuncCondition(() => entity.IsDead.Value == false));
|
.Add(new FuncCondition(() => entity.IsDead.Value == false));
|
||||||
|
|
||||||
ICompositeCondition canStartTeleport = new CompositeCondition()
|
ICompositeCondition canStartTeleport = new CompositeCondition()
|
||||||
.Add(new FuncCondition(() => entity.IsDead.Value == false))
|
.Add(new FuncCondition(() => entity.IsDead.Value == false))
|
||||||
.Add(new FuncCondition(() => entity.CurrentEnergy.Value >= entity.TeleportEnergyCost.Value));
|
.Add(new FuncCondition(() => entity.CurrentEnergy.Value >= entity.TeleportEnergyCost.Value));
|
||||||
|
|
||||||
ICompositeCondition mustDie = new CompositeCondition()
|
ICompositeCondition mustDie = new CompositeCondition()
|
||||||
.Add(new FuncCondition(() => entity.CurrentHealth.Value <= 0));
|
.Add(new FuncCondition(() => entity.CurrentHealth.Value <= 0));
|
||||||
|
|
||||||
ICompositeCondition mustSelfRelease = new CompositeCondition()
|
ICompositeCondition mustSelfRelease = new CompositeCondition()
|
||||||
.Add(new FuncCondition(() => entity.IsDead.Value))
|
.Add(new FuncCondition(() => entity.IsDead.Value))
|
||||||
.Add(new FuncCondition(() => entity.InDeathProcess.Value == false));
|
.Add(new FuncCondition(() => entity.InDeathProcess.Value == false));
|
||||||
|
|
||||||
ICompositeCondition canApplyDamage = new CompositeCondition()
|
ICompositeCondition canApplyDamage = new CompositeCondition()
|
||||||
.Add(new FuncCondition(() => entity.IsDead.Value == false));
|
.Add(new FuncCondition(() => entity.IsDead.Value == false));
|
||||||
|
|
||||||
@@ -278,40 +278,40 @@ namespace _Project.Develop.Runtime.Entities
|
|||||||
|
|
||||||
entity
|
entity
|
||||||
.AddSystem(new TeleportByInputSystem(_playerInput))
|
.AddSystem(new TeleportByInputSystem(_playerInput))
|
||||||
|
|
||||||
// .AddSystem(new RegenEnergyByValueSystem())
|
// .AddSystem(new RegenEnergyByValueSystem())
|
||||||
.AddSystem(new RegenEnergyByPercentageSystem())
|
.AddSystem(new RegenEnergyByPercentageSystem())
|
||||||
.AddSystem(new UseEnergySystem())
|
.AddSystem(new UseEnergySystem())
|
||||||
.AddSystem(new AutoRegenEnergyTimerSystem())
|
.AddSystem(new AutoRegenEnergyTimerSystem())
|
||||||
|
|
||||||
.AddSystem(new TeleportStartByEnergySystem())
|
.AddSystem(new TeleportStartByEnergySystem())
|
||||||
.AddSystem(new TeleportProcessSystem())
|
.AddSystem(new TeleportProcessSystem())
|
||||||
.AddSystem(new FindRandomPointForTeleportSystem())
|
.AddSystem(new FindRandomPointForTeleportSystem())
|
||||||
.AddSystem(new EndTeleportSystem())
|
.AddSystem(new EndTeleportSystem())
|
||||||
.AddSystem(new InstantTeleportSystem())
|
.AddSystem(new InstantTeleportSystem())
|
||||||
.AddSystem(new DealDamageAfterTeleportSystem(_collidersRegistryService))
|
.AddSystem(new DealDamageAfterTeleportSystem(_collidersRegistryService))
|
||||||
|
|
||||||
.AddSystem(new BodyContactsDetectingSystem())
|
.AddSystem(new BodyContactsDetectingSystem())
|
||||||
.AddSystem(new BodyContactsEntitiesFilterSystem(_collidersRegistryService))
|
.AddSystem(new BodyContactsEntitiesFilterSystem(_collidersRegistryService))
|
||||||
|
|
||||||
.AddSystem(new DealDamageOnContactSystem())
|
.AddSystem(new DealDamageOnContactSystem())
|
||||||
.AddSystem(new ApplyDamageSystem())
|
.AddSystem(new ApplyDamageSystem())
|
||||||
|
|
||||||
.AddSystem(new DeathSwitcherSystem())
|
.AddSystem(new DeathSwitcherSystem())
|
||||||
.AddSystem(new DeathProcessTimerSystem())
|
.AddSystem(new DeathProcessTimerSystem())
|
||||||
|
|
||||||
.AddSystem(new DisableCollidersOnDeathSystem())
|
.AddSystem(new DisableCollidersOnDeathSystem())
|
||||||
.AddSystem(new SelfReleaseSystem(_entitiesLifeContext));
|
.AddSystem(new SelfReleaseSystem(_entitiesLifeContext));
|
||||||
|
|
||||||
_entitiesLifeContext.Add(entity);
|
_entitiesLifeContext.Add(entity);
|
||||||
|
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Entity CreateProjectile(Vector3 position, Vector3 direction, float damage)
|
public Entity CreateProjectile(Vector3 position, Vector3 direction, float damage)
|
||||||
{
|
{
|
||||||
Entity entity = CreateEmpty();
|
Entity entity = CreateEmpty();
|
||||||
|
|
||||||
_monoEntitiesFactory.Create(entity, position, PathToResources.Entity.Projectile);
|
_monoEntitiesFactory.Create(entity, position, PathToResources.Entity.Projectile);
|
||||||
|
|
||||||
entity
|
entity
|
||||||
@@ -327,13 +327,13 @@ namespace _Project.Develop.Runtime.Entities
|
|||||||
.AddIsMoving()
|
.AddIsMoving()
|
||||||
.AddDeathMask(Layers.CharactersMask | Layers.EnvironmentMask)
|
.AddDeathMask(Layers.CharactersMask | Layers.EnvironmentMask)
|
||||||
.AddIsTouchDeathMask();
|
.AddIsTouchDeathMask();
|
||||||
|
|
||||||
ICompositeCondition canMove = new CompositeCondition()
|
ICompositeCondition canMove = new CompositeCondition()
|
||||||
.Add(new FuncCondition(() => entity.IsDead.Value == false));
|
.Add(new FuncCondition(() => entity.IsDead.Value == false));
|
||||||
|
|
||||||
ICompositeCondition canRotate = new CompositeCondition()
|
ICompositeCondition canRotate = new CompositeCondition()
|
||||||
.Add(new FuncCondition(() => entity.IsDead.Value == false));
|
.Add(new FuncCondition(() => entity.IsDead.Value == false));
|
||||||
|
|
||||||
ICompositeCondition mustDie = new CompositeCondition()
|
ICompositeCondition mustDie = new CompositeCondition()
|
||||||
.Add(new FuncCondition(() => entity.IsTouchDeathMask.Value));
|
.Add(new FuncCondition(() => entity.IsTouchDeathMask.Value));
|
||||||
|
|
||||||
@@ -349,19 +349,19 @@ namespace _Project.Develop.Runtime.Entities
|
|||||||
entity
|
entity
|
||||||
.AddSystem(new RigidbodyMovementSystem())
|
.AddSystem(new RigidbodyMovementSystem())
|
||||||
.AddSystem(new RigidbodyRotationSystem())
|
.AddSystem(new RigidbodyRotationSystem())
|
||||||
|
|
||||||
.AddSystem(new BodyContactsDetectingSystem())
|
.AddSystem(new BodyContactsDetectingSystem())
|
||||||
.AddSystem(new BodyContactsEntitiesFilterSystem(_collidersRegistryService))
|
.AddSystem(new BodyContactsEntitiesFilterSystem(_collidersRegistryService))
|
||||||
|
|
||||||
.AddSystem(new DealDamageOnContactSystem())
|
.AddSystem(new DealDamageOnContactSystem())
|
||||||
.AddSystem(new DeathMaskTouchDetectorSystem())
|
.AddSystem(new DeathMaskTouchDetectorSystem())
|
||||||
.AddSystem(new DeathSwitcherSystem())
|
.AddSystem(new DeathSwitcherSystem())
|
||||||
|
|
||||||
.AddSystem(new DisableCollidersOnDeathSystem())
|
.AddSystem(new DisableCollidersOnDeathSystem())
|
||||||
.AddSystem(new SelfReleaseSystem(_entitiesLifeContext));
|
.AddSystem(new SelfReleaseSystem(_entitiesLifeContext));
|
||||||
|
|
||||||
_entitiesLifeContext.Add(entity);
|
_entitiesLifeContext.Add(entity);
|
||||||
|
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d79e4112f0c64a90b05cae78e957a829
|
||||||
|
timeCreated: 1772454294
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 647b53823c00413081b7c9221d5bb5c1
|
||||||
|
timeCreated: 1772458604
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 1e225964fa5a4120a1e4bf1cc8d47641
|
||||||
|
timeCreated: 1772455227
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 0b566da239ac47d5b8c828cc1ac54cbe
|
||||||
|
timeCreated: 1772455908
|
||||||
@@ -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);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 77beb88ee43645a5b0f85bf7d1518e4a
|
||||||
|
timeCreated: 1772458164
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 45f2a68dedcb4a61a4ae6dc8a50227e4
|
||||||
|
timeCreated: 1772458266
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: a0534b2062654595bef4d1e59081a533
|
||||||
|
timeCreated: 1772454304
|
||||||
@@ -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)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 3f40181e821046968e6c69ecef7e2384
|
||||||
|
timeCreated: 1772454318
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: dd6446a9b2f646bc870251ae870904b3
|
||||||
|
timeCreated: 1772454385
|
||||||
@@ -3,7 +3,7 @@ using _Project.Develop.Runtime.Entities;
|
|||||||
using _Project.Develop.Runtime.Utilities.Conditions;
|
using _Project.Develop.Runtime.Utilities.Conditions;
|
||||||
using _Project.Develop.Runtime.Utils.ReactiveManagement;
|
using _Project.Develop.Runtime.Utils.ReactiveManagement;
|
||||||
using _Project.Develop.Runtime.Utils.ReactiveManagement.Event;
|
using _Project.Develop.Runtime.Utils.ReactiveManagement.Event;
|
||||||
using Unity.Mathematics;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace _Project.Develop.Runtime.Logic.Gameplay.Features.Energy.Systems
|
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> _regenEnergyRequest;
|
||||||
private ReactiveEvent<int> _regenEnergyEvent;
|
private ReactiveEvent<int> _regenEnergyEvent;
|
||||||
|
|
||||||
private ReactiveVariable<int> _currentEnergy;
|
private ReactiveVariable<int> _currentEnergy;
|
||||||
private ReactiveVariable<int> _maxEnergy;
|
private ReactiveVariable<int> _maxEnergy;
|
||||||
|
|
||||||
private ICompositeCondition _canRegen;
|
private ICompositeCondition _canRegen;
|
||||||
|
|
||||||
private IDisposable _regenRequestDispose;
|
private IDisposable _regenRequestDispose;
|
||||||
|
|
||||||
public void OnInit(Entity entity)
|
public void OnInit(Entity entity)
|
||||||
{
|
{
|
||||||
_currentEnergy = entity.CurrentEnergy;
|
_currentEnergy = entity.CurrentEnergy;
|
||||||
_maxEnergy = entity.MaxEnergy;
|
_maxEnergy = entity.MaxEnergy;
|
||||||
|
|
||||||
_regenEnergyRequest = entity.RegenEnergyRequest;
|
_regenEnergyRequest = entity.RegenEnergyRequest;
|
||||||
_regenEnergyEvent = entity.RegenEnergyEvent;
|
_regenEnergyEvent = entity.RegenEnergyEvent;
|
||||||
|
|
||||||
_canRegen = entity.CanRegenEnergy;
|
_canRegen = entity.CanRegenEnergy;
|
||||||
|
|
||||||
_regenRequestDispose = _regenEnergyRequest.Subscribe(OnRegenRequest);
|
_regenRequestDispose = _regenEnergyRequest.Subscribe(OnRegenRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnRegenRequest(int percentage)
|
private void OnRegenRequest(int percentage)
|
||||||
{
|
{
|
||||||
if (percentage <= 0)
|
if (percentage <= 0)
|
||||||
throw new ArgumentException("Energy regen percentage must be positive", nameof(percentage));
|
throw new ArgumentException("Energy regen percentage must be positive", nameof(percentage));
|
||||||
|
|
||||||
if (_canRegen.Evaluate() == false)
|
if (_canRegen.Evaluate() == false)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int energyDifference = _maxEnergy.Value - _currentEnergy.Value;
|
int energyDifference = _maxEnergy.Value - _currentEnergy.Value;
|
||||||
|
|
||||||
if (energyDifference <= 0)
|
if (energyDifference <= 0)
|
||||||
return;
|
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)
|
if (regenAmount < 1 && _maxEnergy.Value > 0)
|
||||||
regenAmount = 1;
|
regenAmount = 1;
|
||||||
|
|
||||||
int valueAdded = math.min(regenAmount, energyDifference);
|
int valueAdded = Mathf.Min(regenAmount, energyDifference);
|
||||||
|
|
||||||
_currentEnergy.Value += valueAdded;
|
_currentEnergy.Value += valueAdded;
|
||||||
|
|
||||||
_regenEnergyEvent.Invoke(valueAdded);
|
_regenEnergyEvent.Invoke(valueAdded);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnDispose()
|
public void OnDispose()
|
||||||
{
|
{
|
||||||
_regenRequestDispose.Dispose();
|
_regenRequestDispose.Dispose();
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using _Project.Develop.Runtime.Entities;
|
|||||||
using _Project.Develop.Runtime.Utilities.Conditions;
|
using _Project.Develop.Runtime.Utilities.Conditions;
|
||||||
using _Project.Develop.Runtime.Utils.ReactiveManagement;
|
using _Project.Develop.Runtime.Utils.ReactiveManagement;
|
||||||
using _Project.Develop.Runtime.Utils.ReactiveManagement.Event;
|
using _Project.Develop.Runtime.Utils.ReactiveManagement.Event;
|
||||||
using Unity.Mathematics;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace _Project.Develop.Runtime.Logic.Gameplay.Features.Energy.Systems
|
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> _regenEnergyRequest;
|
||||||
private ReactiveEvent<int> _regenEnergyEvent;
|
private ReactiveEvent<int> _regenEnergyEvent;
|
||||||
|
|
||||||
private ReactiveVariable<int> _currentEnergy;
|
private ReactiveVariable<int> _currentEnergy;
|
||||||
private ReactiveVariable<int> _maxEnergy;
|
private ReactiveVariable<int> _maxEnergy;
|
||||||
|
|
||||||
private ICompositeCondition _canRegen;
|
private ICompositeCondition _canRegen;
|
||||||
|
|
||||||
private IDisposable _regenRequestDispose;
|
private IDisposable _regenRequestDispose;
|
||||||
|
|
||||||
public void OnInit(Entity entity)
|
public void OnInit(Entity entity)
|
||||||
{
|
{
|
||||||
_currentEnergy = entity.CurrentEnergy;
|
_currentEnergy = entity.CurrentEnergy;
|
||||||
_maxEnergy = entity.MaxEnergy;
|
_maxEnergy = entity.MaxEnergy;
|
||||||
|
|
||||||
_regenEnergyRequest = entity.RegenEnergyRequest;
|
_regenEnergyRequest = entity.RegenEnergyRequest;
|
||||||
_regenEnergyEvent = entity.RegenEnergyEvent;
|
_regenEnergyEvent = entity.RegenEnergyEvent;
|
||||||
|
|
||||||
_canRegen = entity.CanRegenEnergy;
|
_canRegen = entity.CanRegenEnergy;
|
||||||
|
|
||||||
_regenRequestDispose = _regenEnergyRequest.Subscribe(OnRegenRequest);
|
_regenRequestDispose = _regenEnergyRequest.Subscribe(OnRegenRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnRegenRequest(int value)
|
private void OnRegenRequest(int value)
|
||||||
{
|
{
|
||||||
if (value <= 0)
|
if (value <= 0)
|
||||||
throw new ArgumentException("Energy regen value must be positive", nameof(value));
|
throw new ArgumentException("Energy regen value must be positive", nameof(value));
|
||||||
|
|
||||||
if (_canRegen.Evaluate() == false)
|
if (_canRegen.Evaluate() == false)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int energyDifference = _maxEnergy.Value - _currentEnergy.Value;
|
int energyDifference = _maxEnergy.Value - _currentEnergy.Value;
|
||||||
|
|
||||||
if (energyDifference <= 0)
|
if (energyDifference <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int valueAdded = math.min(value, energyDifference);
|
int valueAdded = Mathf.Min(value, energyDifference);
|
||||||
|
|
||||||
_currentEnergy.Value += valueAdded;
|
_currentEnergy.Value += valueAdded;
|
||||||
|
|
||||||
_regenEnergyEvent.Invoke(valueAdded);
|
_regenEnergyEvent.Invoke(valueAdded);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnDispose()
|
public void OnDispose()
|
||||||
{
|
{
|
||||||
_regenRequestDispose.Dispose();
|
_regenRequestDispose.Dispose();
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using System;
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using _Project.Develop.Runtime.Entities;
|
using _Project.Develop.Runtime.Entities;
|
||||||
using _Project.Develop.Runtime.Logic.Gameplay.Features;
|
using _Project.Develop.Runtime.Logic.Gameplay.Features;
|
||||||
|
using _Project.Develop.Runtime.Logic.Gameplay.Features.AI;
|
||||||
using _Project.Develop.Runtime.Utils.InputManagement;
|
using _Project.Develop.Runtime.Utils.InputManagement;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
@@ -16,7 +17,7 @@ namespace Assets._Project.Develop.Runtime.Gameplay.Infrastructure
|
|||||||
|
|
||||||
private DIContainer _container;
|
private DIContainer _container;
|
||||||
private EntitiesLifeContext _entitiesLifeContext;
|
private EntitiesLifeContext _entitiesLifeContext;
|
||||||
private GameplayInputArgs _gameplayArgs;
|
private AIBrainsContext _aiBrainsContext;
|
||||||
|
|
||||||
private IPlayerInput _playerInput;
|
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");
|
throw new ArgumentException($"{nameof(sceneArgs)} is not match with {typeof(GameplayInputArgs)} type");
|
||||||
|
|
||||||
GameplayContextRegistrations.Process(_container);
|
GameplayContextRegistrations.Process(_container);
|
||||||
_gameplayArgs = gameplayInputArgs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IEnumerator Initialize()
|
public override IEnumerator Initialize()
|
||||||
{
|
{
|
||||||
_entitiesLifeContext = _container.Resolve<EntitiesLifeContext>();
|
_entitiesLifeContext = _container.Resolve<EntitiesLifeContext>();
|
||||||
|
_aiBrainsContext = _container.Resolve<AIBrainsContext>();
|
||||||
|
|
||||||
_testGameplay.Initialize(_container);
|
_testGameplay.Initialize(_container);
|
||||||
yield break;
|
yield break;
|
||||||
@@ -46,6 +47,7 @@ namespace Assets._Project.Develop.Runtime.Gameplay.Infrastructure
|
|||||||
|
|
||||||
private void Update()
|
private void Update()
|
||||||
{
|
{
|
||||||
|
_aiBrainsContext?.Update(Time.deltaTime);
|
||||||
_entitiesLifeContext?.Update(Time.deltaTime);
|
_entitiesLifeContext?.Update(Time.deltaTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using _Project.Develop.Runtime.Entities;
|
using _Project.Develop.Runtime.Entities;
|
||||||
|
using _Project.Develop.Runtime.Logic.Gameplay.Features.AI;
|
||||||
using _Project.Develop.Runtime.UI;
|
using _Project.Develop.Runtime.UI;
|
||||||
using _Project.Develop.Runtime.UI.Core;
|
using _Project.Develop.Runtime.UI.Core;
|
||||||
using _Project.Develop.Runtime.UI.Screens.Gameplay;
|
using _Project.Develop.Runtime.UI.Screens.Gameplay;
|
||||||
@@ -21,9 +22,13 @@ namespace Assets._Project.Develop.Runtime.Gameplay.Infrastructure
|
|||||||
container.RegisterAsSingle(CreateEntitiesFactory);
|
container.RegisterAsSingle(CreateEntitiesFactory);
|
||||||
container.RegisterAsSingle(CreateEntitiesLifeContext);
|
container.RegisterAsSingle(CreateEntitiesLifeContext);
|
||||||
container.RegisterAsSingle(CreateCollidersRegistryService);
|
container.RegisterAsSingle(CreateCollidersRegistryService);
|
||||||
|
container.RegisterAsSingle(CreateAIBrainContext);
|
||||||
|
container.RegisterAsSingle(CreateBrainsFactory);
|
||||||
container.RegisterAsSingle(CreateMonoEntitiesFactory).NonLazy();
|
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 EntitiesLifeContext CreateEntitiesLifeContext(DIContainer c) => new();
|
||||||
|
|
||||||
private static EntitiesFactory CreateEntitiesFactory(DIContainer c) => new(c);
|
private static EntitiesFactory CreateEntitiesFactory(DIContainer c) => new(c);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using _Project.Develop.Runtime.Entities;
|
using _Project.Develop.Runtime.Entities;
|
||||||
|
using _Project.Develop.Runtime.Logic.Gameplay.Features.AI;
|
||||||
using _Project.Develop.Runtime.Utils.InputManagement;
|
using _Project.Develop.Runtime.Utils.InputManagement;
|
||||||
using Assets._Project.Develop.Runtime.Infrastructure.DI;
|
using Assets._Project.Develop.Runtime.Infrastructure.DI;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
@@ -10,8 +11,11 @@ namespace _Project.Develop.Runtime.Logic.Gameplay.Features
|
|||||||
{
|
{
|
||||||
private DIContainer _container;
|
private DIContainer _container;
|
||||||
private EntitiesFactory _entitiesFactory;
|
private EntitiesFactory _entitiesFactory;
|
||||||
|
private BrainsFactory _brainsFactory;
|
||||||
|
|
||||||
private Entity _entity;
|
private Entity _hero;
|
||||||
|
private Entity _ghost;
|
||||||
|
|
||||||
private bool _isRunning;
|
private bool _isRunning;
|
||||||
|
|
||||||
public void Initialize(DIContainer container)
|
public void Initialize(DIContainer container)
|
||||||
@@ -20,15 +24,15 @@ namespace _Project.Develop.Runtime.Logic.Gameplay.Features
|
|||||||
|
|
||||||
_container.Resolve<IPlayerInput>().Enable();
|
_container.Resolve<IPlayerInput>().Enable();
|
||||||
_entitiesFactory = _container.Resolve<EntitiesFactory>();
|
_entitiesFactory = _container.Resolve<EntitiesFactory>();
|
||||||
|
_brainsFactory = _container.Resolve<BrainsFactory>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Run()
|
public void Run()
|
||||||
{
|
{
|
||||||
_entity = _entitiesFactory.CreateTeleportWizard(Vector3.zero);
|
_hero = _entitiesFactory.CreateTeleportWizard(Vector3.zero);
|
||||||
|
_ghost = _entitiesFactory.CreateGhost(Vector3.zero + Vector3.forward * 5);
|
||||||
_entitiesFactory.CreateGhost(Vector3.zero + Vector3.forward * 5);
|
|
||||||
_entitiesFactory.CreateGhost(Vector3.zero + Vector3.right * 5);
|
_brainsFactory.CreateGhostBrain(_ghost);
|
||||||
_entitiesFactory.CreateGhost(Vector3.zero + Vector3.left * 5);
|
|
||||||
|
|
||||||
_isRunning = true;
|
_isRunning = true;
|
||||||
}
|
}
|
||||||
@@ -41,11 +45,11 @@ namespace _Project.Develop.Runtime.Logic.Gameplay.Features
|
|||||||
|
|
||||||
private void OnGUI()
|
private void OnGUI()
|
||||||
{
|
{
|
||||||
if (_entity == null)
|
if (_hero == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
GUI.Label(new Rect(10, 20, 200, 50), $"Health: {_entity.CurrentHealth.Value}/{_entity.MaxHealth.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: {_entity.CurrentEnergy.Value}/{_entity.MaxEnergy.Value}");
|
GUI.Label(new Rect(10, 40, 200, 50), $"Energy: {_hero.CurrentEnergy.Value}/{_hero.MaxEnergy.Value}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,7 +3,7 @@ using System.Collections.Generic;
|
|||||||
|
|
||||||
namespace _Project.Develop.Runtime.Utils.ReactiveManagement.Event
|
namespace _Project.Develop.Runtime.Utils.ReactiveManagement.Event
|
||||||
{
|
{
|
||||||
public class ReactiveEvent<T> : IReadOnlyEvent<T>
|
public class ReactiveEvent<T> : IReadOnlyEvent<T>
|
||||||
{
|
{
|
||||||
private readonly List<Subscriber<T>> _subscribers = new();
|
private readonly List<Subscriber<T>> _subscribers = new();
|
||||||
private readonly List<Subscriber<T>> _toAdd = new();
|
private readonly List<Subscriber<T>> _toAdd = new();
|
||||||
@@ -41,9 +41,9 @@ namespace _Project.Develop.Runtime.Utils.ReactiveManagement.Event
|
|||||||
|
|
||||||
public class ReactiveEvent : IReadOnlyEvent
|
public class ReactiveEvent : IReadOnlyEvent
|
||||||
{
|
{
|
||||||
private readonly List<Subscriber> _subscribers = new();
|
private readonly List<Subscriber> _subscribers = new List<Subscriber>();
|
||||||
private readonly List<Subscriber> _toAdd = new();
|
private readonly List<Subscriber> _toAdd = new List<Subscriber>();
|
||||||
private readonly List<Subscriber> _toRemove = new();
|
private readonly List<Subscriber> _toRemove = new List<Subscriber>();
|
||||||
|
|
||||||
public IDisposable Subscribe(Action action)
|
public IDisposable Subscribe(Action action)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,16 +5,16 @@ namespace _Project.Develop.Runtime.Utils.ReactiveManagement
|
|||||||
{
|
{
|
||||||
public class ReactiveVariable<T> : IReadOnlyVariable<T> where T : IEquatable<T>
|
public class ReactiveVariable<T> : IReadOnlyVariable<T> where T : IEquatable<T>
|
||||||
{
|
{
|
||||||
private readonly List<Subscriber<T, T>> _subscribers = new ();
|
private readonly List<Subscriber<T, T>> _subscribers = new List<Subscriber<T, T>>();
|
||||||
private readonly List<Subscriber<T, T>> _toAddList = new ();
|
private readonly List<Subscriber<T, T>> _toAddList = new List<Subscriber<T, T>>();
|
||||||
private readonly List<Subscriber<T, T>> _toRemoveList = new ();
|
private readonly List<Subscriber<T, T>> _toRemoveList = new List<Subscriber<T, T>>();
|
||||||
|
|
||||||
public ReactiveVariable() => _value = default(T);
|
public ReactiveVariable() => _value = default(T);
|
||||||
|
|
||||||
public ReactiveVariable(T value) => _value = value;
|
public ReactiveVariable(T value) => _value = value;
|
||||||
|
|
||||||
private T _value;
|
private T _value;
|
||||||
|
|
||||||
public T Value
|
public T Value
|
||||||
{
|
{
|
||||||
get => _value;
|
get => _value;
|
||||||
@@ -27,33 +27,33 @@ namespace _Project.Develop.Runtime.Utils.ReactiveManagement
|
|||||||
Invoke(oldValue, _value);
|
Invoke(oldValue, _value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public IDisposable Subscribe(Action<T, T> action)
|
|
||||||
{
|
|
||||||
Subscriber<T, T> subscriber = new (action, RemoveSubscriber);
|
|
||||||
_toAddList.Add(subscriber);
|
|
||||||
|
|
||||||
return subscriber;
|
public IDisposable Subscribe(Action<T, T> action)
|
||||||
}
|
{
|
||||||
|
Subscriber<T, T> subscriber = new Subscriber<T, T>(action, RemoveSubscriber);
|
||||||
|
_toAddList.Add(subscriber);
|
||||||
|
|
||||||
|
return subscriber;
|
||||||
|
}
|
||||||
|
|
||||||
private void RemoveSubscriber(Subscriber<T, T> subscriber) => _toRemoveList.Add(subscriber);
|
private void RemoveSubscriber(Subscriber<T, T> subscriber) => _toRemoveList.Add(subscriber);
|
||||||
|
|
||||||
private void Invoke(T oldValue, T newValue)
|
private void Invoke(T oldValue, T newValue)
|
||||||
{
|
{
|
||||||
if(_toAddList.Count > 0)
|
if (_toAddList.Count > 0)
|
||||||
{
|
{
|
||||||
_subscribers.AddRange(_toAddList);
|
_subscribers.AddRange(_toAddList);
|
||||||
_toAddList.Clear();
|
_toAddList.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(_toRemoveList.Count > 0)
|
if (_toRemoveList.Count > 0)
|
||||||
{
|
{
|
||||||
foreach (Subscriber<T, T> subscriber in _toRemoveList)
|
foreach (Subscriber<T, T> subscriber in _toRemoveList)
|
||||||
_subscribers.Remove(subscriber);
|
_subscribers.Remove(subscriber);
|
||||||
|
|
||||||
_toRemoveList.Clear();
|
_toRemoveList.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (Subscriber<T, T> subscriber in _subscribers)
|
foreach (Subscriber<T, T> subscriber in _subscribers)
|
||||||
subscriber.Invoke(oldValue, newValue);
|
subscriber.Invoke(oldValue, newValue);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
|
||||||
|
using _Project.Develop.Runtime.Utils.ReactiveManagement.Event;
|
||||||
|
|
||||||
|
namespace Assets._Project.Develop.Runtime.Utilities.StateMachineCore
|
||||||
|
{
|
||||||
|
public interface IState
|
||||||
|
{
|
||||||
|
IReadOnlyEvent Entered { get; }
|
||||||
|
IReadOnlyEvent Exited { get; }
|
||||||
|
|
||||||
|
void Enter();
|
||||||
|
void Exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: aed062833c374a6c8f4f784616dad179
|
||||||
|
timeCreated: 1772453453
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace Assets._Project.Develop.Runtime.Utilities.StateMachineCore
|
||||||
|
{
|
||||||
|
public interface IUpdatableState : IState
|
||||||
|
{
|
||||||
|
void Update(float deltaTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: c1ea582554484972bd37276974ad4434
|
||||||
|
timeCreated: 1772453453
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Assets._Project.Develop.Runtime.Utilities.StateMachineCore
|
||||||
|
{
|
||||||
|
public abstract class ParallelState<TState> : State where TState : class, IState
|
||||||
|
{
|
||||||
|
private List<TState> _states;
|
||||||
|
|
||||||
|
public ParallelState(params TState[] states)
|
||||||
|
{
|
||||||
|
_states = new List<TState>(states);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IReadOnlyList<TState> States => _states;
|
||||||
|
|
||||||
|
public override void Enter()
|
||||||
|
{
|
||||||
|
base.Enter();
|
||||||
|
|
||||||
|
foreach (TState state in _states)
|
||||||
|
state.Enter();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Exit()
|
||||||
|
{
|
||||||
|
base.Exit();
|
||||||
|
|
||||||
|
foreach (TState state in _states)
|
||||||
|
state.Exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 3084d8be941e4eb89f019da66b818702
|
||||||
|
timeCreated: 1772453453
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using _Project.Develop.Runtime.Utils.ReactiveManagement.Event;
|
||||||
|
|
||||||
|
namespace Assets._Project.Develop.Runtime.Utilities.StateMachineCore
|
||||||
|
{
|
||||||
|
public abstract class State : IState
|
||||||
|
{
|
||||||
|
private ReactiveEvent _entered = new();
|
||||||
|
private ReactiveEvent _exited = new();
|
||||||
|
|
||||||
|
public IReadOnlyEvent Entered => _entered;
|
||||||
|
|
||||||
|
public IReadOnlyEvent Exited => _exited;
|
||||||
|
|
||||||
|
public virtual void Enter() => _entered.Invoke();
|
||||||
|
|
||||||
|
public virtual void Exit() => _exited.Invoke();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 975fa4387d1e4f37afb584f32071e4bc
|
||||||
|
timeCreated: 1772453453
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using _Project.Develop.Runtime.Utilities.Conditions;
|
||||||
|
|
||||||
|
namespace Assets._Project.Develop.Runtime.Utilities.StateMachineCore
|
||||||
|
{
|
||||||
|
public abstract class StateMachine<TState> : State, IDisposable, IUpdatableState where TState : class, IState
|
||||||
|
{
|
||||||
|
private List<StateNode<TState>> _states = new();
|
||||||
|
|
||||||
|
private StateNode<TState> _currentState;
|
||||||
|
|
||||||
|
private bool _isRunning;
|
||||||
|
|
||||||
|
private List<IDisposable> _disposables;
|
||||||
|
|
||||||
|
protected StateMachine(List<IDisposable> disposables)
|
||||||
|
{
|
||||||
|
_disposables = new List<IDisposable>(disposables);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected TState CurrentState => _currentState.State;
|
||||||
|
|
||||||
|
public void AddState(TState state) => _states.Add(new StateNode<TState>(state));
|
||||||
|
|
||||||
|
public void AddTransition(TState fromState, TState toState, ICondition condition)
|
||||||
|
{
|
||||||
|
StateNode<TState> from = _states.First(stateNode => stateNode.State == fromState);
|
||||||
|
StateNode<TState> to = _states.First(stateNode => stateNode.State == toState);
|
||||||
|
|
||||||
|
from.AddTransition(new StateTransition<TState>(to, condition));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update(float deltaTime)
|
||||||
|
{
|
||||||
|
if (_isRunning == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (StateTransition<TState> transition in _currentState.Transitions)
|
||||||
|
{
|
||||||
|
if (transition.Condition.Evaluate())
|
||||||
|
{
|
||||||
|
SwitchState(transition.ToState);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateLogic(deltaTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void UpdateLogic(float deltaTime) { }
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_isRunning = false;
|
||||||
|
|
||||||
|
foreach (StateNode<TState> stateNode in _states)
|
||||||
|
if (stateNode.State is IDisposable disposableState)
|
||||||
|
disposableState.Dispose();
|
||||||
|
|
||||||
|
_states.Clear();
|
||||||
|
|
||||||
|
foreach (IDisposable disposable in _disposables)
|
||||||
|
disposable.Dispose();
|
||||||
|
|
||||||
|
_disposables.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Enter()
|
||||||
|
{
|
||||||
|
base.Enter();
|
||||||
|
|
||||||
|
if (_currentState == null)
|
||||||
|
SwitchState(_states[0]);
|
||||||
|
|
||||||
|
_isRunning = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Exit()
|
||||||
|
{
|
||||||
|
base.Exit();
|
||||||
|
|
||||||
|
_currentState?.State.Exit();
|
||||||
|
|
||||||
|
_isRunning = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SwitchState(StateNode<TState> nextState)
|
||||||
|
{
|
||||||
|
_currentState?.State.Exit();
|
||||||
|
_currentState = nextState;
|
||||||
|
_currentState.State.Enter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 421f6f14fa064baaa737bea3684d473f
|
||||||
|
timeCreated: 1772453453
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Assets._Project.Develop.Runtime.Utilities.StateMachineCore
|
||||||
|
{
|
||||||
|
public class StateNode<TState> where TState : class, IState
|
||||||
|
{
|
||||||
|
private List<StateTransition<TState>> _transitions = new();
|
||||||
|
|
||||||
|
public StateNode(TState state)
|
||||||
|
{
|
||||||
|
State = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TState State { get; }
|
||||||
|
|
||||||
|
public IReadOnlyList<StateTransition<TState>> Transitions => _transitions;
|
||||||
|
|
||||||
|
public void AddTransition(StateTransition<TState> transition) => _transitions.Add(transition);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: dce697e6ac3b45b497e8e89c5ca258cc
|
||||||
|
timeCreated: 1772453453
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using _Project.Develop.Runtime.Utilities.Conditions;
|
||||||
|
|
||||||
|
namespace Assets._Project.Develop.Runtime.Utilities.StateMachineCore
|
||||||
|
{
|
||||||
|
public class StateTransition<TState> where TState : class, IState
|
||||||
|
{
|
||||||
|
public StateTransition(StateNode<TState> toState, ICondition condition)
|
||||||
|
{
|
||||||
|
ToState = toState;
|
||||||
|
Condition = condition;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StateNode<TState> ToState { get; }
|
||||||
|
public ICondition Condition { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 07aef2e29c2643419ff17e32556da944
|
||||||
|
timeCreated: 1772453453
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 831af1f46fb24b5c89e15c287f7bdfad
|
||||||
|
timeCreated: 1772456814
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using _Project.Develop.Runtime.Utils.ReactiveManagement;
|
||||||
|
using _Project.Develop.Runtime.Utils.ReactiveManagement.Event;
|
||||||
|
using Assets._Project.Develop.Runtime.Utilities.CoroutinesManagement;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Assets._Project.Develop.Runtime.Utilities.Timer
|
||||||
|
{
|
||||||
|
public class TimerService : IDisposable
|
||||||
|
{
|
||||||
|
private float _cooldown;
|
||||||
|
|
||||||
|
private ReactiveEvent _cooldownEnded;
|
||||||
|
|
||||||
|
private ReactiveVariable<float> _currentTime;
|
||||||
|
|
||||||
|
private ICoroutinesPerformer _coroutinePerformer;
|
||||||
|
private Coroutine _cooldownProcess;
|
||||||
|
|
||||||
|
public TimerService(
|
||||||
|
float cooldown,
|
||||||
|
ICoroutinesPerformer coroutinePerformer)
|
||||||
|
{
|
||||||
|
_cooldown = cooldown;
|
||||||
|
_coroutinePerformer = coroutinePerformer;
|
||||||
|
|
||||||
|
_cooldownEnded = new ReactiveEvent();
|
||||||
|
_currentTime = new ReactiveVariable<float>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IReadOnlyEvent CooldownEnded => _cooldownEnded;
|
||||||
|
public IReadOnlyVariable<float> CurrentTime => _currentTime;
|
||||||
|
public bool IsOver => _currentTime.Value <= 0;
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Stop()
|
||||||
|
{
|
||||||
|
if (_cooldownProcess != null)
|
||||||
|
_coroutinePerformer.StopPerform(_cooldownProcess);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Restart()
|
||||||
|
{
|
||||||
|
Stop();
|
||||||
|
|
||||||
|
_cooldownProcess = _coroutinePerformer.StartPerform(CooldownProcess());
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerator CooldownProcess()
|
||||||
|
{
|
||||||
|
_currentTime.Value = _cooldown;
|
||||||
|
|
||||||
|
while (IsOver == false)
|
||||||
|
{
|
||||||
|
_currentTime.Value -= Time.deltaTime;
|
||||||
|
yield return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
_cooldownEnded.Invoke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e5636415f9a840ab8ff88d96719179ec
|
||||||
|
timeCreated: 1772456820
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using Assets._Project.Develop.Runtime.Infrastructure.DI;
|
||||||
|
using Assets._Project.Develop.Runtime.Utilities.CoroutinesManagement;
|
||||||
|
|
||||||
|
namespace Assets._Project.Develop.Runtime.Utilities.Timer
|
||||||
|
{
|
||||||
|
public class TimerServiceFactory
|
||||||
|
{
|
||||||
|
private readonly DIContainer _container;
|
||||||
|
|
||||||
|
public TimerServiceFactory(DIContainer container)
|
||||||
|
{
|
||||||
|
_container = container;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TimerService Create(float cooldown)
|
||||||
|
=> new TimerService(cooldown, _container.Resolve<ICoroutinesPerformer>());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 6fbab9cab89b4ad094fc636facb8597a
|
||||||
|
timeCreated: 1772456820
|
||||||
@@ -924,7 +924,7 @@ PlayerSettings:
|
|||||||
embeddedLinuxEnableGamepadInput: 1
|
embeddedLinuxEnableGamepadInput: 1
|
||||||
hmiLogStartupTiming: 0
|
hmiLogStartupTiming: 0
|
||||||
hmiCpuConfiguration:
|
hmiCpuConfiguration:
|
||||||
apiCompatibilityLevel: 6
|
apiCompatibilityLevel: 3
|
||||||
activeInputHandler: 2
|
activeInputHandler: 2
|
||||||
windowsGamepadBackendHint: 0
|
windowsGamepadBackendHint: 0
|
||||||
cloudProjectId: 4a15d730-99ee-4a69-b00c-c0c75aa639bd
|
cloudProjectId: 4a15d730-99ee-4a69-b00c-c0c75aa639bd
|
||||||
|
|||||||
33
project-entity.slnx
Normal file
33
project-entity.slnx
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<Solution>
|
||||||
|
<Project Path="Unity.Timeline.csproj" />
|
||||||
|
<Project Path="Unity.Timeline.Editor.csproj" />
|
||||||
|
<Project Path="Assembly-CSharp.csproj" />
|
||||||
|
<Project Path="Unity.InputSystem.csproj" />
|
||||||
|
<Project Path="Unity.TextMeshPro.Editor.csproj" />
|
||||||
|
<Project Path="Unity.PlasticSCM.Editor.csproj" />
|
||||||
|
<Project Path="Unity.VisualScripting.Flow.csproj" />
|
||||||
|
<Project Path="Unity.VisualScripting.Core.csproj" />
|
||||||
|
<Project Path="Unity.Mathematics.csproj" />
|
||||||
|
<Project Path="Unity.VisualScripting.Core.Editor.csproj" />
|
||||||
|
<Project Path="Unity.VisualScripting.Flow.Editor.csproj" />
|
||||||
|
<Project Path="UnityEditor.TestRunner.csproj" />
|
||||||
|
<Project Path="Unity.VisualScripting.SettingsProvider.Editor.csproj" />
|
||||||
|
<Project Path="UnityEngine.TestRunner.csproj" />
|
||||||
|
<Project Path="Unity.Searcher.Editor.csproj" />
|
||||||
|
<Project Path="Unity.Burst.csproj" />
|
||||||
|
<Project Path="Unity.VisualStudio.Editor.csproj" />
|
||||||
|
<Project Path="Unity.Rider.Editor.csproj" />
|
||||||
|
<Project Path="Unity.CollabProxy.Editor.csproj" />
|
||||||
|
<Project Path="Unity.VisualScripting.State.Editor.csproj" />
|
||||||
|
<Project Path="Unity.Burst.CodeGen.csproj" />
|
||||||
|
<Project Path="Unity.VisualScripting.State.csproj" />
|
||||||
|
<Project Path="Unity.TextMeshPro.csproj" />
|
||||||
|
<Project Path="Assembly-CSharp-firstpass.csproj" />
|
||||||
|
<Project Path="Unity.VSCode.Editor.csproj" />
|
||||||
|
<Project Path="Unity.Burst.Editor.csproj" />
|
||||||
|
<Project Path="Unity.InputSystem.ForUI.csproj" />
|
||||||
|
<Project Path="Unity.Mathematics.Editor.csproj" />
|
||||||
|
<Project Path="Unity.InputSystem.TestFramework.csproj" />
|
||||||
|
<Project Path="Unity.VisualScripting.Shared.Editor.csproj" />
|
||||||
|
<Project Path="Assembly-CSharp-Editor.csproj" />
|
||||||
|
</Solution>
|
||||||
Reference in New Issue
Block a user