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

Unity中如何将二维数组值存入PlayerPrefs?代码报错求助

问题描述

我有一个Pixel类型的二维数组,通过Fill()函数为数组内元素上色。需求是:元素被上色时,在初始化的int[,] checkColorPixel数组对应位置赋值1,未上色的位置赋值0。但当前代码保存到PlayerPrefs时失败报错,相关代码如下:

CreatePixelMap() 方法

public void CreatePixelMap()
{
    Color[] colors = texture.GetPixels();

    Pixels = new Pixel[texture.width, texture.height];
    int[,] checkColorPixel = new int[texture.width, texture.height];

    for (int x = 0; x < texture.width; x++)
    {
        for (int y = 0; y < texture.height; y++)
        {
            if (colors[x + y * texture.width].a >= 0.5f)
            {
                Pixel pixel = Instantiate(_pxObj, _trs);
                pixel.transform.position = new Vector3(x, y);
                pixel.transform.name = $"square{x}-{y}";
                Pixels[x, y] = pixel;

                if (!_allTypeOfColor.ContainsKey(colors[x + y * texture.width]))//新颜色
                {
                    _allTypeOfColor.Add(colors[x + y * texture.width], _countColor);
                    _allPixelGroups.Add(_countColor, new List<Pixel>());
                    _allPixelGroups[_countColor].Add(Pixels[x, y]);
                    Pixels[x, y].id = _countColor;
                    Pixels[x, y]._colorTrue = colors[x + y * texture.width];
                    _countColor++;
                }
                else//旧颜色
                {
                    int foundId = _allTypeOfColor.GetValueOrDefault(colors[x + y * texture.width]);
                    _allPixelGroups[foundId].Add(Pixels[x, y]);
                    Pixels[x, y].id = foundId;
                    Pixels[x, y]._colorTrue = colors[x + y * texture.width];
                }
            }

            if (_pxObj.isFlilled == true)
            {
                checkColorPixel[texture.width, texture.height] = 1;
            }
            else
            {
                checkColorPixel[texture.width, texture.height] = 0;
            }
        }
    }

    PlayerPrefs.SetInt("CheckColorPixel", checkColorPixel[texture.width, texture.height]);
    PlayerPrefs.Save();
    pageSwipe.totalPages = (_countColor - 1) / 10 + 1;
    if ((_countColor - 1) % 10 == 0)
    {
        pageSwipe.totalPages = (_countColor - 1) / 10;
    }
}

Fill() 方法

public void Fill()
{
    isFilledInTrue = true;
    isFlilled = true;
    _colorRen.color = _colorTrue;
    _lineRen.color = _colorTrue;
    PlayerPrefs.SetInt("CheckColorPixel", 1);
    GameManager.Instance.SaveColor();
    _text.text = "";
    _highlight.enabled = false;
}
错误分析
  1. 数组越界:checkColorPixel[texture.width, texture.height]使用数组长度作为索引,而数组有效索引范围是0 ~ 长度-1,直接访问会触发索引越界异常。
  2. 状态判断错误:循环中判断的是预制体_pxObj的isFlilled状态,而非当前创建的Pixels[x,y]的状态,导致所有位置赋值完全不符合预期。
  3. PlayerPrefs使用错误:PlayerPrefs仅支持存储单个int、float、string类型,无法直接存储二维数组;当前代码只存储了一个越界位置的值,完全没有保存整个数组状态;Fill方法中也只是全局存储了一个1,没有对应到具体像素位置。
  4. 变量作用域错误:checkColorPixel是CreatePixelMap方法的局部变量,Fill方法无法访问,无法更新对应位置的状态。
解决方案

1. 调整变量作用域

将checkColorPixel改为类的成员变量,确保Fill方法和其他逻辑能访问到。

2. 修正数组索引和状态判断

在循环中使用当前的x、y作为索引,判断当前Pixels[x,y]的isFlilled状态来赋值。

3. 序列化二维数组存储到PlayerPrefs

将二维数组转为一维数组,封装成可序列化的类,再转为Json字符串存储;读取时反向解析。

修正后的代码示例

全局变量调整

// 在包含CreatePixelMap的类中添加成员变量
private int[,] checkColorPixel;

修正CreatePixelMap方法

