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 _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(entityPath.Value); task.WaitForAsyncComplete(); return task.AssetObject.As().GetComponent(); } } public int CycleMaxCount => cycleMaxCount; public float4x4 Bounds => bounds; public IEntity[] spawnedEntities => _spawnedEntities.ToArray(); private readonly ConcurrentQueue _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 = Instantiate(entity, position, rotation); _spawnedEntities.Add(entity); entity.TryGetComponent(out var heal); heal.OnSetAlive += (x) => { if (x) return; _removeQueue.Enqueue(entity); }; } } } }