diff --git a/Assets/_Project/Develop/Runtime/Logic/Gameplay/Entities/EntitiesFactory.cs b/Assets/_Project/Develop/Runtime/Logic/Gameplay/Entities/EntitiesFactory.cs index 8aaacc6..7c39bba 100644 --- a/Assets/_Project/Develop/Runtime/Logic/Gameplay/Entities/EntitiesFactory.cs +++ b/Assets/_Project/Develop/Runtime/Logic/Gameplay/Entities/EntitiesFactory.cs @@ -52,13 +52,13 @@ namespace _Project.Develop.Runtime.Entities .AddInDeathProcess() .AddDeathProcessInitialTime(new ReactiveVariable(2)) .AddDeathProcessCurrentTime() - .AddAttackProcessInitialTime(new ReactiveVariable(3)) + .AddAttackProcessInitialTime(new ReactiveVariable(1)) .AddAttackProcessCurrentTime() .AddInAttackProcess() .AddStartAttackRequest() .AddStartAttackEvent() .AddEndAttackEvent() - .AddAttackDelayTime(new ReactiveVariable(2)) + .AddAttackDelayTime(new ReactiveVariable(1)) .AddAttackDelayEndEvent() .AddInstantAttackDamage(new ReactiveVariable(50)) .AddAttackCanceledEvent() @@ -102,9 +102,6 @@ namespace _Project.Develop.Runtime.Entities .AddMustCancelAttack(mustCancelAttack); entity - .AddSystem(new AttackByInputSystem(_playerInput)) - .AddSystem(new MoveDirectionByInputSystem(_playerInput)) - .AddSystem(new RotateDirectionByMoveInputSystem(_playerInput)) .AddSystem(new RigidbodyMovementSystem()) .AddSystem(new RigidbodyRotationSystem()) diff --git a/Assets/_Project/Develop/Runtime/Logic/Gameplay/Entities/Generated/EntityAPI.cs b/Assets/_Project/Develop/Runtime/Logic/Gameplay/Entities/Generated/EntityAPI.cs index 89d3721..11bcd0b 100644 --- a/Assets/_Project/Develop/Runtime/Logic/Gameplay/Entities/Generated/EntityAPI.cs +++ b/Assets/_Project/Develop/Runtime/Logic/Gameplay/Entities/Generated/EntityAPI.cs @@ -1682,5 +1682,29 @@ namespace _Project.Develop.Runtime.Entities return AddComponent(new _Project.Develop.Runtime.Logic.Gameplay.Features.Attack.InAttackCooldown() {Value = value}); } + public _Project.Develop.Runtime.Logic.Gameplay.Features.AI.CurrentTarget CurrentTargetC => GetComponent<_Project.Develop.Runtime.Logic.Gameplay.Features.AI.CurrentTarget>(); + + public _Project.Develop.Runtime.Utils.ReactiveManagement.ReactiveVariable<_Project.Develop.Runtime.Entities.Entity> CurrentTarget => CurrentTargetC.Value; + + public bool TryGetCurrentTarget(out _Project.Develop.Runtime.Utils.ReactiveManagement.ReactiveVariable<_Project.Develop.Runtime.Entities.Entity> value) + { + bool result = TryGetComponent(out _Project.Develop.Runtime.Logic.Gameplay.Features.AI.CurrentTarget component); + if(result) + value = component.Value; + else + value = default(_Project.Develop.Runtime.Utils.ReactiveManagement.ReactiveVariable<_Project.Develop.Runtime.Entities.Entity>); + return result; + } + + public _Project.Develop.Runtime.Entities.Entity AddCurrentTarget() + { + return AddComponent(new _Project.Develop.Runtime.Logic.Gameplay.Features.AI.CurrentTarget() { Value = new _Project.Develop.Runtime.Utils.ReactiveManagement.ReactiveVariable<_Project.Develop.Runtime.Entities.Entity>() }); + } + + public _Project.Develop.Runtime.Entities.Entity AddCurrentTarget(_Project.Develop.Runtime.Utils.ReactiveManagement.ReactiveVariable<_Project.Develop.Runtime.Entities.Entity> value) + { + return AddComponent(new _Project.Develop.Runtime.Logic.Gameplay.Features.AI.CurrentTarget() {Value = value}); + } + } } diff --git a/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/AIComponents.cs b/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/AIComponents.cs new file mode 100644 index 0000000..8eddd40 --- /dev/null +++ b/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/AIComponents.cs @@ -0,0 +1,7 @@ +using _Project.Develop.Runtime.Entities; +using _Project.Develop.Runtime.Utils.ReactiveManagement; + +namespace _Project.Develop.Runtime.Logic.Gameplay.Features.AI +{ + public class CurrentTarget : IEntityComponent { public ReactiveVariable Value; } +} \ No newline at end of file diff --git a/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/AIComponents.cs.meta b/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/AIComponents.cs.meta new file mode 100644 index 0000000..9cf08a1 --- /dev/null +++ b/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/AIComponents.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 78216e3102e549f39cb690e777d00e88 +timeCreated: 1772470309 \ No newline at end of file diff --git a/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/AIParallelState.cs b/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/AIParallelState.cs new file mode 100644 index 0000000..b750a11 --- /dev/null +++ b/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/AIParallelState.cs @@ -0,0 +1,16 @@ +using Assets._Project.Develop.Runtime.Utilities.StateMachineCore; + +namespace _Project.Develop.Runtime.Logic.Gameplay.Features.AI +{ + public class AIParallelState : ParallelState, IUpdatableState + { + public AIParallelState(params IUpdatableState[] states) : base(states) + { } + + public void Update(float deltaTime) + { + foreach (IUpdatableState state in States) + state.Update(deltaTime); + } + } +} \ No newline at end of file diff --git a/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/AIParallelState.cs.meta b/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/AIParallelState.cs.meta new file mode 100644 index 0000000..4c2afc8 --- /dev/null +++ b/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/AIParallelState.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d0ae2666ed0a43d590866fff4686222a +timeCreated: 1772538444 \ No newline at end of file diff --git a/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/BrainsFactory.cs b/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/BrainsFactory.cs index dbcf065..8b16b6f 100644 --- a/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/BrainsFactory.cs +++ b/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/BrainsFactory.cs @@ -3,8 +3,11 @@ 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 _Project.Develop.Runtime.Utils.InputManagement; +using _Project.Develop.Runtime.Utils.ReactiveManagement; using Assets._Project.Develop.Runtime.Infrastructure.DI; using Assets._Project.Develop.Runtime.Utilities.Timer; +using UnityEngine; namespace _Project.Develop.Runtime.Logic.Gameplay.Features.AI { @@ -12,14 +15,19 @@ namespace _Project.Develop.Runtime.Logic.Gameplay.Features.AI { private readonly DIContainer _container; + private readonly EntitiesLifeContext _entitiesLifeContext; private readonly AIBrainsContext _aiBrainsContext; private readonly TimerServiceFactory _timerServiceFactory; + private readonly IPlayerInput _playerInput; public BrainsFactory(DIContainer container) { _container = container; + + _playerInput = _container.Resolve(); _aiBrainsContext = _container.Resolve(); _timerServiceFactory = _container.Resolve(); + _entitiesLifeContext = _container.Resolve(); } public StateMachineBrain CreateGhostBrain(Entity entity) @@ -31,6 +39,43 @@ namespace _Project.Develop.Runtime.Logic.Gameplay.Features.AI return brain; } + + public StateMachineBrain CreateMainHeroBrain(Entity entity, ITargetSelector targetSelector) + { + AIStateMachine combatState = CreateAutoAttackStateMachine(entity); + PlayerInputMovementState movementState = new (entity, _playerInput); + + ReactiveVariable currentTarget = entity.CurrentTarget; + + ICompositeCondition fromMovementToCombatStateCondition = new CompositeCondition() + .Add(new FuncCondition(() => currentTarget.Value != null)) + .Add(new FuncCondition(() => _playerInput.Move.Value == Vector2.zero)); + + ICompositeCondition fromCombatToMovementStateCondition = new CompositeCondition(LogicOperationsUtils.Or) + .Add(new FuncCondition(() => currentTarget.Value == null)) + .Add(new FuncCondition(() => _playerInput.Move.Value != Vector2.zero)); + + AIStateMachine behaviour = new (); + + behaviour.AddState(combatState); + behaviour.AddState(movementState); + + behaviour.AddTransition(combatState, movementState, fromCombatToMovementStateCondition); + behaviour.AddTransition(movementState, combatState, fromMovementToCombatStateCondition); + + FindTargetState findTargetState = new (_entitiesLifeContext, entity, targetSelector); + AIParallelState parallelState = new (findTargetState, behaviour); + + AIStateMachine rootStateMachine = new (); + + rootStateMachine.AddState(parallelState); + + StateMachineBrain brain = new (rootStateMachine); + + _aiBrainsContext.SetFor(entity, brain); + + return brain; + } private AIStateMachine CreateRandomMovementStateMachine(Entity entity) { @@ -60,5 +105,46 @@ namespace _Project.Develop.Runtime.Logic.Gameplay.Features.AI return stateMachine; } + + private AIStateMachine CreateAutoAttackStateMachine(Entity entity) + { + RotateToTargetState rotateToTargetState = new (entity); + AttackTriggerState attackTriggerState = new (entity); + + ICondition canAttack = entity.CanStartAttack; + Transform transform = entity.Transform; + ReactiveVariable currentTarget = entity.CurrentTarget; + + ICompositeCondition fromRotateToAttackCondition = new CompositeCondition() + .Add(canAttack) + .Add(new FuncCondition(() => + { + Entity target = currentTarget.Value; + + if (target == null) + return false; + + float angleToTarget = Quaternion.Angle( + transform.rotation, + Quaternion.LookRotation(target.Transform.position - transform.position)); + + return angleToTarget < 1f; + } + )); + + ReactiveVariable inAttackProcess = entity.InAttackProcess; + + ICondition fromAttackToRotateStateCondition = new FuncCondition(() => inAttackProcess.Value == false); + + AIStateMachine stateMachine = new (); + + stateMachine.AddState(rotateToTargetState); + stateMachine.AddState(attackTriggerState); + + stateMachine.AddTransition(rotateToTargetState, attackTriggerState, fromRotateToAttackCondition); + stateMachine.AddTransition(attackTriggerState, rotateToTargetState, fromAttackToRotateStateCondition); + + return stateMachine; + } } } \ No newline at end of file diff --git a/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/States/AttackTriggerState.cs b/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/States/AttackTriggerState.cs new file mode 100644 index 0000000..0089f54 --- /dev/null +++ b/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/States/AttackTriggerState.cs @@ -0,0 +1,25 @@ +using _Project.Develop.Runtime.Entities; +using _Project.Develop.Runtime.Utils.ReactiveManagement.Event; +using Assets._Project.Develop.Runtime.Utilities.StateMachineCore; + +namespace _Project.Develop.Runtime.Logic.Gameplay.Features.AI.States +{ + public class AttackTriggerState : State, IUpdatableState + { + private ReactiveEvent _attackRequest; + + public AttackTriggerState(Entity entity) + { + _attackRequest = entity.StartAttackRequest; + } + + public override void Enter() + { + base.Enter(); + _attackRequest.Invoke(); + } + + public void Update(float deltaTime) + { } + } +} \ No newline at end of file diff --git a/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/States/AttackTriggerState.cs.meta b/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/States/AttackTriggerState.cs.meta new file mode 100644 index 0000000..8908bd9 --- /dev/null +++ b/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/States/AttackTriggerState.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 9d58a80b452346bda2d968af0f76fdfa +timeCreated: 1772469124 \ No newline at end of file diff --git a/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/States/FindTargetState.cs b/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/States/FindTargetState.cs new file mode 100644 index 0000000..2277956 --- /dev/null +++ b/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/States/FindTargetState.cs @@ -0,0 +1,28 @@ +using _Project.Develop.Runtime.Entities; +using _Project.Develop.Runtime.Utils.ReactiveManagement; +using Assets._Project.Develop.Runtime.Utilities.StateMachineCore; + +namespace _Project.Develop.Runtime.Logic.Gameplay.Features.AI.States +{ + public class FindTargetState : State, IUpdatableState + { + private ITargetSelector _targetSelector; + private EntitiesLifeContext _entitiesLifeContext; + private ReactiveVariable _currentTarget; + + public FindTargetState( + EntitiesLifeContext entitiesLifeContext, + Entity entity, + ITargetSelector targetSelector) + { + _currentTarget = entity.CurrentTarget; + _targetSelector = targetSelector; + _entitiesLifeContext = entitiesLifeContext; + } + + public void Update(float deltaTime) + { + _currentTarget.Value = _targetSelector.SelectTargetFrom(_entitiesLifeContext.Entities); + } + } +} \ No newline at end of file diff --git a/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/States/FindTargetState.cs.meta b/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/States/FindTargetState.cs.meta new file mode 100644 index 0000000..c4a32b8 --- /dev/null +++ b/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/States/FindTargetState.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 1c92a70ea84c48f49ae461eae381a1ce +timeCreated: 1772539593 \ No newline at end of file diff --git a/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/States/ITargetSelector.cs b/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/States/ITargetSelector.cs new file mode 100644 index 0000000..e22d626 --- /dev/null +++ b/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/States/ITargetSelector.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; +using _Project.Develop.Runtime.Entities; + +namespace _Project.Develop.Runtime.Logic.Gameplay.Features.AI.States +{ + public interface ITargetSelector + { + public Entity SelectTargetFrom(IEnumerable targets); + } +} \ No newline at end of file diff --git a/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/States/ITargetSelector.cs.meta b/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/States/ITargetSelector.cs.meta new file mode 100644 index 0000000..a6a76a4 --- /dev/null +++ b/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/States/ITargetSelector.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 15c5398fa2f84d109f74fbe2cd14bcda +timeCreated: 1772538651 \ No newline at end of file diff --git a/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/States/NearestDamageableTargetSelector.cs b/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/States/NearestDamageableTargetSelector.cs new file mode 100644 index 0000000..b77c8ae --- /dev/null +++ b/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/States/NearestDamageableTargetSelector.cs @@ -0,0 +1,64 @@ +using System.Collections.Generic; +using System.Linq; +using _Project.Develop.Runtime.Entities; +using _Project.Develop.Runtime.Logic.Gameplay.Features.Damage; +using _Project.Develop.Runtime.Utilities.Conditions; +using UnityEngine; + +namespace _Project.Develop.Runtime.Logic.Gameplay.Features.AI.States +{ + public class NearestDamageableTargetSelector : ITargetSelector + { + private readonly Entity _source; + private readonly Transform _sourceTransform; + + public NearestDamageableTargetSelector(Entity entity) + { + _source = entity; + _sourceTransform = entity.Transform; + } + + public Entity SelectTargetFrom(IEnumerable targets) + { + IEnumerable selectedTargets = FindSelectedTargets(targets); + + IEnumerable enumerable = selectedTargets.ToList(); + + if (enumerable.Any() == false) + return null; + + Entity closetsTarget = enumerable.First(); + float minDistance = GetDistanceTo(closetsTarget); + + foreach (Entity target in enumerable) + { + float distance = GetDistanceTo(target); + + if (distance < minDistance) + { + minDistance = distance; + closetsTarget = target; + } + } + + return closetsTarget; + } + + private IEnumerable FindSelectedTargets(IEnumerable targets) + { + return targets.Where(target => + { + bool result = target.HasComponent(); + + if (target.TryGetCanApplyDamage(out ICompositeCondition value)) + result = result && value.Evaluate(); + + result = result && (target != _source); + + return result; + }); + } + + private float GetDistanceTo(Entity target) => (_sourceTransform.position - target.Transform.position).magnitude; + } +} \ No newline at end of file diff --git a/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/States/NearestDamageableTargetSelector.cs.meta b/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/States/NearestDamageableTargetSelector.cs.meta new file mode 100644 index 0000000..66a19df --- /dev/null +++ b/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/States/NearestDamageableTargetSelector.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5efdb899e3ea4373b66f0610ea05b5c5 +timeCreated: 1772538727 \ No newline at end of file diff --git a/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/States/PlayerInputMovementState.cs b/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/States/PlayerInputMovementState.cs new file mode 100644 index 0000000..97d7215 --- /dev/null +++ b/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/States/PlayerInputMovementState.cs @@ -0,0 +1,37 @@ +using _Project.Develop.Runtime.Entities; +using _Project.Develop.Runtime.Utils.InputManagement; +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 PlayerInputMovementState : State, IUpdatableState + { + private readonly IPlayerInput _playerInput; + + private ReactiveVariable _rotateDirection; + private ReactiveVariable _moveDirection; + + public PlayerInputMovementState(Entity entity, IPlayerInput playerInput) + { + _playerInput = playerInput; + + _rotateDirection = entity.RotateDirection; + _moveDirection = entity.MoveDirection; + } + + public void Update(float deltaTime) + { + _moveDirection.Value = new Vector3(_playerInput.Move.Value.x, 0, _playerInput.Move.Value.y); + _rotateDirection.Value = new Vector3(_playerInput.Move.Value.x, 0, _playerInput.Move.Value.y); + } + + public override void Exit() + { + base.Exit(); + + _moveDirection.Value = Vector3.zero; + } + } +} \ No newline at end of file diff --git a/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/States/PlayerInputMovementState.cs.meta b/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/States/PlayerInputMovementState.cs.meta new file mode 100644 index 0000000..a478793 --- /dev/null +++ b/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/States/PlayerInputMovementState.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 449f5d14d62348c5a770bd34869f384f +timeCreated: 1772468559 \ No newline at end of file diff --git a/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/States/RotateToTargetState.cs b/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/States/RotateToTargetState.cs new file mode 100644 index 0000000..9b4ace6 --- /dev/null +++ b/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/States/RotateToTargetState.cs @@ -0,0 +1,28 @@ +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 RotateToTargetState : State, IUpdatableState + { + private ReactiveVariable _rotateDirection; + private ReactiveVariable _currentTarget; + + private Transform _transform; + + public RotateToTargetState(Entity entity) + { + _rotateDirection = entity.RotateDirection; + _currentTarget = entity.CurrentTarget; + _transform = entity.Transform; + } + + public void Update(float deltaTime) + { + if (_currentTarget.Value != null) + _rotateDirection.Value = (_currentTarget.Value.Transform.position - _transform.position).normalized; + } + } +} \ No newline at end of file diff --git a/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/States/RotateToTargetState.cs.meta b/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/States/RotateToTargetState.cs.meta new file mode 100644 index 0000000..2de22d9 --- /dev/null +++ b/Assets/_Project/Develop/Runtime/Logic/Gameplay/Features/AI/States/RotateToTargetState.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5a16d8f8d923476b9a5544d64f3b469e +timeCreated: 1772473180 \ No newline at end of file diff --git a/Assets/_Project/Develop/Runtime/Logic/Gameplay/Infrastructure/TestGameplay.cs b/Assets/_Project/Develop/Runtime/Logic/Gameplay/Infrastructure/TestGameplay.cs index f354e25..1a614c4 100644 --- a/Assets/_Project/Develop/Runtime/Logic/Gameplay/Infrastructure/TestGameplay.cs +++ b/Assets/_Project/Develop/Runtime/Logic/Gameplay/Infrastructure/TestGameplay.cs @@ -1,6 +1,7 @@ using System; using _Project.Develop.Runtime.Entities; using _Project.Develop.Runtime.Logic.Gameplay.Features.AI; +using _Project.Develop.Runtime.Logic.Gameplay.Features.AI.States; using _Project.Develop.Runtime.Utils.InputManagement; using Assets._Project.Develop.Runtime.Infrastructure.DI; using UnityEngine; @@ -29,9 +30,11 @@ namespace _Project.Develop.Runtime.Logic.Gameplay.Features public void Run() { - _hero = _entitiesFactory.CreateTeleportWizard(Vector3.zero); - _ghost = _entitiesFactory.CreateGhost(Vector3.zero + Vector3.forward * 5); + _hero = _entitiesFactory.CreateHero(Vector3.zero); + _hero.AddCurrentTarget(); + _brainsFactory.CreateMainHeroBrain(_hero, new NearestDamageableTargetSelector(_hero)); + _ghost = _entitiesFactory.CreateGhost(Vector3.zero + Vector3.forward * 5); _brainsFactory.CreateGhostBrain(_ghost); _isRunning = true; @@ -49,7 +52,7 @@ namespace _Project.Develop.Runtime.Logic.Gameplay.Features return; 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}"); + // GUI.Label(new Rect(10, 40, 200, 50), $"Energy: {_hero.CurrentEnergy.Value}/{_hero.MaxEnergy.Value}"); } } } \ No newline at end of file diff --git a/Assets/_Project/Develop/Runtime/Utilities/ReactiveManagement/Variable/ReactiveVariable.cs b/Assets/_Project/Develop/Runtime/Utilities/ReactiveManagement/Variable/ReactiveVariable.cs index f57cd91..5f6923a 100644 --- a/Assets/_Project/Develop/Runtime/Utilities/ReactiveManagement/Variable/ReactiveVariable.cs +++ b/Assets/_Project/Develop/Runtime/Utilities/ReactiveManagement/Variable/ReactiveVariable.cs @@ -3,18 +3,25 @@ using System.Collections.Generic; namespace _Project.Develop.Runtime.Utils.ReactiveManagement { - public class ReactiveVariable : IReadOnlyVariable where T : IEquatable + public class ReactiveVariable : IReadOnlyVariable { - private readonly List> _subscribers = new List>(); - private readonly List> _toAddList = new List>(); - private readonly List> _toRemoveList = new List>(); - - public ReactiveVariable() => _value = default(T); - - public ReactiveVariable(T value) => _value = value; + private readonly List> _subscribers = new (); + private readonly List> _toAddList = new (); + private readonly List> _toRemoveList = new (); private T _value; + private IEqualityComparer _comparer; + public ReactiveVariable() : this(default) { } + + public ReactiveVariable(T value) : this(value, EqualityComparer.Default){ } + + public ReactiveVariable(T value, IEqualityComparer comparer) + { + _value = value; + _comparer = comparer; + } + public T Value { get => _value; @@ -23,14 +30,14 @@ namespace _Project.Develop.Runtime.Utils.ReactiveManagement T oldValue = _value; _value = value; - if (_value.Equals(oldValue) == false) + if (_comparer.Equals(oldValue, value) == false) Invoke(oldValue, _value); } } public IDisposable Subscribe(Action action) { - Subscriber subscriber = new Subscriber(action, RemoveSubscriber); + Subscriber subscriber = new (action, RemoveSubscriber); _toAddList.Add(subscriber); return subscriber; diff --git a/Assets/_Project/Scenes/Gameplay.unity b/Assets/_Project/Scenes/Gameplay.unity index f00df5b..7197e67 100644 --- a/Assets/_Project/Scenes/Gameplay.unity +++ b/Assets/_Project/Scenes/Gameplay.unity @@ -654,8 +654,8 @@ Camera: near clip plane: 0.3 far clip plane: 1000 field of view: 60 - orthographic: 0 - orthographic size: 5 + orthographic: 1 + orthographic size: 14.12 m_Depth: -1 m_CullingMask: serializedVersion: 2 @@ -680,7 +680,7 @@ Transform: m_GameObject: {fileID: 1496566168} serializedVersion: 2 m_LocalRotation: {x: 0.34130225, y: -0, z: -0, w: 0.9399536} - m_LocalPosition: {x: 0, y: 11.01, z: -12.32} + m_LocalPosition: {x: -0.8, y: 41.4, z: -39.5} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: []