2024-03-12 21:54:29 +08:00
|
|
|
using System;
|
|
|
|
using System.Collections.Concurrent;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Linq;
|
|
|
|
using System.Windows.Forms.VisualStyles;
|
|
|
|
using BITKit;
|
|
|
|
using BITKit.Entities;
|
2024-03-18 18:20:23 +08:00
|
|
|
using BITKit.OpenWorld;
|
2024-04-06 16:33:57 +08:00
|
|
|
using kcp2k;
|
2024-03-18 18:20:23 +08:00
|
|
|
using Quadtree;
|
2024-03-12 21:54:29 +08:00
|
|
|
using Unity.Mathematics;
|
|
|
|
using UnityEngine;
|
|
|
|
using UnityEngine.AI;
|
|
|
|
using YooAsset;
|
|
|
|
using Random = UnityEngine.Random;
|
|
|
|
|
|
|
|
namespace BITFALL.GameMode
|
|
|
|
{
|
2024-04-06 16:33:57 +08:00
|
|
|
public class UnityAISpawner : MonoBehaviour
|
2024-03-12 21:54:29 +08:00
|
|
|
{
|
|
|
|
[SerializeReference,SubclassSelector] private ITicker ticker;
|
|
|
|
[SerializeReference, SubclassSelector] private new IReference name;
|
|
|
|
[SerializeReference,SubclassSelector] private IReference entityPath;
|
2024-03-18 18:20:23 +08:00
|
|
|
[SerializeField, ReadOnly] private int spawnedCount;
|
2024-04-13 01:10:30 +08:00
|
|
|
[SerializeField] private Transform spawnPoint;
|
2024-04-06 16:33:57 +08:00
|
|
|
[SerializeField] private ChunkBehaviour chunkBehaviour;
|
2024-03-12 21:54:29 +08:00
|
|
|
[SerializeField] private int minCapacity;
|
|
|
|
[SerializeField] private int maxCapacity;
|
|
|
|
|
2024-04-06 16:33:57 +08:00
|
|
|
private readonly HashSet<ulong> _spawnedEntities = new();
|
2024-03-12 21:54:29 +08:00
|
|
|
private int _capacity;
|
|
|
|
public IEntity Entity
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
var task = YooAssets.LoadAssetAsync<GameObject>(entityPath.Value);
|
|
|
|
task.WaitForAsyncComplete();
|
|
|
|
return task.AssetObject.As<GameObject>().GetComponent<IEntity>();
|
|
|
|
}
|
|
|
|
}
|
2024-04-06 16:33:57 +08:00
|
|
|
private readonly ConcurrentQueue<ulong> _removeQueue = new();
|
2024-03-18 18:20:23 +08:00
|
|
|
private readonly ValidHandle allowTick = new();
|
2024-03-12 21:54:29 +08:00
|
|
|
private void OnEnable()
|
|
|
|
{
|
|
|
|
_capacity = Random.Range(minCapacity, maxCapacity);
|
|
|
|
}
|
|
|
|
private void Start()
|
|
|
|
{
|
2024-03-18 18:20:23 +08:00
|
|
|
allowTick.AddListener(x =>
|
|
|
|
{
|
|
|
|
if(x)
|
|
|
|
ticker.Add(OnTick);
|
|
|
|
else
|
|
|
|
ticker.Remove(OnTick);
|
|
|
|
});
|
2024-04-06 16:33:57 +08:00
|
|
|
|
|
|
|
chunkBehaviour.OnLodChangedEvent += OnLodChanged;
|
2024-03-18 18:20:23 +08:00
|
|
|
destroyCancellationToken.Register(Dispose);
|
2024-03-12 21:54:29 +08:00
|
|
|
}
|
2024-03-18 18:20:23 +08:00
|
|
|
private void Dispose()
|
2024-03-12 21:54:29 +08:00
|
|
|
{
|
2024-04-06 16:33:57 +08:00
|
|
|
allowTick.SetDisableElements(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void OnLodChanged(int arg1, int lod)
|
|
|
|
{
|
|
|
|
switch (lod)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
allowTick.AddElement(this);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
case 2:
|
|
|
|
allowTick.RemoveElement(this);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
allowTick.RemoveElement(this);
|
|
|
|
break;
|
|
|
|
}
|
2024-03-12 21:54:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
private void OnTick(float obj)
|
|
|
|
{
|
2024-04-06 16:33:57 +08:00
|
|
|
while (_removeQueue.TryDequeue(out var _x))
|
2024-03-12 21:54:29 +08:00
|
|
|
{
|
2024-04-06 16:33:57 +08:00
|
|
|
if (_spawnedEntities.Contains(_x))
|
|
|
|
_spawnedEntities.Remove(_x);
|
2024-03-12 21:54:29 +08:00
|
|
|
}
|
2024-03-18 18:20:23 +08:00
|
|
|
|
|
|
|
spawnedCount = _spawnedEntities.Count;
|
2024-03-12 21:54:29 +08:00
|
|
|
|
2024-04-06 16:33:57 +08:00
|
|
|
if(chunkBehaviour.Lod is not 0) return;
|
|
|
|
|
|
|
|
if (_spawnedEntities.Count >= _capacity) return;
|
|
|
|
|
2024-04-13 01:10:30 +08:00
|
|
|
var position = spawnPoint ? spawnPoint.position : transform.position;
|
|
|
|
|
|
|
|
if (NavMesh.SamplePosition(position, out var navMeshHit, 100, NavMesh.AllAreas))
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2024-04-06 16:33:57 +08:00
|
|
|
var entity = Entity.As<Entity>();
|
|
|
|
var _transform = entity.transform;
|
2024-04-13 01:10:30 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2024-03-12 21:54:29 +08:00
|
|
|
|
2024-04-06 16:33:57 +08:00
|
|
|
for (var i = 0; i < _capacity - _spawnedEntities.Count; i++)
|
2024-03-12 21:54:29 +08:00
|
|
|
{
|
2024-04-06 16:33:57 +08:00
|
|
|
if (PoolService.TryGet(_transform, out var instance) is false) continue;
|
2024-04-13 01:10:30 +08:00
|
|
|
|
2024-03-12 21:54:29 +08:00
|
|
|
|
2024-04-13 01:10:30 +08:00
|
|
|
if(Physics.Raycast(position+Vector3.up,Vector3.down,out var hit,100))
|
2024-03-12 21:54:29 +08:00
|
|
|
position = hit.point;
|
|
|
|
|
|
|
|
var rotation = Quaternion.Euler(
|
|
|
|
0,
|
|
|
|
Random.Range(0, 360),
|
|
|
|
0);
|
2024-04-06 16:33:57 +08:00
|
|
|
|
2024-04-13 01:10:30 +08:00
|
|
|
|
2024-04-06 16:33:57 +08:00
|
|
|
instance.position = position;
|
|
|
|
instance.rotation = rotation;
|
|
|
|
var newEntity = instance.GetComponent<Entity>();
|
2024-03-12 21:54:29 +08:00
|
|
|
|
2024-04-06 16:33:57 +08:00
|
|
|
_spawnedEntities.Add(newEntity.Id);
|
2024-03-12 21:54:29 +08:00
|
|
|
|
2024-04-06 16:33:57 +08:00
|
|
|
newEntity.TryGetComponent<IHealth>(out var heal);
|
|
|
|
heal.HealthPoint = heal.MaxHealthPoint;
|
|
|
|
|
|
|
|
heal.OnSetAlive += OnSetAlive;
|
|
|
|
continue;
|
|
|
|
void OnSetAlive(bool alive)
|
2024-03-12 21:54:29 +08:00
|
|
|
{
|
2024-04-06 16:33:57 +08:00
|
|
|
if (alive) return;
|
|
|
|
PoolService.Release(_transform.name, instance);
|
|
|
|
_removeQueue.Enqueue(newEntity.Id);
|
|
|
|
heal.OnSetAlive -= OnSetAlive;
|
|
|
|
}
|
2024-03-12 21:54:29 +08:00
|
|
|
}
|
2024-03-18 18:20:23 +08:00
|
|
|
|
|
|
|
|
|
|
|
}
|
2024-03-12 21:54:29 +08:00
|
|
|
}
|
|
|
|
}
|