Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 检测多个对象的接近度并更改其材质颜色_C#_List_Unity3d_Distance_Collision - Fatal编程技术网

C# 检测多个对象的接近度并更改其材质颜色

C# 检测多个对象的接近度并更改其材质颜色,c#,list,unity3d,distance,collision,C#,List,Unity3d,Distance,Collision,我对使用距离计算正确检测物体近邻有问题,希望你们中的一位能帮助我 我想要什么: 在我的场景中有几个具有相同标记的实例化游戏对象,如果它们在x轴和z轴上的距离小于“1”,我想更改它们的材质颜色。为此,我遍历所有对象的列表,并将它们的位置与当前游戏对象的位置进行比较 问题: 碰撞对象上的材质颜色会随机更改,有时碰撞结束后不会再更改 到目前为止我的代码: public class DistanceTester : MonoBehaviour { void Start()

我对使用距离计算正确检测物体近邻有问题,希望你们中的一位能帮助我

我想要什么: 在我的场景中有几个具有相同标记的实例化游戏对象,如果它们在x轴和z轴上的距离小于“1”,我想更改它们的材质颜色。为此,我遍历所有对象的列表,并将它们的位置与当前游戏对象的位置进行比较

问题: 碰撞对象上的材质颜色会随机更改,有时碰撞结束后不会再更改

到目前为止我的代码:

     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);
    }

    ...
}