You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用foreach循环时Physics2D.IgnoreLayerCollision失效问题

颜色匹配门碰撞失效问题修复方案

问题描述

游戏规则为玩家与方形门精灵颜色一致时可穿过门,否则触发碰撞。当前实现中,仅初始颜色对应的门生效,切换玩家颜色后碰撞忽略功能失效。原代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering.Universal;

public class PlayerColor : MonoBehaviour
{
    private Color currentColor;
    private Light2D olight;
    private SpriteRenderer sprite;

    public Color[] colorArray = {
        new Color(0.07843138f, 0.7490196f, 0.1803922f, 1.0f), //Green 14BF2E 
        new Color(0.09019608f, 0.5019608f, 0.9098039f, 1.0f), //Blue 1780E8 
        new Color(0.6313726f, 0.2705882f, 0.9019608f, 1.0f), //Purple A145E6 
        new Color(1f, 0.6392157f, 0.09019608f, 1.0f)  //Orange FFA317
    };

    void Start()
    {
        olight = GetComponent<Light2D>();
        sprite = GetComponent<SpriteRenderer>();

        ChangeColor(sprite.color);
        
    }

    public Color ChangeColor(Color _color)
    {
        Color oldCol = currentColor;
        currentColor = _color;
        olight.color = currentColor;
        sprite.color = currentColor;

        int index = 6;
        foreach(Color color in colorArray)
        {
            if(color == sprite.color)
            {
                Physics2D.IgnoreLayerCollision(3, index);
            }
            else
            {
                Physics2D.IgnoreLayerCollision(3, index, false);
            }
            index++;
        }
        return oldCol;
    }
}

问题根源

  1. 浮点数精度问题:直接使用color == sprite.color比较颜色,由于Color的RGBA值是浮点数,微小的数值差异会导致比较结果为false,切换颜色后无法正确匹配数组中的颜色。
  2. 状态重置不彻底:循环中逐个设置图层碰撞状态,若颜色匹配失败,会错误地将所有图层设为不忽略碰撞,导致功能失效。

修复方案

修改后的代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering.Universal;

public class PlayerColor : MonoBehaviour
{
    private Color currentColor;
    private Light2D olight;
    private SpriteRenderer sprite;

    public Color[] colorArray = {
        new Color(0.07843138f, 0.7490196f, 0.1803922f, 1.0f), //Green 14BF2E 
        new Color(0.09019608f, 0.5019608f, 0.9098039f, 1.0f), //Blue 1780E8 
        new Color(0.6313726f, 0.2705882f, 0.9019608f, 1.0f), //Purple A145E6 
        new Color(1f, 0.6392157f, 0.09019608f, 1.0f)  //Orange FFA317
    };

    void Start()
    {
        olight = GetComponent<Light2D>();
        sprite = GetComponent<SpriteRenderer>();

        // 初始时通过近似匹配找到颜色索引,初始化碰撞状态
        int initialIndex = FindColorIndex(sprite.color);
        if (initialIndex != -1)
        {
            ChangeColorByIndex(initialIndex);
        }
    }

    // 通过颜色索引切换颜色并处理碰撞逻辑
    public void ChangeColorByIndex(int colorIndex)
    {
        if (colorIndex < 0 || colorIndex >= colorArray.Length) return;

        currentColor = colorArray[colorIndex];
        olight.color = currentColor;
        sprite.color = currentColor;

        int layerIndex = 6;
        // 先重置所有门图层与玩家图层的碰撞状态
        foreach (Color _ in colorArray)
        {
            Physics2D.IgnoreLayerCollision(3, layerIndex, false);
            layerIndex++;
        }

        // 仅开启当前颜色对应门图层的碰撞忽略
        Physics2D.IgnoreLayerCollision(3, 6 + colorIndex);
    }

    // 近似匹配颜色,解决浮点数精度问题
    private int FindColorIndex(Color targetColor)
    {
        for (int i = 0; i < colorArray.Length; i++)
        {
            if (ColorApproximatelyEqual(colorArray[i], targetColor))
            {
                return i;
            }
        }
        return -1;
    }

    // 自定义颜色比较方法,设置容忍度避免精度误差
    private bool ColorApproximatelyEqual(Color a, Color b)
    {
        const float tolerance = 0.001f;
        return Mathf.Abs(a.r - b.r) < tolerance &&
               Mathf.Abs(a.g - b.g) < tolerance &&
               Mathf.Abs(a.b - b.b) < tolerance &&
               Mathf.Abs(a.a - b.a) < tolerance;
    }

    // 保留原方法兼容现有调用,内部转用索引逻辑
    public Color ChangeColor(Color _color)
    {
        Color oldCol = currentColor;
        int index = FindColorIndex(_color);
        if (index != -1)
        {
            ChangeColorByIndex(index);
        }
        return oldCol;
    }
}

关键修改点

  • 近似颜色比较:新增ColorApproximatelyEqual方法,通过设置容忍度比较颜色,避免浮点数精度导致的匹配失败。
  • 索引驱动逻辑:新增ChangeColorByIndex方法,直接通过颜色数组索引对应门图层(6+索引),逻辑更可靠。
  • 状态重置优先:每次切换颜色时先重置所有门图层的碰撞状态,再单独开启当前颜色对应的忽略碰撞,确保状态正确。
  • 初始化优化:Start方法中改用近似匹配初始化,确保初始状态正确生效。

内容的提问来源于stack exchange,提问作者Okorare Tega

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 16:25:15