[英]Checking collisions in near objects for random object spawning in Unity 5
I have almost finished my first game in Unity, which is a simple maze with characters collecting different coins.我几乎完成了我在 Unity 中的第一款游戏,这是一个简单的迷宫,角色们收集不同的硬币。 As it was a hassle to manually put all the different coins in the terrain, I decided to try and make a random generator for the coins.
由于手动将所有不同的硬币放入地形中很麻烦,我决定尝试为硬币制作一个随机生成器。
The script is largely working, but the problem is that it's spawning objects most of the time inside walls.该脚本在很大程度上可以正常工作,但问题是它大部分时间都在墙内生成对象。 So I tried to add rigid bodies to coins, but this is messing with the coins position as the coins have a script for rotation.
所以我尝试为硬币添加刚体,但这与硬币 position 相混淆,因为硬币有一个旋转脚本。 I also have the coins collision triggered because they perform a certain action when colliding with the character.
我还触发了硬币碰撞,因为它们在与角色碰撞时会执行特定动作。
So after some research I saw that I need to check in my generator script for a near object collision and somehow change the spawn position of the coin if it's true.因此,经过一些研究,我发现我需要检查我的生成器脚本是否存在近 object 碰撞,并以某种方式更改硬币的生成 position 如果它是真的。 I'm trying to figure out how I can do that.
我试图弄清楚我该怎么做。 My script is attached to my terrain and it looks like this:
我的脚本附加到我的地形,它看起来像这样:
using System.Collections;
using CustomArrayExtensions;
using UnityEngine;
public class ObjectSpawner : MonoBehaviour
{
[SerializeField] public GameObject[] letters;
GameObject selectedObject;
private int amount = 0;
public int limit;
void Start()
{
StartCoroutine(SpawnObjects());
}
IEnumerator SpawnObjects()
{
selectedObject = letters.GetRandom();
while (amount < limit)
{
Instantiate(selectedObject, new Vector3(Random.Range(35.0f, 950.0f), 13.0f, Random.Range(35.0f, 950.0f)), Quaternion.identity);
yield return new WaitForSeconds(5.0f);
amount++;
}
}
void OnCollisionEnter(Collision col)
{
if (col.gameObject.name == "Fox_Main")
{
Debug.Log("Collision Detected");
}
}
}
So i tried both answers and they didn't help me.Coins and other objects is still spawning close/inside the walls.My boxes have box collider and rigidbody with all positions/rotations locked(i need it that way so that i can destroy it later without moving it with the character),walls have box collider.So i tried to modify your solutions following Unity Documentation.I failed too.Here is what i have done so far.所以我尝试了这两个答案,但它们都没有帮助我。硬币和其他物体仍在靠近/在墙壁内产生。我的盒子有盒子对撞机和刚体,所有位置/旋转都被锁定(我需要这样才能摧毁稍后它不随角色移动),墙壁有盒子对撞机。所以我尝试按照 Unity 文档修改你的解决方案。我也失败了。这是我到目前为止所做的。 See here
看这里
using System.Collections;
using UnityEngine;
public class RandomCrates : MonoBehaviour
{
public GameObject[] crates;
private GameObject selectedCrate;
public int limit = 0;
public float x, y, z;
public float forX_From,forX_To,forZ_From,forZ_To;
private int mask = 1 << 7;
void Start()
{
StartCoroutine(SpawnObjects());
}
IEnumerator SpawnObjects()
{
for (int i = 0; i < crates.Length; i++)
{
for (int j = 0; j < limit; j++)
{
Vector3 freePos = GetFreePosition();
Instantiate(crates[i], freePos, Quaternion.identity);
yield return new WaitForSeconds(0.0f);
}
}
}
Vector3 GetFreePosition()
{
Vector3 position;
Collider[] collisions = new Collider[1];
do
{
position = new Vector3(Random.Range(forX_From, forX_To), 10.0f, Random.Range(forZ_From, forZ_To));
} while (Physics.OverlapBoxNonAlloc(position, new Vector3(x, y, z), collisions, Quaternion.identity, mask) > 0);
return position;
}
} }
Unity provides a simple way to detect collisions in specific position with Physics.OverlapSphere : Unity 提供了一种简单的方法来检测特定 position 与Physics.OverlapSphere的碰撞:
public class ObjectSpawner : MonoBehaviour
{
[SerializeField] public GameObject[] letters;
GameObject selectedObject;
private int amount = 0;
public int limit;
private float radius = 2f; //Radius of object to spawn
void Start()
{
StartCoroutine(SpawnObjects());
}
IEnumerator SpawnObjects()
{
selectedObject = letters[Random.Range(0, letters.Length)];
while (amount < limit)
{
Vector3 spawnPos = new Vector3(Random.Range(35.0f, 950.0f), 13.0f, Random.Range(35.0f, 950.0f));
//Check collisions
if (DetectCollisions(spawnPos) > 0)
continue;
Instantiate(selectedObject, spawnPos, Quaternion.identity);
yield return new WaitForSeconds(5.0f);
amount++;
}
}
private int DetectCollisions(Vector3 pos)
{
Collider[] hitColliders = Physics.OverlapSphere(pos, radius);
return hitColliders.Length;
}
}
In this way, if there is a collision in spawn position, the coin will not be spawned.这样,如果在 spawn position 中发生碰撞,则不会生成硬币。
There are different ways of approaching this problem and given more information one could come up with a smarter approach.有不同的方法可以解决这个问题,如果提供更多信息,人们可能会想出更聪明的方法。 However, to provide you with a simple solution to your problem: You could just pick random positions until you find a "free spot".
但是,为您提供解决问题的简单方法:您可以选择随机位置,直到找到“空闲位置”。 Assuming your coins to have a size of 1, you could do something like:
假设您的硬币大小为 1,您可以执行以下操作:
IEnumerator SpawnObjects()
{
selectedObject = letters.GetRandom();
while(amount < limit)
{
Vector3 freePos = GetFreePosition();
Instantiate(selectedObject, freePos), Quaternion.identity);
yield return new WaitForSeconds(5.0f);
amount++;
}
}
Vector3 GetFreePosition()
{
Vector3 position;
Collider[] collisions = new Collider[1];
do
{
position = new Vector3(Random.Range(35.0f, 950.0f), 13.0f, Random.Range(35.0f, 950.0f));
}
while(Physics.OverlapSphereNonAlloc(position, 1f, collisions) > 0);
return position;
}
Please note that Physics.OverlapSphereNonAlloc()
can also accept a LayerMask for filtering collisions based on layers.请注意,
Physics.OverlapSphereNonAlloc()
也可以接受一个LayerMask来过滤基于层的碰撞。 You might want to look into this, to prevent detecting collision with your terrain, which may well keep the do-while loop from exiting and freeze Unity.您可能需要对此进行研究,以防止检测到与地形的碰撞,这很可能会阻止 do-while 循环退出并冻结 Unity。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.