162 lines
9.8 KiB
C#
162 lines
9.8 KiB
C#
#if GRAPH_DESIGNER
|
|
/// ---------------------------------------------
|
|
/// Behavior Designer
|
|
/// Copyright (c) Opsive. All Rights Reserved.
|
|
/// https://www.opsive.com
|
|
/// ---------------------------------------------
|
|
namespace Opsive.BehaviorDesigner.Runtime.Utility
|
|
{
|
|
using Opsive.BehaviorDesigner.Runtime.Components;
|
|
using Unity.Collections;
|
|
using Unity.Entities;
|
|
|
|
/// <summary>
|
|
/// Utility functions that are used throughout the behavior tree execution.
|
|
/// </summary>
|
|
public static class ComponentUtility
|
|
{
|
|
/// <summary>
|
|
/// The size of a ulong in bits.
|
|
/// </summary>
|
|
public static int ulongBitSize => sizeof(ulong) * 8;
|
|
|
|
/// <summary>
|
|
/// Adds an evaluation component to the specified entity based on the task count and evaluation type.
|
|
/// </summary>
|
|
/// <param name="world">The ECS world to add the component to.</param>
|
|
/// <param name="entity">The entity to add the evaluation component to.</param>
|
|
/// <param name="taskCount">The total number of tasks in the behavior tree.</param>
|
|
/// <param name="evaluationType">The type of evaluation to perform.</param>
|
|
/// <param name="maxEvaluationCount">The maximum number of evaluations allowed.</param>
|
|
public static void AddEvaluationComponent(World world, Entity entity, int taskCount, EvaluationType evaluationType, int maxEvaluationCount)
|
|
{
|
|
// Both EvaluationType.EntireTree and EvaluationType.Count use a bitmask to track evaluated tasks.
|
|
// For Count mode, an additional element is reserved at the end to store the execution count.
|
|
var bitmaskElementCount = taskCount / ulongBitSize + 1;
|
|
var countModeExtraElement = evaluationType == EvaluationType.Count ? 1 : 0;
|
|
|
|
if (taskCount < 192) {
|
|
world.EntityManager.AddComponent<EvaluationComponent32>(entity);
|
|
var evaluatedTasks = new FixedList32Bytes<ulong>();
|
|
for (int i = 0; i < bitmaskElementCount + countModeExtraElement; ++i) {
|
|
evaluatedTasks.Add(0);
|
|
}
|
|
world.EntityManager.AddComponentData(entity, new EvaluationComponent32() { EvaluationType = evaluationType, MaxEvaluationCount = (ushort)UnityEngine.Mathf.Max(1, maxEvaluationCount), EvaluatedTasks = evaluatedTasks });
|
|
} else if (taskCount < 448) {
|
|
world.EntityManager.AddComponent<EvaluationComponent64>(entity);
|
|
var evaluatedTasks = new FixedList64Bytes<ulong>();
|
|
for (int i = 0; i < bitmaskElementCount + countModeExtraElement; ++i) {
|
|
evaluatedTasks.Add(0);
|
|
}
|
|
world.EntityManager.AddComponentData(entity, new EvaluationComponent64() { EvaluationType = evaluationType, MaxEvaluationCount = (ushort)UnityEngine.Mathf.Max(1, maxEvaluationCount), EvaluatedTasks = evaluatedTasks });
|
|
} else if (taskCount < 960) {
|
|
world.EntityManager.AddComponent<EvaluationComponent128>(entity);
|
|
var evaluatedTasks = new FixedList128Bytes<ulong>();
|
|
for (int i = 0; i < bitmaskElementCount + countModeExtraElement; ++i) {
|
|
evaluatedTasks.Add(0);
|
|
}
|
|
world.EntityManager.AddComponentData(entity, new EvaluationComponent128() { EvaluationType = evaluationType, MaxEvaluationCount = (ushort)UnityEngine.Mathf.Max(1, maxEvaluationCount), EvaluatedTasks = evaluatedTasks });
|
|
} else if (taskCount < 4032) {
|
|
world.EntityManager.AddComponent<EvaluationComponent512>(entity);
|
|
var evaluatedTasks = new FixedList512Bytes<ulong>();
|
|
for (int i = 0; i < bitmaskElementCount + countModeExtraElement; ++i) {
|
|
evaluatedTasks.Add(0);
|
|
}
|
|
world.EntityManager.AddComponentData(entity, new EvaluationComponent512() { EvaluationType = evaluationType, MaxEvaluationCount = (ushort)UnityEngine.Mathf.Max(1, maxEvaluationCount), EvaluatedTasks = evaluatedTasks });
|
|
} else if (taskCount < 32704) {
|
|
world.EntityManager.AddComponent<EvaluationComponent4096>(entity);
|
|
var evaluatedTasks = new FixedList4096Bytes<ulong>();
|
|
for (int i = 0; i < bitmaskElementCount + countModeExtraElement; ++i) {
|
|
evaluatedTasks.Add(0);
|
|
}
|
|
world.EntityManager.AddComponentData(entity, new EvaluationComponent4096() { EvaluationType = evaluationType, MaxEvaluationCount = (ushort)UnityEngine.Mathf.Max(1, maxEvaluationCount), EvaluatedTasks = evaluatedTasks });
|
|
} else {
|
|
UnityEngine.Debug.LogError("Error: Trees with more than 32,703 tasks are not supported. Please email support@opsive.com.");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Resets the evaluation component data for the specified entity by clearing all evaluated task flags.
|
|
/// </summary>
|
|
/// <param name="world">The ECS world containing the entity.</param>
|
|
/// <param name="entity">The entity whose evaluation component should be reset.</param>
|
|
public static void ResetEvaluationComponent(World world, Entity entity)
|
|
{
|
|
if (world.EntityManager.HasComponent<EvaluationComponent32>(entity)) {
|
|
var evaluateComponent = world.EntityManager.GetComponentData<EvaluationComponent32>(entity);
|
|
var evaluatedTasks = evaluateComponent.EvaluatedTasks;
|
|
for (int i = 0; i < evaluatedTasks.Length; ++i) {
|
|
evaluatedTasks[i] = 0;
|
|
}
|
|
evaluateComponent.EvaluatedTasks = evaluatedTasks;
|
|
world.EntityManager.SetComponentData(entity, evaluateComponent);
|
|
} else if (world.EntityManager.HasComponent<EvaluationComponent64>(entity)) {
|
|
var evaluateComponent = world.EntityManager.GetComponentData<EvaluationComponent64>(entity);
|
|
var evaluatedTasks = evaluateComponent.EvaluatedTasks;
|
|
for (int i = 0; i < evaluatedTasks.Length; ++i) {
|
|
evaluatedTasks[i] = 0;
|
|
}
|
|
evaluateComponent.EvaluatedTasks = evaluatedTasks;
|
|
world.EntityManager.SetComponentData(entity, evaluateComponent);
|
|
} else if (world.EntityManager.HasComponent<EvaluationComponent128>(entity)) {
|
|
var evaluateComponent = world.EntityManager.GetComponentData<EvaluationComponent128>(entity);
|
|
var evaluatedTasks = evaluateComponent.EvaluatedTasks;
|
|
for (int i = 0; i < evaluatedTasks.Length; ++i) {
|
|
evaluatedTasks[i] = 0;
|
|
}
|
|
evaluateComponent.EvaluatedTasks = evaluatedTasks;
|
|
world.EntityManager.SetComponentData(entity, evaluateComponent);
|
|
} else if (world.EntityManager.HasComponent<EvaluationComponent512>(entity)) {
|
|
var evaluateComponent = world.EntityManager.GetComponentData<EvaluationComponent512>(entity);
|
|
var evaluatedTasks = evaluateComponent.EvaluatedTasks;
|
|
for (int i = 0; i < evaluatedTasks.Length; ++i) {
|
|
evaluatedTasks[i] = 0;
|
|
}
|
|
evaluateComponent.EvaluatedTasks = evaluatedTasks;
|
|
world.EntityManager.SetComponentData(entity, evaluateComponent);
|
|
} else if (world.EntityManager.HasComponent<EvaluationComponent4096>(entity)) {
|
|
var evaluateComponent = world.EntityManager.GetComponentData<EvaluationComponent4096>(entity);
|
|
var evaluatedTasks = evaluateComponent.EvaluatedTasks;
|
|
for (int i = 0; i < evaluatedTasks.Length; ++i) {
|
|
evaluatedTasks[i] = 0;
|
|
}
|
|
evaluateComponent.EvaluatedTasks = evaluatedTasks;
|
|
world.EntityManager.SetComponentData(entity, evaluateComponent);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Removes the evaluation component from the specified entity.
|
|
/// </summary>
|
|
/// <param name="world">The ECS world containing the entity.</param>
|
|
/// <param name="entity">The entity whose evaluation component should be removed.</param>
|
|
public static void RemoveEvaluationComponent(World world, Entity entity)
|
|
{
|
|
if (world.EntityManager.HasComponent<EvaluationComponent32>(entity)) {
|
|
world.EntityManager.RemoveComponent<EvaluationComponent32>(entity);
|
|
} else if (world.EntityManager.HasComponent<EvaluationComponent64>(entity)) {
|
|
world.EntityManager.RemoveComponent<EvaluationComponent64>(entity);
|
|
} else if (world.EntityManager.HasComponent<EvaluationComponent128>(entity)) {
|
|
world.EntityManager.RemoveComponent<EvaluationComponent128>(entity);
|
|
} else if (world.EntityManager.HasComponent<EvaluationComponent512>(entity)) {
|
|
world.EntityManager.RemoveComponent<EvaluationComponent512>(entity);
|
|
} else if (world.EntityManager.HasComponent<EvaluationComponent4096>(entity)) {
|
|
world.EntityManager.RemoveComponent<EvaluationComponent4096>(entity);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds the components necessary in order to trigger an interrupt.
|
|
/// </summary>
|
|
/// <param name="entityManager">The EntityManager that the entity belongs to.</param>
|
|
/// <param name="entity">The entity that should have the components added.</param>
|
|
public static void AddInterruptComponents(EntityManager entityManager, Entity entity)
|
|
{
|
|
entityManager.AddComponent<InterruptFlag>(entity);
|
|
entityManager.SetComponentEnabled<InterruptFlag>(entity, false);
|
|
entityManager.AddComponent<InterruptedFlag>(entity);
|
|
entityManager.SetComponentEnabled<InterruptedFlag>(entity, false);
|
|
}
|
|
}
|
|
}
|
|
#endif |