Implement EntitySpawnerZone override system
Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Has been cancelled

- Создан скрипт EntitySpawnerZone.cs для выделения зон замены префабов в Unity Editor.
- Модифицирован EntitySpawner.cs для поддержки зон при выборе префаба на основе координат точки спавна.
This commit is contained in:
Данил Ярош 2026-08-07 14:39:18 +03:00
parent 3d1772af15
commit 28f5409187
5 changed files with 5101 additions and 4179 deletions

View File

@ -4937,7 +4937,7 @@ GameObject:
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
m_IsActive: 0
--- !u!4 &314704398255972110
Transform:
m_ObjectHideFlags: 0
@ -4989,7 +4989,7 @@ VisualEffect:
- m_Value: {x: 2, y: 0.019583605, z: 0, w: 1}
m_Name: ParticleColor
m_Overridden: 1
- m_Value: {x: 4, y: 0.20000002, z: 0, w: 1}
- m_Value: {x: 766.9961, y: 275.83508, z: 0, w: 1}
m_Name: ShaderColor
m_Overridden: 1
m_Uint:
@ -5014,7 +5014,7 @@ VFXRenderer:
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4081737046539047411}
m_Enabled: 1
m_Enabled: 0
m_CastShadows: 0
m_ReceiveShadows: 0
m_DynamicOccludee: 1
@ -5187,7 +5187,7 @@ VisualEffect:
- m_Value: {x: 1, y: 0, z: 0, w: 1}
m_Name: ParticleColor
m_Overridden: 0
- m_Value: {x: 2, y: 0.06666667, z: 0, w: 1}
- m_Value: {x: 32, y: 1.0666667, z: 0, w: 1}
m_Name: ShaderColor
m_Overridden: 1
m_Uint:

View File

@ -227,16 +227,16 @@ namespace RR.Game2D.Behaviour
if (!CanSpawn())
return null;
GameObject prefab = PickPrefab();
if (prefab == null)
return null;
if (!TryPickSpawnPoint(usedSpawnPointIndices, out Transform spawnPoint))
return null;
Vector3 spawnPosition = spawnPoint != null ? spawnPoint.position : transform.position;
Quaternion spawnRotation = spawnPoint != null ? spawnPoint.rotation : transform.rotation;
GameObject prefab = PickPrefab(spawnPosition);
if (prefab == null)
return null;
float zAngle = UnityEngine.Random.Range(randomZRotation.x, randomZRotation.y);
spawnRotation *= Quaternion.Euler(0f, 0f, zAngle);
@ -261,16 +261,31 @@ namespace RR.Game2D.Behaviour
return true;
}
private GameObject PickPrefab()
private GameObject PickPrefab(Vector3 spawnPosition)
{
// Проверка, находится ли эта точка спавна внутри какой-либо активной зоны переопределения
SpawnPrefabEntry[] activePrefabs = prefabs;
for (int i = 0; i < EntitySpawnerZone.ActiveZones.Count; i++)
{
EntitySpawnerZone zone = EntitySpawnerZone.ActiveZones[i];
if (zone != null && zone.IsPointInside(spawnPosition))
{
activePrefabs = zone.Prefabs;
break;
}
}
if (activePrefabs == null || activePrefabs.Length == 0)
return null;
int totalWeight = 0;
for (int i = 0; i < prefabs.Length; i++)
for (int i = 0; i < activePrefabs.Length; i++)
{
if (prefabs[i].prefab == null)
if (activePrefabs[i].prefab == null)
continue;
totalWeight += Mathf.Max(1, prefabs[i].weight);
totalWeight += Mathf.Max(1, activePrefabs[i].weight);
}
if (totalWeight <= 0)
@ -279,17 +294,17 @@ namespace RR.Game2D.Behaviour
int randomValue = UnityEngine.Random.Range(0, totalWeight);
int currentWeight = 0;
for (int i = 0; i < prefabs.Length; i++)
for (int i = 0; i < activePrefabs.Length; i++)
{
if (prefabs[i].prefab == null)
if (activePrefabs[i].prefab == null)
continue;
currentWeight += Mathf.Max(1, prefabs[i].weight);
currentWeight += Mathf.Max(1, activePrefabs[i].weight);
if (randomValue < currentWeight)
return prefabs[i].prefab;
return activePrefabs[i].prefab;
}
return prefabs[prefabs.Length - 1].prefab;
return activePrefabs[activePrefabs.Length - 1].prefab;
}
private bool TryPickSpawnPoint(HashSet<int> usedSpawnPointIndices, out Transform spawnPoint)

View File

@ -0,0 +1,83 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace RR.Game2D.Behaviour
{
[RequireComponent(typeof(Collider2D))]
[DisallowMultipleComponent]
public sealed class EntitySpawnerZone : MonoBehaviour
{
[Header("Override Prefabs")]
[Tooltip("Список префабов, которые будут спавниться вместо оригинальных префабов спавнера внутри этой зоны.")]
[SerializeField] private EntitySpawner.SpawnPrefabEntry[] prefabs;
private Collider2D _collider;
// Статический список всех активных зон на сцене для быстрого поиска
public static readonly List<EntitySpawnerZone> ActiveZones = new();
public EntitySpawner.SpawnPrefabEntry[] Prefabs => prefabs;
private void Awake()
{
_collider = GetComponent<Collider2D>();
// Убеждаемся, что коллайдер является триггером, чтобы не вызывать физических коллизий с персонажами
if (_collider != null)
{
_collider.isTrigger = true;
}
}
private void OnEnable()
{
ActiveZones.Add(this);
}
private void OnDisable()
{
ActiveZones.Remove(this);
}
/// <summary>
/// Проверяет, находится ли мировая точка внутри коллайдера зоны.
/// </summary>
public bool IsPointInside(Vector3 point)
{
if (_collider == null)
{
_collider = GetComponent<Collider2D>();
}
return _collider != null && _collider.OverlapPoint(point);
}
private void OnDrawGizmos()
{
if (_collider == null)
{
_collider = GetComponent<Collider2D>();
}
if (_collider == null) return;
// Рисуем оранжевую рамку зоны замены в редакторе
Gizmos.color = new Color(1f, 0.5f, 0f, 0.2f);
if (_collider is BoxCollider2D box)
{
Vector3 position = transform.TransformPoint(box.offset);
Vector3 size = Vector3.Scale(box.size, transform.lossyScale);
Gizmos.DrawCube(position, size);
Gizmos.color = new Color(1f, 0.5f, 0f, 0.8f);
Gizmos.DrawWireCube(position, size);
}
else
{
// Для других типов коллайдеров рисуем сферу в центре объекта
Gizmos.DrawSphere(transform.position, 0.5f);
}
}
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: b5c91a3a7ea71314e9c60d5e48b397d4

File diff suppressed because it is too large Load Diff