/// --------------------------------------------- /// Behavior Designer /// Copyright (c) Opsive. All Rights Reserved. /// https://www.opsive.com /// --------------------------------------------- namespace Opsive.BehaviorDesigner.Samples { using Opsive.BehaviorDesigner.Runtime.Components; using Opsive.BehaviorDesigner.Runtime.Tasks; using Unity.Burst; using Unity.Entities; using Unity.Transforms; using UnityEngine; [Opsive.Shared.Utility.Description("Uses DOTS to determine if the turret is still alive.")] [Shared.Utility.Category("Behavior Designer Samples/DOTS")] public class IsTurretAlive : ECSConditionalTask, IReevaluateResponder { public ComponentType ReevaluateFlag { get => typeof(IsTurretAliveReevaluateFlag); } public System.Type ReevaluateSystemType { get => typeof(IsTurretAliveReevaluateTaskSystem); } /// /// Returns a new TBufferElement for use by the system. /// /// A new TBufferElement for use by the system. public override IsTurretAliveComponent GetBufferElement() { return new IsTurretAliveComponent() { Index = RuntimeIndex, }; } } /// /// The DOTS data structure for the IsTurretAlive struct. /// public struct IsTurretAliveComponent : IBufferElementData { [Tooltip("The index of the node.")] public ushort Index; } /// /// A DOTS flag indicating when a IsTurretAlive node is active. /// public struct IsTurretAliveFlag : IComponentData, IEnableableComponent { } /// /// Runs the IsTurretAlive logic. /// [DisableAutoCreation] public partial struct IsTurretAliveTaskSystem : ISystem { /// /// Updates the logic. /// /// The current state of the system. [BurstCompile] private void OnUpdate(ref SystemState state) { // Find the turret. An entity will be found if the turret hasn't been destroyed. var isTurretAlive = false; foreach (var localTransform in SystemAPI.Query>().WithAll()) { isTurretAlive = true; break; } foreach (var (branchComponents, taskComponents, isTurretAliveComponents) in SystemAPI.Query, DynamicBuffer, DynamicBuffer>().WithAll()) { for (int i = 0; i < isTurretAliveComponents.Length; ++i) { var isTurretAliveComponent = isTurretAliveComponents[i]; var taskComponent = taskComponents[isTurretAliveComponent.Index]; var branchComponent = branchComponents[taskComponent.BranchIndex]; if (!branchComponent.CanExecute) { continue; } if (taskComponent.Status != TaskStatus.Queued) { continue; } taskComponent.Status = isTurretAlive ? TaskStatus.Success : TaskStatus.Failure; var taskComponentBuffer = taskComponents; taskComponentBuffer[isTurretAliveComponent.Index] = taskComponent; } } } } /// /// A DOTS tag indicating when an IsTurretAlive node needs to be reevaluated. /// public struct IsTurretAliveReevaluateFlag : IComponentData, IEnableableComponent { } /// /// Runs the IsTurretAlive reevaluation logic. /// [DisableAutoCreation] public partial struct IsTurretAliveReevaluateTaskSystem : ISystem { /// /// Updates the reevaluation logic. /// /// The current state of the system. [BurstCompile] private void OnUpdate(ref SystemState state) { // Find the turret. An entity will be found if the turret hasn't been destroyed. var isTurretAlive = false; foreach (var localTransform in SystemAPI.Query>().WithAll()) { isTurretAlive = true; break; } foreach (var (branchComponents, taskComponents, isTurretAliveComponents) in SystemAPI.Query, DynamicBuffer, DynamicBuffer>().WithAll()) { for (int i = 0; i < isTurretAliveComponents.Length; ++i) { var isTurretAliveComponent = isTurretAliveComponents[i]; var taskComponent = taskComponents[isTurretAliveComponent.Index]; var branchComponent = branchComponents[taskComponent.BranchIndex]; if (!branchComponent.CanExecute) { continue; } if (!taskComponent.Reevaluate) { continue; } var status = isTurretAlive ? TaskStatus.Success : TaskStatus.Failure; if (status != taskComponent.Status) { taskComponent.Status = status; var buffer = taskComponents; buffer[taskComponent.Index] = taskComponent; } } } } } }