BITFALL/Assets/Artists/Scripts/GameMode/UnityAISpawner.cs

148 lines
4.5 KiB
C#
Raw Normal View History

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
}
}