ProjectDDD/Packages/com.opsive.behaviordesigner/Runtime/Components/BakedBehaviorTree.cs

109 lines
5.3 KiB
C#
Raw Normal View History

2025-08-19 09:53:26 +00:00
#if GRAPH_DESIGNER
/// ---------------------------------------------
/// Behavior Designer
/// Copyright (c) Opsive. All Rights Reserved.
/// https://www.opsive.com
/// ---------------------------------------------
namespace Opsive.BehaviorDesigner.Runtime.Components
{
using Opsive.BehaviorDesigner.Runtime.Groups;
using Unity.Entities;
using UnityEngine;
/// <summary>
/// Indicates that the behavior tree was baked.
/// </summary>
public class BakedBehaviorTree : IComponentData
{
[Tooltip("The index of the connected start task.")]
public int StartEventConnectedIndex;
[Tooltip("Should the behavior tree be started after it has been baked?")]
public bool StartEvaluation;
[Tooltip("The indicies of the reevaluate task systems.")]
public string[] ReevaluateTaskSystems;
[Tooltip("The indicies of the interrupt task systems.")]
public string[] InterruptTaskSystems;
[Tooltip("The indicies of the traversal task systems.")]
public string[] TraversalTaskSystems;
[Tooltip("The hashes that correspond to the TaskComponent's ComponentType.")]
public ulong[] TagStableTypeHashes;
[Tooltip("The hashes that correspond to the ReevaluateTaskComponent's ComponentType.")]
public ulong[] ReevaluateTagStableTypeHashes;
}
/// <summary>
/// The behavior tree has been baked. Start the tree using the baked data.
/// </summary>
public partial struct StartBakedBehaviorTreeSystem : ISystem
{
/// <summary>
/// Restricts when the system should run.
/// </summary>
/// <param name="state">The current SystemState.</param>
private void OnCreate(ref SystemState state)
{
state.RequireForUpdate<BakedBehaviorTree>();
state.Enabled = false;
}
/// <summary>
/// Starts the baked behavior tree.
/// </summary>
/// <param name="state">The current SystemState.</param>
private void OnUpdate(ref SystemState state)
{
state.Enabled = false;
// The components are baked, but systems are not baked. Create the required systems within the current world.
var reevaluateTaskSystemGroup = state.World.GetOrCreateSystemManaged<ReevaluateTaskSystemGroup>();
var interruptTaskSystemGroup = state.World.GetOrCreateSystemManaged<InterruptTaskSystemGroup>();
var traversalTaskSystemGroup = state.World.GetOrCreateSystemManaged<TraversalTaskSystemGroup>();
var ecb = new EntityCommandBuffer(state.WorldUpdateAllocator);
foreach (var (bakedBehaviorTree, entity) in SystemAPI.Query<BakedBehaviorTree>().WithEntityAccess()) {
AddSystems(state.World, reevaluateTaskSystemGroup, bakedBehaviorTree.ReevaluateTaskSystems);
AddSystems(state.World, interruptTaskSystemGroup, bakedBehaviorTree.InterruptTaskSystems);
AddSystems(state.World, traversalTaskSystemGroup, bakedBehaviorTree.TraversalTaskSystems);
// ComponentTypes cannot be serialized. Convert the StableTypeHash to a ComponentType.
var taskComponents = state.World.EntityManager.GetBuffer<TaskComponent>(entity);
for (int i = 0; i < taskComponents.Length; ++i) {
var taskComponent = taskComponents[i];
taskComponent.TagComponentType = ComponentType.FromTypeIndex(TypeManager.GetTypeIndexFromStableTypeHash(bakedBehaviorTree.TagStableTypeHashes[i]));
taskComponents[i] = taskComponent;
}
if (state.World.EntityManager.HasBuffer<ReevaluateTaskComponent>(entity)) {
var reevaluateComponents = state.World.EntityManager.GetBuffer<ReevaluateTaskComponent>(entity);
for (int i = 0; i < reevaluateComponents.Length; ++i) {
var reevaluateComponent = reevaluateComponents[i];
reevaluateComponent.ReevaluateTagComponentType = ComponentType.FromTypeIndex(TypeManager.GetTypeIndexFromStableTypeHash(bakedBehaviorTree.ReevaluateTagStableTypeHashes[i]));
reevaluateComponents[i] = reevaluateComponent;
}
}
// All of the systems have been added. Start the behavior tree.
BehaviorTree.StartBranch(state.World, entity, (ushort)bakedBehaviorTree.StartEventConnectedIndex, bakedBehaviorTree.StartEvaluation);
ecb.RemoveComponent<BakedBehaviorTree>(entity);
}
ecb.Playback(state.EntityManager);
ecb.Dispose();
}
/// <summary>
/// Adds the systems indicated by the SystemTypeIndex to the specified group.
/// </summary>
/// <param name="world">The current World.</param>
/// <param name="group">The group that the systems should be added to.</param>
/// <param name="systemTypes">The types of systems that should be added.</param>
private void AddSystems(World world, ComponentSystemGroup group, string[] systemTypes)
{
if (systemTypes == null) { return; }
for (int i = 0; i < systemTypes.Length; ++i) {
group.AddSystemToUpdateList(world.GetOrCreateSystem(Shared.Utility.TypeUtility.GetType(systemTypes[i])));
}
}
}
}
#endif