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; }
错误分析
- 数组越界:
checkColorPixel[texture.width, texture.height]使用数组长度作为索引,而数组有效索引范围是0 ~ 长度-1,直接访问会触发索引越界异常。 - 状态判断错误:循环中判断的是预制体
_pxObj的isFlilled状态,而非当前创建的Pixels[x,y]的状态,导致所有位置赋值完全不符合预期。 - PlayerPrefs使用错误:PlayerPrefs仅支持存储单个int、float、string类型,无法直接存储二维数组;当前代码只存储了一个越界位置的值,完全没有保存整个数组状态;Fill方法中也只是全局存储了一个1,没有对应到具体像素位置。
- 变量作用域错误:
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
相关产品推荐
相关产品推荐

