我正在努力阻止预制对象在生成时重叠。我在 Google 上搜索了很多类似的问题,并意识到这个问题在游戏开发中很常见,但我自己很难解决。
我有一个带有 Box Collider 2D 和 Sprite Renderer 组件的预制件。它们绑定到屏幕边界并在此边界内的任何位置随机生成。每 8 秒,预制件的数量就会增加 1,直到达到 8 个对象。问题在于,随着对象数量的增加,可用于生成的空间会减少,预制件会尝试寻找任何可用空间。如果找不到任何预制件,它会在任何位置生成,导致与其他预制件重叠(参见 GIF)。
如何确保在生成大量对象时预制件不会相互重叠? GIF 显示仍然有足够的可用空间用于生成预制件,但由于某种原因,它没有检测到这些空间并与其他对象重叠。我尝试了一些方法,但没有成功(查看 GetUniqueSpawnPosition)。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpikeController : MonoBehaviour
{
public int initialSpikeCount = 3; // Initial number of spikes
public int maxSpikes = 8; // Maximum number of spikes
public int spikesIncreaseInterval = 8; // Interval for increasing spikes
public float spikeSpawnInterval = 1.5f; // Spikes disappear time
public GameObject spikePrefab; // Spike prefab
public Transform LeftBoundary;
private int currentSpikeCount;
private List<GameObject> spikes = new List<GameObject>();
// Spike size
public Vector3 spikeSize = new Vector3(2.84f, 2.84f, 2.84f);
void Start()
{
currentSpikeCount = initialSpikeCount;
SpawnSpikes();
StartCoroutine(SpikeIncreaseRoutine());
}
void Update()
{
if (spikes.Count < currentSpikeCount)
{
SpawnSpikes();
}
}
private IEnumerator SpikeIncreaseRoutine()
{
while (currentSpikeCount < maxSpikes)
{
yield return new WaitForSeconds(spikesIncreaseInterval);
IncreaseSpikeCount();
}
}
private void SpawnSpikes()
{
ClearSpikes(); // Remove previous spikes if any
for (int i = 0; i < currentSpikeCount; i++)
{
Vector3 spawnPosition = GetUniqueSpawnPosition();
GameObject spike = Instantiate(spikePrefab, spawnPosition, Quaternion.Euler(0, 0, 90f)); // Spawning only on the left
// Set the size of the prefab
spike.transform.localScale = spikeSize;
spikes.Add(spike);
StartCoroutine(RemoveSpikeAfterDelay(spike, spikeSpawnInterval));
}
}
private Vector3 GetUniqueSpawnPosition()
{
BoxCollider2D boundaryCollider = LeftBoundary.GetComponent<BoxCollider2D>();
float boundaryYMin = LeftBoundary.position.y - boundaryCollider.size.y / 2;
float boundaryYMax = LeftBoundary.position.y + boundaryCollider.size.y / 2;
float x = -2.24f; // Fixed position on the left
float y = 0;
float spikeHeight = spikeSize.y; // Spike height
// Adjust y range to avoid spawning outside the boundary
float boundaryMin = boundaryYMin + spikeHeight / 2;
float boundaryMax = boundaryYMax - spikeHeight / 2;
// Try to find a unique spawn position
for (int attempt = 0; attempt < 100; attempt++)
{
y = Random.Range(boundaryMin, boundaryMax); // Adjusted for the height of the spike
Vector3 potentialPosition = new Vector3(x, y, 0);
if (!IsOverlappingWithExistingSpikes(potentialPosition, spikeSize.x, spikeSize.y))
{
return potentialPosition;
}
}
Debug.LogWarning("Cannot find unique positions");
return new Vector3(x, Random.Range(boundaryMin, boundaryMax), 0);
}
private bool IsOverlappingWithExistingSpikes(Vector3 position, float width, float height)
{
// Check for overlap with existing colliders
foreach (var spike in spikes)
{
if (Vector2.Distance(position, spike.transform.position) < (width / 2 + spikeSize.x / 2))
{
return true;
}
}
return false;
}
public void IncreaseSpikeCount()
{
if (currentSpikeCount < maxSpikes)
{
currentSpikeCount++;
SpawnSpikes(); // Create new spikes after increasing the count
}
}
private void ClearSpikes()
{
foreach (var spike in spikes)
{
Destroy(spike);
}
spikes.Clear();
}
private IEnumerator RemoveSpikeAfterDelay(GameObject spike, float delay)
{
yield return new WaitForSeconds(delay);
spikes.Remove(spike);
Destroy(spike);
}
}
我尝试了 100 次尝试来找到生成预制件的位置。我将寻找唯一位置的尝试次数限制为 100 次,因为我不确定更多的尝试次数可能会如何影响整体性能,而且增加尝试次数似乎没有任何区别。
我希望它能为每个预制件找到一个独特的位置,这样它们就不会重叠。然而,它并没有按预期工作。当预制件找不到唯一的位置时,它们会开始寻找任何可用的空间来生成,这会导致重叠。