104 lines
3.1 KiB
C#
104 lines
3.1 KiB
C#
|
using System;
|
||
|
using System.Collections.Concurrent;
|
||
|
using System.Collections.Generic;
|
||
|
using System.Linq;
|
||
|
using System.Windows.Forms.VisualStyles;
|
||
|
using BITKit;
|
||
|
using BITKit.Entities;
|
||
|
using Unity.Mathematics;
|
||
|
using UnityEngine;
|
||
|
using UnityEngine.AI;
|
||
|
using YooAsset;
|
||
|
using Random = UnityEngine.Random;
|
||
|
|
||
|
namespace BITFALL.GameMode
|
||
|
{
|
||
|
public class UnityAISpawner : MonoBehaviour
|
||
|
{
|
||
|
[SerializeReference,SubclassSelector] private ITicker ticker;
|
||
|
[SerializeReference, SubclassSelector] private new IReference name;
|
||
|
[SerializeReference,SubclassSelector] private IReference entityPath;
|
||
|
[SerializeField] private int minCapacity;
|
||
|
[SerializeField] private int maxCapacity;
|
||
|
[SerializeField] private int cycleMaxCount;
|
||
|
[SerializeField] private float4x4 bounds;
|
||
|
|
||
|
private readonly CacheList<IEntity> _spawnedEntities = new();
|
||
|
|
||
|
public string Name => name.Value;
|
||
|
public int MinCapacity => minCapacity;
|
||
|
public int MaxCapacity => maxCapacity;
|
||
|
private int _capacity;
|
||
|
|
||
|
public IEntity Entity
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
var task = YooAssets.LoadAssetAsync<GameObject>(entityPath.Value);
|
||
|
task.WaitForAsyncComplete();
|
||
|
return task.AssetObject.As<GameObject>().GetComponent<IEntity>();
|
||
|
}
|
||
|
}
|
||
|
public int CycleMaxCount => cycleMaxCount;
|
||
|
public float4x4 Bounds => bounds;
|
||
|
public IEntity[] spawnedEntities => _spawnedEntities.ToArray();
|
||
|
private readonly ConcurrentQueue<IEntity> _removeQueue = new();
|
||
|
|
||
|
private void OnEnable()
|
||
|
{
|
||
|
_capacity = Random.Range(minCapacity, maxCapacity);
|
||
|
ticker.Add(OnTick);
|
||
|
}
|
||
|
|
||
|
private void Start()
|
||
|
{
|
||
|
OnTick(Time.deltaTime);
|
||
|
}
|
||
|
|
||
|
private void OnDisable()
|
||
|
{
|
||
|
ticker.Remove(OnTick);
|
||
|
}
|
||
|
|
||
|
private void OnTick(float obj)
|
||
|
{
|
||
|
while (_removeQueue.TryDequeue(out var entity))
|
||
|
{
|
||
|
_spawnedEntities.Remove(entity);
|
||
|
}
|
||
|
|
||
|
if (spawnedEntities.Length >= _capacity) return;
|
||
|
|
||
|
for (var i = 0; i < Math.Min(cycleMaxCount, _capacity - spawnedEntities.Length); i++)
|
||
|
{
|
||
|
var position =transform.position + new Vector3(
|
||
|
Random.Range(-8, 8),
|
||
|
Random.Range(0, 8),
|
||
|
Random.Range(-8, 8)
|
||
|
);
|
||
|
|
||
|
if(Physics.Raycast(position,Vector3.down,out var hit,100))
|
||
|
position = hit.point;
|
||
|
|
||
|
var rotation = Quaternion.Euler(
|
||
|
0,
|
||
|
Random.Range(0, 360),
|
||
|
0);
|
||
|
|
||
|
var entity = Entity.As<Entity>();
|
||
|
|
||
|
entity = Instantiate(entity, position, rotation);
|
||
|
|
||
|
_spawnedEntities.Add(entity);
|
||
|
|
||
|
entity.TryGetComponent<IHealth>(out var heal);
|
||
|
heal.OnSetAlive += (x) =>
|
||
|
{
|
||
|
if (x) return;
|
||
|
_removeQueue.Enqueue(entity);
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|