riversong code showcase
This commit is contained in:
@@ -0,0 +1,128 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Pool;
|
||||
using Object = UnityEngine.Object;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
namespace DanieleMarotta.RiversongCodeShowcase
|
||||
{
|
||||
[Service(typeof(IRawResourceVisualizationCollection))]
|
||||
public class RawResourceRenderingSystem : GameSystem, IInitializable, IDisposable, IRawResourceVisualizationCollection, IOnWorldGenerationCompletedCallback
|
||||
{
|
||||
private const int MaxCreatedPerUpdate = 16;
|
||||
|
||||
[InjectService]
|
||||
private IScene _scene;
|
||||
|
||||
[InjectService]
|
||||
private IGameDatabase _gameDatabase;
|
||||
|
||||
[InjectService]
|
||||
private ISignalBus _signalBus;
|
||||
|
||||
[InjectService]
|
||||
private World _world;
|
||||
|
||||
[InjectService]
|
||||
private GameConfig _config;
|
||||
|
||||
private Dictionary<int, GameObject> _visualizationsById = new();
|
||||
|
||||
public RawResourceRenderingSystem(IServiceLocator serviceLocator) : base(serviceLocator)
|
||||
{
|
||||
}
|
||||
|
||||
public UniTask InitializeAsync()
|
||||
{
|
||||
_signalBus.Subscribe<WorldGenerationCompletedSignal>(OnWorldGenerationCompleted);
|
||||
_signalBus.Subscribe<CollectDeletedGameObjectsSignal>(OnCollectDeletedGameObjects);
|
||||
_signalBus.Subscribe<RawResourcesRemovedSignal>(OnRawResourcesRemoved);
|
||||
|
||||
return UniTask.CompletedTask;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_signalBus.Unsubscribe<WorldGenerationCompletedSignal>(OnWorldGenerationCompleted);
|
||||
_signalBus.Unsubscribe<CollectDeletedGameObjectsSignal>(OnCollectDeletedGameObjects);
|
||||
_signalBus.Unsubscribe<RawResourcesRemovedSignal>(OnRawResourcesRemoved);
|
||||
}
|
||||
|
||||
private void OnWorldGenerationCompleted(WorldGenerationCompletedSignal signal)
|
||||
{
|
||||
signal.Callbacks.Add(this);
|
||||
}
|
||||
|
||||
public async UniTask OnWorldGenerationCompletedAsync(World world)
|
||||
{
|
||||
await CreateVisualizationsAsync();
|
||||
}
|
||||
|
||||
private async UniTask CreateVisualizationsAsync()
|
||||
{
|
||||
var visualizationCount = 0;
|
||||
|
||||
foreach (var resourceNode in _world.RawResources)
|
||||
{
|
||||
var definition = _gameDatabase.WithId<ResourceNodeDefinition>(resourceNode.DefinitionId);
|
||||
|
||||
var rotation = definition.RandomRotation ? Quaternion.Euler(0, Random.Range(0, 360), 0) : resourceNode.Orientation.ToQuaternion();
|
||||
var scale = Vector3.one * Random.Range(definition.ScaleRange.x, definition.ScaleRange.y);
|
||||
|
||||
GameObject prefab;
|
||||
if (definition.Prefab.IsValid())
|
||||
prefab = (GameObject)definition.Prefab.Asset;
|
||||
else
|
||||
prefab = await definition.Prefab.LoadAssetAsync<GameObject>();
|
||||
|
||||
var visualization = Object.Instantiate(prefab, _scene.SceneFolders.RawResources);
|
||||
visualization.transform.SetPositionAndRotation(resourceNode.Position, rotation);
|
||||
visualization.transform.localScale = Vector3.Scale(visualization.transform.localScale, scale);
|
||||
|
||||
_visualizationsById.Add(resourceNode.Id, visualization);
|
||||
|
||||
if (++visualizationCount % MaxCreatedPerUpdate == 0) await UniTask.NextFrame();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCollectDeletedGameObjects(CollectDeletedGameObjectsSignal signal)
|
||||
{
|
||||
if ((signal.Filter & DeletedGameObjectsFilter.RawResources) == 0) return;
|
||||
|
||||
using var resourceNodesScope = ListPool<(int, bool)>.Get(out var resourceNodeIds);
|
||||
_world.RawResources.GetResourceNodes(signal.Rect, _config.GeneralSettings.BaseElevation, resourceNodeIds);
|
||||
|
||||
foreach (var (id, canBeDeleted) in resourceNodeIds)
|
||||
{
|
||||
if (!canBeDeleted) continue;
|
||||
|
||||
var visualization = _visualizationsById[id];
|
||||
signal.GameObjects.Add(visualization.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnRawResourcesRemoved(RawResourcesRemovedSignal signal)
|
||||
{
|
||||
foreach (var resourceNode in signal.ResourceNodes)
|
||||
{
|
||||
if (!_visualizationsById.Remove(resourceNode.Id, out var visualization)) return;
|
||||
|
||||
_ = DestroyVisualizationAsync(visualization);
|
||||
}
|
||||
}
|
||||
|
||||
private async UniTask DestroyVisualizationAsync(GameObject visualization)
|
||||
{
|
||||
if (visualization.TryGetComponent<IDestroyRawResourceAnimation>(out var animation)) await animation.PlayAsync();
|
||||
|
||||
Object.Destroy(visualization);
|
||||
}
|
||||
|
||||
public bool TryGetVisualization(int id, out GameObject visualization)
|
||||
{
|
||||
return _visualizationsById.TryGetValue(id, out visualization);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user