using System.Collections.Generic; using UnityEngine; using Zenject; namespace DanroJump.Gameplay { public sealed class PlatformContentSpawner { private readonly DiContainer container; private readonly Dictionary> spawnedContentByPlatform = new(); public PlatformContentSpawner(DiContainer container) { this.container = container; } public void SpawnContent( PlatformController platform, IPlatformContentSource catalog, System.Random random) { ClearSpawnedContent(platform); if (platform == null || catalog == null) { return; } SpawnIntoPoints(platform, catalog, PlatformContentKind.Collectible, platform.CollectibleSpawnPoints, random); SpawnIntoPoints(platform, catalog, PlatformContentKind.Equipment, platform.EquipmentSpawnPoints, random); SpawnIntoPoints(platform, catalog, PlatformContentKind.Enemy, platform.EnemySpawnPoints, random); } public void ClearSpawnedContent(PlatformController platform) { if (platform == null) { return; } if (!ClearTrackedContent(platform)) { ClearOrphanSpawnedContent(platform); } } public void ClearAll() { foreach (var platform in new List(spawnedContentByPlatform.Keys)) { ClearSpawnedContent(platform); } } private void SpawnIntoPoints( PlatformController platform, IPlatformContentSource catalog, PlatformContentKind kind, IReadOnlyList spawnPoints, System.Random random) { if (spawnPoints == null || !catalog.ShouldSpawn(kind, random) || !catalog.TryGetPrefab(kind, random, out var prefab)) { return; } foreach (var spawnPoint in spawnPoints) { if (spawnPoint == null || ShouldSkipOptionalPoint(spawnPoint, random)) { continue; } Spawn(prefab, spawnPoint.Anchor, platform); } } private void Spawn(GameObject prefab, Transform parent, PlatformController platform) { var targetParent = parent != null ? parent : platform.transform; var instance = container.InstantiatePrefab(prefab, targetParent.position, targetParent.rotation, targetParent); if (!instance.TryGetComponent(out PlatformSpawnedContent _)) { instance.AddComponent(); } if (instance.TryGetComponent(out IPlatformEquipment equipment)) { equipment.Install(platform); } if (!spawnedContentByPlatform.TryGetValue(platform, out var spawnedContent)) { spawnedContent = new List(); spawnedContentByPlatform.Add(platform, spawnedContent); } spawnedContent.Add(instance); } private bool ClearTrackedContent(PlatformController platform) { if (!spawnedContentByPlatform.TryGetValue(platform, out var spawnedContent)) { return false; } for (var index = spawnedContent.Count - 1; index >= 0; index--) { var content = spawnedContent[index]; if (content != null) { content.SetActive(false); Object.Destroy(content); } } spawnedContent.Clear(); spawnedContentByPlatform.Remove(platform); return true; } private static void ClearOrphanSpawnedContent(PlatformController platform) { var markers = platform.GetComponentsInChildren(true); foreach (var marker in markers) { if (marker != null) { marker.gameObject.SetActive(false); Object.Destroy(marker.gameObject); } } } private static bool ShouldSkipOptionalPoint(PlatformSpawnPoint spawnPoint, System.Random random) { if (!spawnPoint.Optional) { return false; } if (spawnPoint.Weight <= 0f) { return true; } if (spawnPoint.Weight >= 1f) { return false; } var roll = random != null ? random.NextDouble() : 0d; return roll > spawnPoint.Weight; } } }