137 lines
5.4 KiB
C#
137 lines
5.4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Sirenix.OdinInspector;
|
|
using UnityEngine;
|
|
|
|
namespace DDD
|
|
{
|
|
[CreateAssetMenu(fileName = "RestaurantCustomerStateSo", menuName = "RestaurantState/RestaurantCustomerStateSo")]
|
|
public class RestaurantCustomerStateSo : ScriptableObject, IGameFlowHandler
|
|
{
|
|
[Title("스폰 제어")]
|
|
[Tooltip("플로우 시작 후 첫 손님이 등장하기까지 대기 시간(초)")]
|
|
[SerializeField] private float _firstSpawnDelaySeconds = 5f;
|
|
|
|
[SerializeField] private Vector3 _spawnPoint = new(5f, 0f, 4f);
|
|
|
|
[Title("디버그")]
|
|
[SerializeField] private SpawnSchedule _spawnSchedule;
|
|
|
|
private GameStateSo _gameStateSo;
|
|
private LevelDataSo _levelDataSo;
|
|
private CustomerDataSo _customerDataSo;
|
|
private CustomerPoolDataSo _customerPoolDataSo;
|
|
|
|
private ICustomerFactory _iCustomerFactory;
|
|
|
|
private CancellationTokenSource _spawnLoopCancellationTokenSource;
|
|
|
|
public async Task OnReadyNewFlow(GameFlowState newFlowState)
|
|
{
|
|
if (newFlowState == GameFlowState.RunRestaurant)
|
|
{
|
|
await InitializeRunRestaurant();
|
|
}
|
|
}
|
|
|
|
public Task OnExitCurrentFlow(GameFlowState exitingFlowState)
|
|
{
|
|
if (exitingFlowState == GameFlowState.RunRestaurant)
|
|
{
|
|
_spawnLoopCancellationTokenSource?.Cancel();
|
|
_spawnLoopCancellationTokenSource?.Dispose();
|
|
_spawnLoopCancellationTokenSource = null;
|
|
}
|
|
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
private async Task InitializeRunRestaurant()
|
|
{
|
|
_gameStateSo = await AssetManager.LoadAsset<GameStateSo>(DataConstants.GameStateSo);
|
|
|
|
Debug.Assert(_gameStateSo != null, "_gameStateSo is null");
|
|
|
|
_iCustomerFactory = new CustomerFactory();
|
|
|
|
var currentGameLevel = _gameStateSo.GetCurrentLevel();
|
|
if (_levelDataSo == null)
|
|
{
|
|
_levelDataSo = DataManager.Instance.GetDataSo<LevelDataSo>();
|
|
}
|
|
if (_customerDataSo == null)
|
|
{
|
|
_customerDataSo = DataManager.Instance.GetDataSo<CustomerDataSo>();
|
|
}
|
|
if (_customerPoolDataSo == null)
|
|
{
|
|
_customerPoolDataSo = DataManager.Instance.GetDataSo<CustomerPoolDataSo>();
|
|
}
|
|
var currentLevelData = _levelDataSo.GetDataList().FirstOrDefault(data => data.Level == currentGameLevel);
|
|
|
|
Debug.Assert(currentLevelData != null, "currentLevelData is null");
|
|
|
|
var normalPool = _customerPoolDataSo.GetDataById(currentLevelData.CustomerPool);
|
|
var specialPool = _customerPoolDataSo.GetDataById(currentLevelData.SpecialCustomerPool);
|
|
|
|
_spawnLoopCancellationTokenSource?.Cancel();
|
|
_spawnLoopCancellationTokenSource = new CancellationTokenSource();
|
|
_ = RunSpawnLoopAsync(currentLevelData, normalPool, specialPool, _spawnLoopCancellationTokenSource.Token);
|
|
}
|
|
|
|
private async Task RunSpawnLoopAsync(LevelData levelData, CustomerPoolData normalPool, CustomerPoolData specialPool, CancellationToken token)
|
|
{
|
|
if (_firstSpawnDelaySeconds > 0)
|
|
await Task.Delay(TimeSpan.FromSeconds(_firstSpawnDelaySeconds), token);
|
|
|
|
var scheduleBuilder = CreateBuilder(levelData.SpawnType);
|
|
int randomSeed = Environment.TickCount;
|
|
|
|
SpawnSchedule MakeSchedule() => scheduleBuilder.Build(new SpawnScheduleBuildArgs
|
|
{
|
|
NormalIds = (IReadOnlyList<string>) (normalPool?.ValidCustomers) ?? Array.Empty<string>(),
|
|
SpecialIds = (IReadOnlyList<string>) (specialPool?.ValidCustomers) ?? Array.Empty<string>(),
|
|
NormalQuota = Math.Max(0, normalPool?.CustomerLimitCount ?? 0),
|
|
SpecialQuota = Math.Max(0, specialPool?.CustomerLimitCount ?? 0),
|
|
Seed = ++randomSeed
|
|
});
|
|
|
|
_spawnSchedule = MakeSchedule();
|
|
float wait = Mathf.Max(0.1f, levelData.CustomerRespawnTime);
|
|
|
|
while (token.IsCancellationRequested == false)
|
|
{
|
|
if (_spawnSchedule.TryDequeue(out var customerId) == false) break;
|
|
|
|
if (_customerDataSo.TryGetDataById(customerId, out var customerData))
|
|
{
|
|
var rotation = Quaternion.identity;
|
|
|
|
_ = _iCustomerFactory.CreateAsync(new CustomerSpawnArgs
|
|
{
|
|
CustomerDataId = customerId,
|
|
CustomerData = customerData,
|
|
Position = _spawnPoint,
|
|
Rotation = rotation,
|
|
Parent = null
|
|
});
|
|
}
|
|
|
|
await Task.Delay(TimeSpan.FromSeconds(wait), token);
|
|
}
|
|
}
|
|
|
|
private ISpawnScheduleBuilder CreateBuilder(SpawnType type)
|
|
{
|
|
return type switch
|
|
{
|
|
SpawnType.Random => new RandomSpawnScheduleBuilder(),
|
|
SpawnType.Regular => new RegularSpawnScheduleBuilder(),
|
|
_ => new RandomSpawnScheduleBuilder()
|
|
};
|
|
}
|
|
}
|
|
} |