80 lines
2.7 KiB
C#
80 lines
2.7 KiB
C#
using Unity.Mathematics;
|
|
using UnityEngine;
|
|
using UnityEngine.Pool;
|
|
using Random = UnityEngine.Random;
|
|
|
|
namespace DanieleMarotta.RiversongCodeShowcase
|
|
{
|
|
[GameSystemGroup(typeof(EarlyAgentsSystemGroup))]
|
|
public class CritterSpawnSystem : GameSystem, IUpdatable
|
|
{
|
|
[InjectService]
|
|
private World _world;
|
|
|
|
[InjectService]
|
|
private IEntityCollection _entityCollection;
|
|
|
|
[InjectService]
|
|
private IAgentFactory _agentFactory;
|
|
|
|
[InjectService]
|
|
private ITileSpace _tileSpace;
|
|
|
|
public CritterSpawnSystem(IServiceLocator serviceLocator) : base(serviceLocator)
|
|
{
|
|
}
|
|
|
|
public void Update()
|
|
{
|
|
foreach (CritterHerd herd in _entityCollection.GetInternalEntityList(typeof(CritterHerd)))
|
|
{
|
|
ref var agentSourceState = ref herd.GetAgentSourceStateRW();
|
|
|
|
if (agentSourceState.AgentCount[(int)AgentJob.None] >= herd.MaxCritterCount)
|
|
{
|
|
herd.SpawnTimer = float.MinValue;
|
|
continue;
|
|
}
|
|
|
|
var critterDefinition = herd.CritterDefinition;
|
|
|
|
if (herd.SpawnTimer < 0) herd.SpawnTimer = Random.Range(critterDefinition.MinSpawningInterval, critterDefinition.MaxSpawningInterval);
|
|
|
|
herd.SpawnTimer -= Time.deltaTime;
|
|
if (herd.SpawnTimer <= 0)
|
|
{
|
|
herd.SpawnTimer = float.MinValue;
|
|
|
|
var wanderingRadius = critterDefinition.AgentDefinition.WanderingRadius;
|
|
if (!TryFindRandomFreeTile(herd.Center - wanderingRadius, herd.Center + wanderingRadius, out var tile)) continue;
|
|
|
|
var position = _tileSpace.TileToWorld(tile);
|
|
var critter = _agentFactory.CreateCritter(critterDefinition, herd, position);
|
|
critter.WanderingCenter = tile;
|
|
|
|
ref var intentQueue = ref critter.GetIntentQueueRW();
|
|
intentQueue.EnqueueIntent(AgentIntent.MakeLive());
|
|
IntentQueue.LoopWandering(ref intentQueue, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
private bool TryFindRandomFreeTile(int2 min, int2 max, out int2 tile)
|
|
{
|
|
using var candidatesScope = ListPool<int2>.Get(out var candidates);
|
|
|
|
foreach (var candidate in TileRange.From(min, max))
|
|
if (!_world.BlockMap.IsBlocked(candidate, BlockReason.BlocksAgents))
|
|
candidates.Add(candidate);
|
|
|
|
if (candidates.Count == 0)
|
|
{
|
|
tile = int2.zero;
|
|
return false;
|
|
}
|
|
|
|
tile = candidates[Random.Range(0, candidates.Count)];
|
|
return true;
|
|
}
|
|
}
|
|
} |