/// --------------------------------------------- /// Behavior Designer /// Copyright (c) Opsive. All Rights Reserved. /// https://www.opsive.com /// --------------------------------------------- namespace Opsive.BehaviorDesigner.Samples { using System; using Unity.Burst; using Unity.Entities; using Unity.Mathematics; using Unity.Transforms; /// /// Specifies the entity agents. /// public struct AgentTag : IComponentData { } /// /// Marks the object for destruction. /// public struct DestroyEntityTag : IComponentData { } /// /// Destroys the tagged entities after the behavior tree simulation has run. /// [DisableAutoCreation] public partial class DestroyEntitySystem : SystemBase { public Action OnDestroyEntity; /// /// Destroys the entities tagged with the DestroyTag. /// protected override void OnUpdate() { var ecb = new EntityCommandBuffer(Unity.Collections.Allocator.Temp); foreach (var (destroyTag, localTransform, entity) in SystemAPI.Query().WithEntityAccess()) { ecb.DestroyEntity(entity); OnDestroyEntity?.Invoke(localTransform.Position); } ecb.Playback(EntityManager); ecb.Dispose(); } } /// /// Specifies the entity that is the rotating part of the turret. /// public struct TurretTag : IComponentData { } /// /// Specifies the entity that is the base of the turret. This entity should be destroyed at the same time as the turret's gun. /// public struct TurretBaseTag : IComponentData { } /// /// Component for pulling back the turret when it fires a bullet. /// public struct TurretRecoil : IComponentData, IEnableableComponent { [UnityEngine.Tooltip("Is the recoil pulling back the turret?")] public bool Pullback; [UnityEngine.Tooltip("The speed of the recoil pullback.")] public float PullbackPosition; [UnityEngine.Tooltip("The target z position of the recoil pullback.")] public float PullbackSpeed; } /// /// Destroys the tagged entities after the behavior tree simulation has run. /// [DisableAutoCreation] public partial struct TurretRecoilSystem : ISystem { /// /// Destroys the entities tagged with the DestroyTag. /// [BurstCompile] private void OnUpdate(ref SystemState state) { var ecb = new EntityCommandBuffer(Unity.Collections.Allocator.Temp); var deltaTime = SystemAPI.Time.DeltaTime; foreach (var (turretRecoil, localTransform, entity) in SystemAPI.Query, RefRW>().WithEntityAccess()) { var position = localTransform.ValueRO.Position; position.z = MoveTowards(localTransform.ValueRO.Position.z, turretRecoil.ValueRO.Pullback ? turretRecoil.ValueRO.PullbackPosition : 0, turretRecoil.ValueRO.PullbackSpeed * deltaTime); localTransform.ValueRW.Position = position; if (turretRecoil.ValueRO.Pullback && math.abs(position.z - turretRecoil.ValueRO.PullbackPosition) <= 0.01f) { turretRecoil.ValueRW.Pullback = false; ecb.SetComponentEnabled(entity, false); } else if (!turretRecoil.ValueRO.Pullback && math.abs(position.z) <= 0.01f) { turretRecoil.ValueRW.Pullback = true; ecb.SetComponentEnabled(entity, false); } } ecb.Playback(state.EntityManager); ecb.Dispose(); } /// /// Moves towards the target limited by the maximum distance. /// /// The current value. /// The target value. /// The maximum distance that the delta value can move. /// The move towards value. [BurstCompile] private static float MoveTowards(float current, float target, float maxDistanceDelta) { var delta = target - current; if (math.abs(delta) <= maxDistanceDelta) { return target; } return current + maxDistanceDelta * math.sign(delta); } } }