Files
riversong-code-showcase/Source/Riversong/Game/World/Roads/RoadVisualizationManager.cs
2026-05-21 16:04:49 +02:00

100 lines
3.2 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using Cysharp.Threading.Tasks;
using Unity.Mathematics;
using UnityEngine;
using Object = UnityEngine.Object;
namespace DanieleMarotta.RiversongCodeShowcase
{
public class RoadVisualizationManager : GameSystem, IInitializable, IDisposable
{
[InjectService]
private GameConfig _config;
[InjectService]
private IScene _scene;
[InjectService]
private ISignalBus _signalBus;
[InjectService]
private ITileSpace _tileSpace;
[InjectService]
private World _world;
private readonly List<GameObject> _prefabs = new();
private readonly Dictionary<int2, GameObject> _visualizations = new();
private GameObject _placementVfxPrefab;
public RoadVisualizationManager(IServiceLocator serviceLocator) : base(serviceLocator)
{
}
public async UniTask InitializeAsync()
{
var tilePrefabTasks = _config.Roads.Tiles.Select(tilePrefabRef => tilePrefabRef.LoadAssetAsync().ToUniTask()).ToArray();
var placementVfxTask = _config.Roads.PlacementVfxPrefab.LoadAssetAsync().ToUniTask();
var tilePrefabs = await UniTask.WhenAll(tilePrefabTasks);
_prefabs.AddRange(tilePrefabs);
_placementVfxPrefab = await placementVfxTask;
_signalBus.Subscribe<RoadTileUpdatedSignal>(OnRoadTileChanged);
}
public void Dispose()
{
foreach (var tilePrefabRef in _config.Roads.Tiles) tilePrefabRef.ReleaseAsset();
_config.Roads.PlacementVfxPrefab.ReleaseAsset();
_signalBus.Unsubscribe<RoadTileUpdatedSignal>(OnRoadTileChanged);
}
private void OnRoadTileChanged(RoadTileUpdatedSignal signal)
{
var tile = signal.Tile;
UpdateTile(tile);
if (tile.x > 0) UpdateTile(tile + new int2(-1, 0));
if (tile.x < _world.Size.x - 1) UpdateTile(tile + new int2(1, 0));
if (tile.y > 0) UpdateTile(tile + new int2(0, -1));
if (tile.y < _world.Size.y - 1) UpdateTile(tile + new int2(0, 1));
if (signal.RoadTileAdded) SpawnPlacementVfx(tile);
}
private void UpdateTile(int2 tile)
{
if (_visualizations.TryGetValue(tile, out var visualization))
{
Object.Destroy(visualization);
_visualizations.Remove(tile);
}
if (!_world.RoadNetwork.IsRoadTile(tile)) return;
visualization = Object.Instantiate(GetRoadTilePrefab(tile), _scene.SceneFolders.RoadTiles);
visualization.transform.position = _tileSpace.TileToWorld(tile) + new Vector3(0, 0.001f, 0);
_visualizations.Add(tile, visualization);
}
private GameObject GetRoadTilePrefab(int2 tile)
{
var connectivity = _world.RoadNetwork.GetConnectivity(tile);
return _prefabs[(int)connectivity];
}
private void SpawnPlacementVfx(int2 tile)
{
var position = _tileSpace.TileToWorld(tile);
Object.Instantiate(_placementVfxPrefab, position, Quaternion.identity);
}
}
}