C# 检测多个对象的接近度并更改其材质颜色
我对使用距离计算正确检测物体近邻有问题,希望你们中的一位能帮助我 我想要什么: 在我的场景中有几个具有相同标记的实例化游戏对象,如果它们在x轴和z轴上的距离小于“1”,我想更改它们的材质颜色。为此,我遍历所有对象的列表,并将它们的位置与当前游戏对象的位置进行比较 问题: 碰撞对象上的材质颜色会随机更改,有时碰撞结束后不会再更改 到目前为止我的代码:C# 检测多个对象的接近度并更改其材质颜色,c#,list,unity3d,distance,collision,C#,List,Unity3d,Distance,Collision,我对使用距离计算正确检测物体近邻有问题,希望你们中的一位能帮助我 我想要什么: 在我的场景中有几个具有相同标记的实例化游戏对象,如果它们在x轴和z轴上的距离小于“1”,我想更改它们的材质颜色。为此,我遍历所有对象的列表,并将它们的位置与当前游戏对象的位置进行比较 问题: 碰撞对象上的材质颜色会随机更改,有时碰撞结束后不会再更改 到目前为止我的代码: public class DistanceTester : MonoBehaviour { void Start()
public class DistanceTester : MonoBehaviour
{
void Start()
{
}
void Update()
{
var menschen = GameObject.FindGameObjectsWithTag("Mensch");
float positionX = transform.position.x;
float positionZ = transform.position.z;
foreach (GameObject mensch in menschen)
{
float distanceX = Mathf.Abs(mensch.transform.position.x - positionX);
float distanceZ = Mathf.Abs(mensch.transform.position.z - positionZ);
if (gameObject != mensch) //Making sure the object is not the same
{
if (distanceX <= 1 && distanceZ <= 1)
{
GetComponent<Renderer>().material.color = Color.red;
mensch.GetComponent<Renderer>().material.color = Color.red;
}
else
{
GetComponent<Renderer>().material.color = Color.green;
mensch.GetComponent<Renderer>().material.color = Color.green;
}
}
}
}
}
公共类距离测试仪:单行为
{
void Start()
{
}
无效更新()
{
var menschen=GameObject.FindGameObjectsWithTag(“Mensch”);
浮动位置x=变换位置x;
浮动位置z=变换位置z;
foreach(游戏对象mensch在menschen中)
{
浮动距离x=Mathf.Abs(mensch.transform.position.x-positionX);
浮动距离z=Mathf.Abs(mensch.transform.position.z-positionZ);
if(gameObject!=mensch)//确保对象不同
{
如果(distanceX主要问题可能是您也设置了
GetComponent<Renderer>().material.color = ...;
其中,此Linq表达式使用and
然后您可以非常高效地迭代\u实例
更有效的方法是只从全局控制器迭代一次,而不是在DistanceTester
!的每个实例中迭代一次(顺便说一句,您知道有;)还有..为什么你的方法比使用Collider更有效?你正在使用FindGameObjectsWithTag
迭代每个对象,并使用GetComponent
设置颜色…对我来说不是很有效tbh;)是的,我知道,我已经实现了它,但得到了相同的结果。我也不需要值所以我认为不使用矢量会更有效。你能指出一种方法,如何比迭代所有对象更有效地检测碰撞吗?我已经有了碰撞器的设置,但它不能很好地用于快速移动的对象。我知道的最快的方法是使用(如果对象上有三维碰撞器)在2DWow中,非常感谢您为我指明了正确的方向。您的代码比我的代码要流畅得多。由于对象是动态生成/销毁的,我需要在每一帧调用FindGameObjectsSwithTag。您如何从全局控制器设置迭代?我是否需要在第一个要创建的foreach循环中嵌套另一个foreach循环能够比较对象还是有更好的方法使用Linq?
using Sytsem.Linq;
public class DistanceTester : MonoBehaviour
{
// reference this via the Inspector already
[SerializeField] private Renderer _renderer;
private void Awake()
{
// As fallback get it ONCE
if(!_renderer) _renderer = GetComponent<Renderer>();
}
private void Update()
{
// If possible you should also store this ONCE
var menschen = GameObject.FindGameObjectsWithTag("Mensch");
// This checks if ANY of the objects that is not this object is clsoe enough
if(menschen.Where(m => m != gameObject).Any(m => (transform.position - m.transform.position).sqrMagnitude < 1))
{
_renderer.material.color = Color.red;
}
else
{
_renderer.material.color = Color.green;
}
}
}
menschen.Where(m => m!= gameObject).Any(m => (transform.position - m.transform.position).sqrMagnitude < 1)
var isClose = false;
foreach(var m in menschen)
{
if(m == gameObject) continue;
if((transform.position - m.transform.position).sqrMagnitude < 1)
{
isClose = true;
break;
}
}
if(isClose)
{
...
public class DistanceTester : MonoBehaviour
{
private static HashSet<DistanceTester> _instances = new HashSet<DistanceTester>();
private void Awake()
{
_instances.Add(this);
...
}
private void OnDestroy()
{
_instances.Remove(this);
}
...
}