Files
SoulliesOfficial 50ee502684 完善
2026-02-13 09:22:11 -05:00

172 lines
6.7 KiB
C#

/// ---------------------------------------------
/// Behavior Designer
/// Copyright (c) Opsive. All Rights Reserved.
/// https://www.opsive.com
/// ---------------------------------------------
namespace Opsive.BehaviorDesigner.Samples
{
using System.Collections;
using Unity.Collections;
using Unity.Entities;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.Pool;
using UnityEngine.UI;
/// <summary>
/// Adds effects to the entities sample scene.
/// </summary>
public class EffectsManager : MonoBehaviour
{
[Tooltip("The explosion prefab.")]
[SerializeField] protected GameObject m_Explosion;
[Tooltip("A reference to the turret's healthbar.")]
[SerializeField] protected Slider m_TurretHealthbar;
private ObjectPool<GameObject> m_ExplosionPool;
private EntityCommandBuffer m_EntityCommandBuffer;
/// <summary>
/// Initializes the default values.
/// </summary>
private void Awake()
{
m_ExplosionPool = new ObjectPool<GameObject>(() => // Create.
{
var explosion = GameObject.Instantiate(m_Explosion);
explosion.GetComponent<ReturnToParticlePool>().Pool = m_ExplosionPool;
return explosion;
}, (GameObject explosion) => // Take.
{
explosion.SetActive(true);
}, (GameObject explosion) => // Return.
{
explosion.SetActive(false);
}, (GameObject explosion) => // Destroy.
{
DestroyImmediate(explosion);
});
}
/// <summary>
/// The entity subscene has loaded.
/// </summary>
private void Start()
{
StartCoroutine(RegisterEvents());
}
/// <summary>
/// Subscribes to the interested events.
/// </summary>
private IEnumerator RegisterEvents()
{
DamageTaskSystem damageTaskSystem;
do {
damageTaskSystem = World.DefaultGameObjectInjectionWorld.GetExistingSystemManaged<DamageTaskSystem>();
yield return new WaitForEndOfFrame(); // The systems aren't available immediately.
} while (damageTaskSystem == null);
damageTaskSystem.OnDamage += OnDamageTurret;
var destroyTaskSystem = World.DefaultGameObjectInjectionWorld.GetOrCreateSystemManaged<DestroyEntitySystem>();
destroyTaskSystem.OnDestroyEntity += OnDestroyEntity;
// Add the necessary systems that are not created by Behavior Designer.
var systemGroup = World.DefaultGameObjectInjectionWorld.GetOrCreateSystemManaged<SimulationSystemGroup>();
systemGroup.AddSystemToUpdateList(destroyTaskSystem);
systemGroup.AddSystemToUpdateList(World.DefaultGameObjectInjectionWorld.GetOrCreateSystem<TurretRecoilSystem>());
}
/// <summary>
/// The entity has been destroyed.
/// </summary>
/// <param name="position">The position of the entity.</param>
private void OnDestroyEntity(float3 position)
{
var explosion = m_ExplosionPool.Get();
explosion.transform.position = position;
}
/// <summary>
/// The turret has been damaged.
/// </summary>
/// <param name="healthAmount">The remaining health amount.</param>
private void OnDamageTurret(float healthAmount)
{
healthAmount = Mathf.Clamp(healthAmount, 0, Mathf.Abs(healthAmount));
m_TurretHealthbar.value = healthAmount;
// Destroy the turret when it doesn't have any more health.
if (healthAmount == 0) {
var explosion = m_ExplosionPool.Get();
explosion.transform.position = Vector3.zero;
explosion.transform.localScale = new Vector3(4, 4, 4);
// The turret base should also be destroyed.
var entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
var query = new EntityQueryBuilder(Allocator.Temp).WithAll<TurretBaseTag>().Build(entityManager);
var entities = query.ToEntityArray(AllocatorManager.Temp); // Only one entity will be returned.
m_EntityCommandBuffer = new EntityCommandBuffer(Allocator.Persistent);
if (entities.Length > 0) {
m_EntityCommandBuffer.DestroyEntity(entities[0]);
}
query.Dispose();
entities.Dispose();
// .. As well as the turret weapon.
query = new EntityQueryBuilder(Allocator.Temp).WithAll<TurretRecoil>().WithOptions(EntityQueryOptions.IgnoreComponentEnabledState).Build(entityManager);
entities = query.ToEntityArray(AllocatorManager.Temp); // Only one entity will be returned.
if (entities.Length > 0) {
m_EntityCommandBuffer.DestroyEntity(entities[0]);
}
query.Dispose();
entities.Dispose();
// All of the currently charging agents should be destroyed.
query = new EntityQueryBuilder(Allocator.Temp).WithAll<ChargeFlag>().Build(entityManager);
entities = query.ToEntityArray(AllocatorManager.Temp);
for (int i = 0; i < entities.Length; ++i) {
m_EntityCommandBuffer.DestroyEntity(entities[i]);
}
query.Dispose();
entities.Dispose();
enabled = true;
}
}
/// <summary>
/// Runs the EntityCommandBuffer if it exists.
/// </summary>
private void Update()
{
if (m_EntityCommandBuffer.IsEmpty) {
enabled = false;
return;
}
m_EntityCommandBuffer.Playback(World.DefaultGameObjectInjectionWorld.EntityManager);
m_EntityCommandBuffer.Dispose();
}
/// <summary>
/// The component has been destroyed.
/// </summary>
private void OnDestroy()
{
if (World.DefaultGameObjectInjectionWorld == null) {
return;
}
var destroySystem = World.DefaultGameObjectInjectionWorld.GetExistingSystemManaged<DestroyEntitySystem>();
if (destroySystem != null) {
destroySystem.OnDestroyEntity -= OnDestroyEntity;
}
var damageSystem = World.DefaultGameObjectInjectionWorld.GetExistingSystemManaged<DamageTaskSystem>();
if (damageSystem != null) {
damageSystem.OnDamage -= OnDamageTurret;
}
}
}
}