0

在我的 fps 级别(Unity)中,目标在随机位置生成。我想确保目标不能在物体后面或物体内部产生。

为了确保它们不会在物体后面产生,我已经raycast从玩家到目标。如果它被阻挡,我会重新计算生成点。这很好用,但是,由于目标是球体,因此当目标在物体(例如地板)内的 50% 时,光线投射不会被阻挡。我不想那样,很明显。

为了确定目标是否在另一个对象的范围内,我尝试使用OnCollisionEnterand 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");
}

游戏对象世界是我放置游戏世界所有对象的父对象。

问题是他只考虑了第一个对象的对撞机。我基本上想使用一个由所有关卡对象组成的大型对撞机。

这可能吗?或者有人知道我如何实现这一目标的不同方法吗?

4

1 回答 1

0

您应该使用该GetComponentsInChildren方法而不是GetComponentInChildren,以便您可以从中获取一个colliders 数组,您可以在该数组上执行 aforeach以检查sbounds是否相交。

IE:

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方法真的很慢,所以如果可能的话,它们的使用应该限制在内部AwakeStart方法上。

解决该问题的另一种方法是List<Collider>在开始时创建一个,并将 World 游戏对象的起始子对象添加到其中。如果实例化了另一个,Add则将其添加到您的列表中,如果已销毁,则仅Remove此而已。

然后,就在实例化之前,您可以bounds通过在内部循环来检查Lista foreach,检查会快很多。

====================================

编辑:

好的,这是交易。首先,将这些行添加到您的World游戏对象脚本中(我猜您调用了 class 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>());
}

差不多就是这样。;)

于 2018-01-28T16:59:17.983 回答