在我的fps级别(Unity)中,目标会在随机位置产生。我想确保目标不能在对象后面或对象内部生成。
为了确保它们不会在对象后面产生,我已经从玩家到目标进行了raycast
。如果它被阻塞,我会重新计算生成点。这样可以正常工作,但是,由于目标是球体,当目标在物体内部(例如地板)的50%时,光线投射不会被阻挡。我显然不希望这样。
要确定目标是否在另一个对象的范围内,我尝试使用OnCollisionEnter
和OnCollisionExit
。虽然这只是在将目标移动到另一个对象内部时有效,但当一个脚本的更新周期重新计算生成位置而目标的更新周期跟踪碰撞时,它似乎是不可靠的。
所以我找了一个不同的方法。这是我提出的(来自Unity文档):
m_Collider2 = spawnpoints[i].GetComponent<Collider>();
m_Collider = world.GetComponentInChildren<Collider>();
if (m_Collider.bounds.Intersects(m_Collider2.bounds))
{
Debug.Log("Bounds intersecting");
}
游戏对象世界是我放置游戏世界所有物体的父母。
问题是他只考虑了第一个物体的对撞机。我基本上想要使用一个由所有关卡对象组成的大型对撞机。
这可能吗?或者是否有人知道如何实现这一目标的不同方法?
答案 0 :(得分:0)
您应该使用GetComponentsInChildren
方法而不是GetComponentInChildren
,这样您就可以从中获取collider
个数组,您可以在其中执行foreach
来检查如果bounds
相交。
即:
m_Collider2 = spawnpoints [i].GetComponent<Collider>();
m_Collider = world.GetComponentsInChildren<Collider>();
foreach(Collider objCollider in m_Collider) {
if (objCollider.bounds.Intersects(m_Collider2.bounds))
{
Debug.Log("Bounds intersecting");
break;
}
}
但是,这种做事方式对CPU来说非常沉重,因为GetComponent
方法非常慢,所以如果可能的话,它们的使用应该限制在Awake
和Start
方法中。
解决问题的另一种方法是在开始时创建一个List<Collider>
,然后将World游戏对象的起始子项添加到其中。如果另一个实例化,只需将Add
添加到您的列表中,如果它被销毁,只需Remove
。
然后,就在实例化之前,您可以通过使用bounds
在List
内循环来检查foreach
,检查速度会快得多。
==================================
编辑:
好的,这是交易。首先,将这些行添加到World
游戏对象脚本中(我猜你称之为World
类):
using UnityEngine;
using System.Collections.Generic; //Namespace needed to use the List type
public class World : MonoBehaviour {
//The list which will hold references to the children game objects colliders
public List<Collider> childrenColliders;
private void Start() {
//Code used to populate the list at start
childrenColliders = new List<Collider>(GetComponentsInChildren<Collider>());
}
现在,因为在生成新对象的脚本中已经有一个world
变量,它保存了对World
类的引用:
foreach(Collider coll in world.childrenColliders) {
if (coll.bounds.Intersects(m_Collider2.bounds))
{
Debug.Log("Bounds intersecting");
break;
}
}
当然,正如我之前所说,记得将新产生的游戏对象的对撞机添加到列表中:
void AddNewGameObject() {
// spawnPoint is the transform.position Vector3 you'll use for the new game object
var newGameObject = Instantiate(yourObjectPrefab, spawnPoint, Quaternion.identity, world.transform);
world.childrenColliders.Add(newGameObject.GetComponent<Collider>());
}
这就是它。 ;)