Unity中CSV数据导入ScriptableObject数组失败问题排查
问题:CSV导入ScriptableObject时answers数组赋值报错
开发答题应用时,将CSV题目导入Unity ScriptableObject的过程中,操作answers数组的代码导致报错;移除数组相关代码后,能正常生成150个QuestionCSV资源,但数组无数据。
生成问题的脚本:
public static void GenerateQuestions() //edit function name { string[] allLines = File.ReadAllLines(Application.dataPath + questionCSVPath); //edit variable name foreach(string s in allLines) { string[] splitData = s.Split(','); QuestionCSV question = ScriptableObject.CreateInstance<QuestionCSV>(); //no change to class unless different type of setup such as 2 or 3 stacked numbers question.ID = splitData[0]; question.question = splitData[1]; question.answers[0] = splitData[2]; question.answers[1] = splitData[3]; question.answers[2] = splitData[4]; question.answers[3] = splitData[5]; question.correctAnswer = splitData[6]; question.solution = splitData[7]; AssetDatabase.CreateAsset(question, $"Assets/Resources/Questions/4thSub3/{question.ID}.asset"); } AssetDatabase.SaveAssets(); }
QuestionCSV脚本:
public class QuestionCSV : ScriptableObject { [SerializeField] private string ID; [SerializeField] private string question; [SerializeField] private string[] answers; [SerializeField] private int correctAnswer; [SerializeField] private string solution;
错误原因
- 数组未初始化:创建
QuestionCSV实例时,引用类型的answers数组默认是null,直接通过索引赋值会触发空引用异常。 - 类型不匹配:
correctAnswer是int类型,但直接赋值字符串splitData[6]会引发类型转换错误(移除数组代码后该错误可能被掩盖)。 - 潜在风险:使用
Split(',')分割CSV,如果答案文本中包含逗号,会导致分割结果错乱。
修复方案
1. 初始化answers数组
有两种方式初始化数组:
方式一:在QuestionCSV类中默认初始化
修改QuestionCSV脚本,给数组指定默认长度:
public class QuestionCSV : ScriptableObject { [SerializeField] private string ID; [SerializeField] private string question; [SerializeField] private string[] answers = new string[4]; // 初始化长度为4,对应CSV中的4个选项 [SerializeField] private int correctAnswer; [SerializeField] private string solution; }
方式二:在生成脚本中实例化后初始化
在GenerateQuestions中创建QuestionCSV实例后,先初始化数组再赋值:
QuestionCSV question = ScriptableObject.CreateInstance<QuestionCSV>(); question.ID = splitData[0]; question.question = splitData[1]; // 先初始化数组 question.answers = new string[4]; question.answers[0] = splitData[2]; question.answers[1] = splitData[3]; question.answers[2] = splitData[4]; question.answers[3] = splitData[5];
2. 修复correctAnswer的类型转换
将字符串转为int,同时增加错误处理:
if (int.TryParse(splitData[6], out int correctIdx)) { question.correctAnswer = correctIdx; } else { Debug.LogError($"ID为{splitData[0]}的题目正确答案格式错误:{splitData[6]}"); continue; // 跳过错误数据 }
3. 跳过CSV表头(可选)
如果CSV第一行是字段名(如ID,question,answer1...),需要跳过表头行:
foreach(string s in allLines) { // 跳过空行和表头 if (string.IsNullOrWhiteSpace(s) || s.StartsWith("ID")) continue; string[] splitData = s.Split(','); // ...后续代码 }
内容的提问来源于stack exchange,提问作者wrtuttle
相关产品推荐
相关产品推荐

