feat: add sensors

This commit is contained in:
Bragin Stepan
2026-02-20 00:18:03 +05:00
parent 1a067a3563
commit 6e04b47ac2
17 changed files with 356 additions and 2 deletions

View File

@@ -1,6 +1,8 @@
using _Project.Develop.Runtime.Logic.Gameplay.Features.Damage;
using _Project.Develop.Runtime.Logic.Gameplay.Features.Lifetime.Systems;
using _Project.Develop.Runtime.Logic.Gameplay.Features.Movement;
using _Project.Develop.Runtime.Logic.Gameplay.Features.Sensors.Systems;
using _Project.Develop.Runtime.Utilities;
using _Project.Develop.Runtime.Utilities.Conditions;
using _Project.Develop.Runtime.Utils.InputManagement;
using _Project.Develop.Runtime.Utils.ReactiveManagement;
@@ -14,10 +16,12 @@ namespace _Project.Develop.Runtime.Entities
{
private readonly EntitiesLifeContext _entitiesLifeContext;
private readonly MonoEntitiesFactory _monoEntitiesFactory;
private readonly CollidersRegistryService _collidersRegistryService;
private readonly IPlayerInput _playerInput;
public EntitiesFactory(DIContainer container)
{
_collidersRegistryService = container.Resolve<CollidersRegistryService>();
_entitiesLifeContext = container.Resolve<EntitiesLifeContext>();
_monoEntitiesFactory = container.Resolve<MonoEntitiesFactory>();
_playerInput = container.Resolve<IPlayerInput>();
@@ -30,6 +34,9 @@ namespace _Project.Develop.Runtime.Entities
_monoEntitiesFactory.Create(entity, position, PathToResources.Entity.Ghost);
entity
.AddContactsDetectingMask(Layers.CharactersMask)
.AddContactCollidersBuffer(new Buffer<Collider>(64))
.AddContactEntitiesBuffer(new Buffer<Entity>(64))
.AddMoveDirection()
.AddRotateDirection()
.AddMoveSpeed(new ReactiveVariable<float>(10))
@@ -69,10 +76,12 @@ namespace _Project.Develop.Runtime.Entities
entity
.AddSystem(new ApplyDamageSystem())
.AddSystem(new RigidbodyMovementSystem())
.AddSystem(new RigidbodyRotationSystem())
.AddSystem(new BodyContactsDetectingSystem())
.AddSystem(new BodyContactsEntitiesFilterSystem(_collidersRegistryService))
.AddSystem(new MoveDirectionByInputSystem(_playerInput))
.AddSystem(new RotateDirectionByInputSystem(_playerInput))
.AddSystem(new RigidbodyMovementSystem())
.AddSystem(new RigidbodyRotationSystem())
.AddSystem(new DeathSwitcherSystem())
.AddSystem(new DeathProcessTimerSystem())
.AddSystem(new SelfReleaseSystem(_entitiesLifeContext));

View File

@@ -78,6 +78,149 @@ namespace _Project.Develop.Runtime.Entities
return AddComponent(new Assets._Project.Develop.Runtime.Gameplay.Common.NavMeshAgentComponent() {Value = value});
}
public _Project.Develop.Runtime.Logic.Gameplay.Features.Sensors.CapsuleColliderComponent CapsuleColliderC => GetComponent<_Project.Develop.Runtime.Logic.Gameplay.Features.Sensors.CapsuleColliderComponent>();
public UnityEngine.CapsuleCollider CapsuleCollider => CapsuleColliderC.Value;
public bool TryGetCapsuleCollider(out UnityEngine.CapsuleCollider value)
{
bool result = TryGetComponent(out _Project.Develop.Runtime.Logic.Gameplay.Features.Sensors.CapsuleColliderComponent component);
if(result)
value = component.Value;
else
value = default(UnityEngine.CapsuleCollider);
return result;
}
public _Project.Develop.Runtime.Entities.Entity AddCapsuleCollider(UnityEngine.CapsuleCollider value)
{
return AddComponent(new _Project.Develop.Runtime.Logic.Gameplay.Features.Sensors.CapsuleColliderComponent() {Value = value});
}
public _Project.Develop.Runtime.Logic.Gameplay.Features.Sensors.ContactsDetectingMask ContactsDetectingMaskC => GetComponent<_Project.Develop.Runtime.Logic.Gameplay.Features.Sensors.ContactsDetectingMask>();
public UnityEngine.LayerMask ContactsDetectingMask => ContactsDetectingMaskC.Value;
public bool TryGetContactsDetectingMask(out UnityEngine.LayerMask value)
{
bool result = TryGetComponent(out _Project.Develop.Runtime.Logic.Gameplay.Features.Sensors.ContactsDetectingMask component);
if(result)
value = component.Value;
else
value = default(UnityEngine.LayerMask);
return result;
}
public _Project.Develop.Runtime.Entities.Entity AddContactsDetectingMask(UnityEngine.LayerMask value)
{
return AddComponent(new _Project.Develop.Runtime.Logic.Gameplay.Features.Sensors.ContactsDetectingMask() {Value = value});
}
public _Project.Develop.Runtime.Logic.Gameplay.Features.Sensors.ContactCollidersBuffer ContactCollidersBufferC => GetComponent<_Project.Develop.Runtime.Logic.Gameplay.Features.Sensors.ContactCollidersBuffer>();
public _Project.Develop.Runtime.Utilities.Buffer<UnityEngine.Collider> ContactCollidersBuffer => ContactCollidersBufferC.Value;
public bool TryGetContactCollidersBuffer(out _Project.Develop.Runtime.Utilities.Buffer<UnityEngine.Collider> value)
{
bool result = TryGetComponent(out _Project.Develop.Runtime.Logic.Gameplay.Features.Sensors.ContactCollidersBuffer component);
if(result)
value = component.Value;
else
value = default(_Project.Develop.Runtime.Utilities.Buffer<UnityEngine.Collider>);
return result;
}
public _Project.Develop.Runtime.Entities.Entity AddContactCollidersBuffer(_Project.Develop.Runtime.Utilities.Buffer<UnityEngine.Collider> value)
{
return AddComponent(new _Project.Develop.Runtime.Logic.Gameplay.Features.Sensors.ContactCollidersBuffer() {Value = value});
}
public _Project.Develop.Runtime.Logic.Gameplay.Features.Sensors.ContactEntitiesBuffer ContactEntitiesBufferC => GetComponent<_Project.Develop.Runtime.Logic.Gameplay.Features.Sensors.ContactEntitiesBuffer>();
public _Project.Develop.Runtime.Utilities.Buffer<_Project.Develop.Runtime.Entities.Entity> ContactEntitiesBuffer => ContactEntitiesBufferC.Value;
public bool TryGetContactEntitiesBuffer(out _Project.Develop.Runtime.Utilities.Buffer<_Project.Develop.Runtime.Entities.Entity> value)
{
bool result = TryGetComponent(out _Project.Develop.Runtime.Logic.Gameplay.Features.Sensors.ContactEntitiesBuffer component);
if(result)
value = component.Value;
else
value = default(_Project.Develop.Runtime.Utilities.Buffer<_Project.Develop.Runtime.Entities.Entity>);
return result;
}
public _Project.Develop.Runtime.Entities.Entity AddContactEntitiesBuffer(_Project.Develop.Runtime.Utilities.Buffer<_Project.Develop.Runtime.Entities.Entity> value)
{
return AddComponent(new _Project.Develop.Runtime.Logic.Gameplay.Features.Sensors.ContactEntitiesBuffer() {Value = value});
}
public _Project.Develop.Runtime.Logic.Gameplay.Features.Sensors.DeathMask DeathMaskC => GetComponent<_Project.Develop.Runtime.Logic.Gameplay.Features.Sensors.DeathMask>();
public UnityEngine.LayerMask DeathMask => DeathMaskC.Value;
public bool TryGetDeathMask(out UnityEngine.LayerMask value)
{
bool result = TryGetComponent(out _Project.Develop.Runtime.Logic.Gameplay.Features.Sensors.DeathMask component);
if(result)
value = component.Value;
else
value = default(UnityEngine.LayerMask);
return result;
}
public _Project.Develop.Runtime.Entities.Entity AddDeathMask(UnityEngine.LayerMask value)
{
return AddComponent(new _Project.Develop.Runtime.Logic.Gameplay.Features.Sensors.DeathMask() {Value = value});
}
public _Project.Develop.Runtime.Logic.Gameplay.Features.Sensors.IsTouchDeathMask IsTouchDeathMaskC => GetComponent<_Project.Develop.Runtime.Logic.Gameplay.Features.Sensors.IsTouchDeathMask>();
public _Project.Develop.Runtime.Utils.ReactiveManagement.ReactiveVariable<System.Boolean> IsTouchDeathMask => IsTouchDeathMaskC.Value;
public bool TryGetIsTouchDeathMask(out _Project.Develop.Runtime.Utils.ReactiveManagement.ReactiveVariable<System.Boolean> value)
{
bool result = TryGetComponent(out _Project.Develop.Runtime.Logic.Gameplay.Features.Sensors.IsTouchDeathMask component);
if(result)
value = component.Value;
else
value = default(_Project.Develop.Runtime.Utils.ReactiveManagement.ReactiveVariable<System.Boolean>);
return result;
}
public _Project.Develop.Runtime.Entities.Entity AddIsTouchDeathMask()
{
return AddComponent(new _Project.Develop.Runtime.Logic.Gameplay.Features.Sensors.IsTouchDeathMask() { Value = new _Project.Develop.Runtime.Utils.ReactiveManagement.ReactiveVariable<System.Boolean>() });
}
public _Project.Develop.Runtime.Entities.Entity AddIsTouchDeathMask(_Project.Develop.Runtime.Utils.ReactiveManagement.ReactiveVariable<System.Boolean> value)
{
return AddComponent(new _Project.Develop.Runtime.Logic.Gameplay.Features.Sensors.IsTouchDeathMask() {Value = value});
}
public _Project.Develop.Runtime.Logic.Gameplay.Features.Sensors.IsTouchAnotherTeam IsTouchAnotherTeamC => GetComponent<_Project.Develop.Runtime.Logic.Gameplay.Features.Sensors.IsTouchAnotherTeam>();
public _Project.Develop.Runtime.Utils.ReactiveManagement.ReactiveVariable<System.Boolean> IsTouchAnotherTeam => IsTouchAnotherTeamC.Value;
public bool TryGetIsTouchAnotherTeam(out _Project.Develop.Runtime.Utils.ReactiveManagement.ReactiveVariable<System.Boolean> value)
{
bool result = TryGetComponent(out _Project.Develop.Runtime.Logic.Gameplay.Features.Sensors.IsTouchAnotherTeam component);
if(result)
value = component.Value;
else
value = default(_Project.Develop.Runtime.Utils.ReactiveManagement.ReactiveVariable<System.Boolean>);
return result;
}
public _Project.Develop.Runtime.Entities.Entity AddIsTouchAnotherTeam()
{
return AddComponent(new _Project.Develop.Runtime.Logic.Gameplay.Features.Sensors.IsTouchAnotherTeam() { Value = new _Project.Develop.Runtime.Utils.ReactiveManagement.ReactiveVariable<System.Boolean>() });
}
public _Project.Develop.Runtime.Entities.Entity AddIsTouchAnotherTeam(_Project.Develop.Runtime.Utils.ReactiveManagement.ReactiveVariable<System.Boolean> value)
{
return AddComponent(new _Project.Develop.Runtime.Logic.Gameplay.Features.Sensors.IsTouchAnotherTeam() {Value = value});
}
public _Project.Develop.Runtime.Logic.Gameplay.Features.Lifetime.CurrentHealth CurrentHealthC => GetComponent<_Project.Develop.Runtime.Logic.Gameplay.Features.Lifetime.CurrentHealth>();
public _Project.Develop.Runtime.Utils.ReactiveManagement.ReactiveVariable<System.Single> CurrentHealth => CurrentHealthC.Value;

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6859effc3b144554aef3ab59218b3d6e
timeCreated: 1771526800

View File

@@ -0,0 +1,15 @@
using _Project.Develop.Runtime.Entities;
using UnityEngine;
namespace _Project.Develop.Runtime.Logic.Gameplay.Features.Sensors
{
public class CapsuleColliderRegistratorEntityRegistrator : MonoEntityRegistrator
{
[SerializeField] private CapsuleCollider _collider;
public override void Register(Entity entity)
{
entity.AddCapsuleCollider(_collider);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 72015d8dc01449c1b86801cc47ccd4a1
timeCreated: 1771527211

View File

@@ -0,0 +1,21 @@
using _Project.Develop.Runtime.Entities;
using _Project.Develop.Runtime.Utilities;
using _Project.Develop.Runtime.Utils.ReactiveManagement;
using UnityEngine;
namespace _Project.Develop.Runtime.Logic.Gameplay.Features.Sensors
{
public class CapsuleColliderComponent : IEntityComponent { public CapsuleCollider Value; }
public class ContactsDetectingMask : IEntityComponent { public LayerMask Value; }
public class ContactCollidersBuffer : IEntityComponent { public Buffer<Collider> Value; }
public class ContactEntitiesBuffer : IEntityComponent { public Buffer<Entity> Value; }
public class DeathMask : IEntityComponent { public LayerMask Value; }
public class IsTouchDeathMask : IEntityComponent { public ReactiveVariable<bool> Value; }
public class IsTouchAnotherTeam : IEntityComponent { public ReactiveVariable<bool> Value; }
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 97c125dd14164d1abb97f7b6e9491ffb
timeCreated: 1771526845

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0b6ed068a8dd402780ef9c958b1e62e8
timeCreated: 1771526830

View File

@@ -0,0 +1,58 @@
using _Project.Develop.Runtime.Entities;
using _Project.Develop.Runtime.Utilities;
using UnityEngine;
namespace _Project.Develop.Runtime.Logic.Gameplay.Features.Sensors.Systems
{
public class BodyContactsDetectingSystem : IInitializableSystem, IUpdatableSystem
{
private Buffer<Collider> _contacts;
private LayerMask _mask;
private CapsuleCollider _body;
public void OnInit(Entity entity)
{
_contacts = entity.ContactCollidersBuffer;
_mask = entity.ContactsDetectingMask;
_body = entity.CapsuleCollider;
}
// потом перенести в fixed
public void OnUpdate(float deltaTime)
{
_contacts.Count = Physics.OverlapCapsuleNonAlloc(
_body.bounds.min,
_body.bounds.max,
_body.radius,
_contacts.Items,
_mask,
QueryTriggerInteraction.Ignore);
RemoveSelfFromContacts();
}
private void RemoveSelfFromContacts()
{
int indexToRemove = -1;
for (int i = 0; i < _contacts.Count; i++)
{
if (_contacts.Items[i] == _body)
{
indexToRemove = i;
break;
}
}
if (indexToRemove >= 0)
{
for (int i = indexToRemove; i < _contacts.Count - 1; i++)
_contacts.Items[i] = _contacts.Items[i + 1];
_contacts.Count--;
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 49c5315e5a484456b5f0544204cd73ef
timeCreated: 1771527550

View File

@@ -0,0 +1,43 @@
using _Project.Develop.Runtime.Entities;
using _Project.Develop.Runtime.Utilities;
using UnityEngine;
namespace _Project.Develop.Runtime.Logic.Gameplay.Features.Sensors.Systems
{
public class BodyContactsEntitiesFilterSystem : IInitializableSystem, IUpdatableSystem
{
private Buffer<Collider> _contacts;
private Buffer<Entity> _contactsEntities;
private readonly CollidersRegistryService _collidersRegistryService;
public BodyContactsEntitiesFilterSystem(CollidersRegistryService collidersRegistryService)
{
_collidersRegistryService = collidersRegistryService;
}
public void OnInit(Entity entity)
{
_contacts = entity.ContactCollidersBuffer;
_contactsEntities = entity.ContactEntitiesBuffer;
}
public void OnUpdate(float deltaTime)
{
_contactsEntities.Count = 0;
for (int i = 0; i < _contacts.Count; i++)
{
Collider collider = _contacts.Items[i];
Entity contactEntity = _collidersRegistryService.GetBy(collider);
if(contactEntity != null)
{
_contactsEntities.Items[_contactsEntities.Count] = contactEntity;
_contactsEntities.Count++;
}
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0b49c1d778ab446ebc5f01f15fb97d41
timeCreated: 1771527927

View File

@@ -0,0 +1,14 @@
namespace _Project.Develop.Runtime.Utilities
{
public class Buffer<T>
{
public T[] Items;
public int Count;
public Buffer(int initialSize)
{
Items = new T[initialSize];
Count = 0;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 29473d664e014a86b3257246837569ce
timeCreated: 1771526615

View File

@@ -0,0 +1,13 @@
using UnityEngine;
namespace _Project.Develop.Runtime.Utilities
{
public static class Layers
{
public static readonly int Characters = LayerMask.NameToLayer("Characters");
public static readonly LayerMask CharactersMask = 1 << Characters;
public static readonly int Environment = LayerMask.NameToLayer("Environment");
public static readonly LayerMask EnvironmentMask = 1 << Environment;
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 49a6848819fd4acb8663089ef8f00659
timeCreated: 1771526630

View File

@@ -97,6 +97,7 @@ GameObject:
- component: {fileID: 7031502133547492830}
- component: {fileID: 6565447619237781124}
- component: {fileID: 8643992716899077862}
- component: {fileID: 8777523951741640921}
m_Layer: 0
m_Name: Ghost
m_TagString: Untagged
@@ -206,6 +207,19 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: b3d77209b50f4ecf9185ae250a76b909, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!114 &8777523951741640921
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6344150908040749382}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 72015d8dc01449c1b86801cc47ccd4a1, type: 3}
m_Name:
m_EditorClassIdentifier:
_collider: {fileID: 994812354150526974}
--- !u!1 &7421563490521616768
GameObject:
m_ObjectHideFlags: 0