Files
2026-05-10 11:47:55 -04:00

133 lines
5.5 KiB
C#

/// ---------------------------------------------
/// Behavior Designer
/// Copyright (c) Opsive. All Rights Reserved.
/// https://www.opsive.com
/// ---------------------------------------------
namespace Opsive.BehaviorDesigner.Samples
{
using Opsive.BehaviorDesigner.Runtime;
using System;
using Unity.Collections;
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;
using UnityEngine;
/// <summary>
/// Spawns the entities.
/// </summary>
public class EntitySpawner : MonoBehaviour
{
[Tooltip("A reference to the spawn data.")]
[SerializeField] protected EntitySpawnData m_SpawnData;
/// <summary>
/// Bakes the spawn data.
/// </summary>
private class Baker : Baker<EntitySpawner>
{
/// <summary>
/// Bakes the data.
/// </summary>
/// <param name="authoring">The parent authoring component.</param>
public override void Bake(EntitySpawner authoring)
{
if (authoring.m_SpawnData == null || authoring.m_SpawnData.Prefab == null) {
return;
}
var entity = GetEntity(TransformUsageFlags.Dynamic);
var entityPrefab = GetEntity(authoring.m_SpawnData.Prefab, TransformUsageFlags.Dynamic);
AddComponent<EntitySpawnerPrefab>(entity, new EntitySpawnerPrefab()
{
Prefab = entityPrefab,
});
AddComponentObject(entity, new SpawnData
{
Prefab = entityPrefab,
SpawnCount = authoring.m_SpawnData.InitialSpawnCount,
MinRadius = authoring.m_SpawnData.MinRadius,
MaxRadius = authoring.m_SpawnData.MaxRadius,
MinRotationSpeed = authoring.m_SpawnData.MinRotationSpeed,
MaxRotationSpeed = authoring.m_SpawnData.MaxRotationSpeed,
});
}
}
}
/// <summary>
/// Stores a reference to the spawn prefab.
/// </summary>
public struct EntitySpawnerPrefab : IComponentData
{
public Entity Prefab;
}
/// <summary>
/// Contains the information needed to spawn the entities.
/// </summary>
public class SpawnData : IComponentData
{
[Tooltip("The entity prefab that should be spawned.")]
public Entity Prefab;
[Tooltip("The number of entities that should be initially spawned.")]
public int SpawnCount;
[Tooltip("The minimum radius that the entities should be spawned.")]
public int MinRadius;
[Tooltip("The maximum radius that the entities should be spawned.")]
public int MaxRadius;
[Tooltip("The minimum speed that the entities should rotate.")]
public float3 MinRotationSpeed;
[Tooltip("The maximum speed that the entities should rotate.")]
public float3 MaxRotationSpeed;
}
/// <summary>
/// System that does the spawning.
/// </summary>
public partial struct EntitySpawnerSystem : ISystem
{
/// <summary>
/// Sets the system requirements.
/// </summary>
/// <param name="state">The current SystemState.</param>
private void OnCreate(ref SystemState state)
{
state.RequireForUpdate<SpawnData>();
}
/// <summary>
/// Spawns the entities.
/// </summary>
/// <param name="state">The current SystemState.</param>
private void OnUpdate(ref SystemState state)
{
state.Enabled = false;
var spawner = SystemAPI.ManagedAPI.GetSingleton<SpawnData>();
var entities = state.EntityManager.Instantiate(spawner.Prefab, spawner.SpawnCount, Allocator.Temp);
var random = Unity.Mathematics.Random.CreateFromIndex((uint)DateTime.Now.Ticks);
// Setup each entity.
for (int i = 0; i < entities.Length; i += 1) {
var position = new float3();
var radians = random.NextFloat(math.PI2);
var dist = random.NextFloat(spawner.MinRadius, spawner.MaxRadius);
position.x = math.cos(radians) * dist;
position.y = 1;
position.z = math.sin(radians) * dist;
state.EntityManager.SetComponentData(entities[i], new LocalTransform { Position = position, Scale = 1, Rotation = quaternion.identity });
state.EntityManager.AddComponentData(entities[i], new LocalRotation { RotationSpeed =
new float3(
random.NextFloat(spawner.MinRotationSpeed.x, spawner.MaxRotationSpeed.x),
random.NextFloat(spawner.MinRotationSpeed.y, spawner.MaxRotationSpeed.y),
random.NextFloat(spawner.MinRotationSpeed.z, spawner.MaxRotationSpeed.z)) });
state.EntityManager.AddComponent(entities[i], ComponentType.ReadOnly<AgentTag>());
}
// LocalRotationSystem needs to be added manually.
var systemGroup = World.DefaultGameObjectInjectionWorld.GetOrCreateSystemManaged<SimulationSystemGroup>();
systemGroup.AddSystemToUpdateList(World.DefaultGameObjectInjectionWorld.GetOrCreateSystem<LocalRotationSystem>());
}
}
}