public void CreatePixelMap()
{
    Color[] colors = texture.GetPixels();

    Pixels = new Pixel[texture.width, texture.height];
    checkColorPixel = new int[texture.width, texture.height];

    for (int x = 0; x < texture.width; x++)
    {
        for (int y = 0; y < texture.height; y++)
        {
            // 默认未上色赋值0
            checkColorPixel[x, y] = 0;

            if (colors[x + y * texture.width].a >= 0.5f)
            {
                Pixel pixel = Instantiate(_pxObj, _trs);
                pixel.transform.position = new Vector3(x, y);
                pixel.transform.name = $"square{x}-{y}";
                // 记录当前像素的坐标,供Fill方法使用
                pixel.x = x;
                pixel.y = y;
                Pixels[x, y] = pixel;

                // 颜色分组逻辑保持不变
                if (!_allTypeOfColor.ContainsKey(colors[x + y * texture.width]))
                {
                    _allTypeOfColor.Add(colors[x + y * texture.width], _countColor);
                    _allPixelGroups.Add(_countColor, new List<Pixel>());
                    _allPixelGroups[_countColor].Add(Pixels[x, y]);
                    Pixels[x, y].id = _countColor;
                    Pixels[x, y]._colorTrue = colors[x + y * texture.width];
                    _countColor++;
                }
                else
                {
                    int foundId = _allTypeOfColor.GetValueOrDefault(colors[x + y * texture.width]);
                    _allPixelGroups[foundId].Add(Pixels[x, y]);
                    Pixels[x, y].id = foundId;
                    Pixels[x, y]._colorTrue = colors[x + y * texture.width];
                }

                // 根据当前像素的初始填充状态赋值
                checkColorPixel[x, y] = Pixels[x, y].isFlilled ? 1 : 0;
            }
        }
    }

    // 传递数组信息给GameManager
    GameManager.Instance.SetCheckColorPixel(checkColorPixel, texture.width, texture.height);
    // 调用序列化存储方法
    GameManager.Instance.SaveCheckColorPixelToPlayerPrefs();

    // 分页逻辑保持不变
    pageSwipe.totalPages = (_countColor - 1) / 10 + 1;
    if ((_countColor - 1) % 10 == 0)
    {
        pageSwipe.totalPages = (_countColor - 1) / 10;
    }
}

修正Pixel类(添加坐标字段)

public class Pixel : MonoBehaviour
{
    // 添加坐标字段,记录当前像素在数组中的位置
    public int x;
    public int y;
    // 原有字段保持不变
    public bool isFlilled;
    public bool isFilledInTrue;
    public Color _colorTrue;
    public Renderer _colorRen;
    public Renderer _lineRen;
    public Text _text;
    public MonoBehaviour _highlight;
    public int id;
}

修正Fill方法

public void Fill()
{
    isFilledInTrue = true;
    isFlilled = true;
    _colorRen.color = _colorTrue;
    _lineRen.color = _colorTrue;
    _text.text = "";
    _highlight.enabled = false;

    // 更新对应位置的checkColorPixel并保存
    GameManager.Instance.UpdateCheckColorPixel(x, y, 1);
    GameManager.Instance.SaveCheckColorPixelToPlayerPrefs();
    GameManager.Instance.SaveColor();
}

在GameManager中添加序列化存储逻辑

public class GameManager : MonoBehaviour
{
    public static GameManager Instance;
    private int[,] checkColorPixel;
    private int textureWidth;
    private int textureHeight;

    private void Awake()
    {
        Instance = this;
    }

    // 外部设置checkColorPixel的方法
    public void SetCheckColorPixel(int[,] array, int width, int height)
    {
        checkColorPixel = array;
        textureWidth = width;
        textureHeight = height;
    }

    // 更新单个像素的状态
    public void UpdateCheckColorPixel(int x, int y, int value)
    {
        if (x >= 0 && x < textureWidth && y >= 0 && y < textureHeight)
        {
            checkColorPixel[x, y] = value;
        }
    }

    // 保存到PlayerPrefs
    public void SaveCheckColorPixelToPlayerPrefs()
    {
        // 将二维数组转为一维数组
        int[] flatArray = new int[textureWidth * textureHeight];
        for (int y = 0; y < textureHeight; y++)
        {
            for (int x = 0; x < textureWidth; x++)
            {
                flatArray[y * textureWidth + x] = checkColorPixel[x, y];
            }
        }

        // 封装为可序列化的类
        CheckColorData data = new CheckColorData
        {
            width = textureWidth,
            height = textureHeight,
            values = flatArray
        };

        // 转为Json字符串存储
        string json = JsonUtility.ToJson(data);
        PlayerPrefs.SetString("CheckColorPixel", json);
        PlayerPrefs.Save();
    }

    // 从PlayerPrefs加载
    public void LoadCheckColorPixel()
    {
        if (!PlayerPrefs.HasKey("CheckColorPixel")) return;

        string json = PlayerPrefs.GetString("CheckColorPixel");
        CheckColorData data = JsonUtility.FromJson<CheckColorData>(json);

        textureWidth = data.width;
        textureHeight = data.height;
        checkColorPixel = new int[textureWidth, textureHeight];

        // 将一维数组转回二维数组
        for (int i = 0; i < data.values.Length; i++)
        {
            int x = i % textureWidth;
            int y = i / textureWidth;
            checkColorPixel[x, y] = data.values[i];
        }
    }

    // 辅助序列化类
    [System.Serializable]
    private class CheckColorData
    {
        public int width;
        public int height;
        public int[] values;
    }

    // 原有SaveColor方法保持不变
    public void SaveColor()
    {
        // 你的原有逻辑
    }
}

内容的提问来源于stack exchange,提问作者Mr hydro

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 15:12:02