c# - 如何在场景中找到彼此最近的物体
问题描述
在现场,我有多个四处游荡的物体。
我需要创建一个系统来检查哪些对象彼此靠近并执行一些逻辑。
例如:
我在场景中有 40 个对象。他们都四处游荡。系统检测到 object4 和 object30 彼此靠近。做一些逻辑(在这两个对象之间随机选择并销毁)。
有什么有效的方法吗?
解决方案
为了对对象何时彼此靠近进行逻辑处理,您首先必须计算到您感兴趣的每个对象的距离。您可以在脚本中的每个对象本身中执行此操作,也可以使用一个脚本来跟踪所有对象他们。
选项 1:一个脚本跟踪所有对象
第一种方式显示了单个脚本如何跟踪所有对象并检查它们是否低于某个阈值。在示例脚本中,对象将通过检查器填充,但您也可以使用标签系统和GameObject.FindGameObjectsWithTag
public class Tracker : MonoBehaviour
{
public GameObject[] trackingObjects;
public float threshold = 1f;
void Update()
{
for(int i = 0; i < trackingObjects.Length; i++){
for(int j = i+1; j < trackingObjects.Length; j++){
Transform objOne = trackingObjects[i].transform;
Transform objTwo = trackingObjects[j].transform;
float distance = Vector3.Distance(objOne.position, objTwo.position);
if (distance < threshold){
Debug.Log(objOne.name + " near " + objTwo.name);
}
}
}
}
}
选项 2:对撞机
这个选项稍微复杂一些,因为每个对象都需要一个刚体和一个碰撞器,并将 isTrigger 设置为 true。(然后,此触发器的大小将等于您要检查的范围)。使用以下解决方案,两个对象在彼此靠近时都会触发此功能,这与单个脚本跟踪方法不同。
public class IsNear : MonoBehaviour
{
void OnTriggerEnter(Collider obj){
Debug.Log(obj.name + "is near");
}
}
选项 3:个人跟踪(无对撞机)
这与第一个选项相同,但每个对象都有一个单独的脚本,不需要碰撞器或附加刚体。它还允许为每个对象配置阈值,而不是作为单个值(与选项 1 一样)
public class IsNear : MonoBehaviour
{
public GameObject[] otherObjects;
public float threshold;
void Update(){
for(int i = 0; i < otherObjects.Length; i++){
Transform otherObj = otherObjects[i].transform;
float distance = Vector3.Distance(transform.position, otherObj.position);
if (distance < threshold){
Debug.Log(gameObject.name + " near " + otherObj.name);
}
}
}
}
值得注意的是,由于这些是距离检查,它们可以通过不执行 Vector3.Distance 所做的平方根运算来进行更多优化,但由于您只有 40 个对象,因此可能不会优化。(除非您正在跟踪可能成百上千的对象)
优化的阈值检查:
public GameObject[] trackingObjects;
public float squaredThreshold = 1f;
void Update()
{
for(int i = 0; i < trackingObjects.Length; i++){
for(int j = i+1; j < trackingObjects.Length; j++){
Transform objOne = trackingObjects[i].transform;
Transform objTwo = trackingObjects[j].transform;
Vector3 toOtherObject = objOne.transform.position - objTwo.transform.position;
if (toOtherObject.sqrMagnitude < squaredThreshold){
Debug.Log(objOne.name + " near " + objTwo.name);
}
}
}
}
推荐阅读
- python-3.x - 并行化文档中所有成对单词组合之间的语音距离
- typescript - 使用 Redux Toolkit asyncThunkCreator 时如何强制执行 DRY
- javascript - JSON.stringify 将字符串中的冒号转换为 unicode 字符
- javascript - 无法读取 javascript 中未定义的属性“推送”
- javascript - 在对象本身内部使用对象方法的结果的语法是什么?
- java - 模拟内联:3.11.2 | 不支持的类文件主要版本 62
- elasticsearch - 在弹性搜索中获取特定日期?
- javascript - 我想在 solana 上铸造一个新的代币。如何使用 solana-web3.js 做到这一点?
- certificate - 如何在 MS Excel 2007 中启用 sha256 支持?
- c# - 如何验证返回列表函数 C# 的断言抛出异常