Unity 报错合集,从现在开始记录于该博客中
- 1. 前言
- 2. 错误名 && 错误原因 && 解决方法
- 2.1 The supplied array needs to be the same size as the Mesh.vertices array.
- 2.2 Shader.Find()查找失败
- 2.3 修改gameobject的Position和Rotation 不能达到预期
- 2.4 空指针报错 NullReferenceException -->(Unity三维模型导出插件 Exporter相关)
- 2.5 LineRenderer渲染出错
- 2.6 Failed setting triangles. Some indices are referencing out of bounds vertices
1. 前言
- 用于汇总在代码书写中所遇到的错误,方便自己和一些同样在书写Unity脚本时遇到此类错误的同僚进行查找和解决问题。直接在网页中按住
Ctrl + F
进行报错问题的搜索即可!!该文档将会不断地得到完善,直到放弃Unity编程。
2. 错误名 && 错误原因 && 解决方法
2.1 The supplied array needs to be the same size as the Mesh.vertices array.
-
问题提示,与顶点Vertices的数量不一致,超出边界,然后将三个值打印出来(创建MeshFilter之前),代码&&报错 如图:
-
代码:
Debug.Log("=========="); Debug.Log("temp_Nor_List.Count: " + temp_Nor_List.Count); Debug.Log("points.Count: " + points.Count); Debug.Log("newTriangles.Length: " + newTriangles.Length); Debug.Log("=========="); //获得切面顶点法向量 mesh.normals = temp_Nor_List.ToArray(); //获得切面顶点坐标 mesh.vertices = points.ToArray(); //获得切面三角关系 mesh.triangles = new int[newTriangles.Length]; mesh.triangles = newTriangles; //绘制 cutPlaneMark(mesh); Debug.Log("绘制结束!!!!"); //绘制函数 将三角面生成新的物体 进行渲染 并绑定到原物体上,从而实现视觉上的"物体某一个面的渲染" //这个操作是不会Shader编程 而采取的替代手段 //cutPlaneMark(Mesh mesh); cutPlaneMark(points, temp_Nor_List, newTriangles);
-
报错:
因此,可以确认的是:这跟三个量所对应的数量无关(
属于正常,不存在问题
) -
解决办法:
绕开Mesh,而是直接给 cutPlaneMark()函数传入Mesh的三个数组数据,则不会报错void cutPlaneMark(List<Vector3> ver,List<Vector3> nor,int[] tri ) { //Mesh meshToMark = new Mesh(mesh); //Mesh meshToMark = mesh; //meshToMark.vertices = mesh.vertices; //meshToMark.triangles = mesh.triangles; //meshToMark.normals = mesh.normals; //Graphics.DrawMeshNow(meshToMark, Vector3.zero,Quaternion.identity); GameObject PlaneMark = new GameObject("PlaneMark"); PlaneMark.transform.SetParent(beCutThing.transform); PlaneMark.AddComponent<MeshFilter>(); PlaneMark.GetComponent<MeshFilter>().mesh.vertices = ver.ToArray(); PlaneMark.GetComponent<MeshFilter>().mesh.triangles = tri; PlaneMark.GetComponent<MeshFilter>().mesh.normals = nor.ToArray(); PlaneMark.transform.position = Vector3.zero; PlaneMark.transform.rotation = Quaternion.Euler(Vector3.zero); PlaneMark.tag = "temp_cutplane_mark"; PlaneMark.AddComponent<MeshRenderer>(); PlaneMark.GetComponent<MeshRenderer>().material.color = Color.red; GameObject planeMark = GameObject.Instantiate(PlaneMark); Vector3[] temp_nor = planeMark.GetComponent<MeshFilter>().mesh.normals; for(int i=0;i<temp_nor.Length;i++) { temp_nor[i] = -temp_nor[i]; } planeMark.GetComponent<MeshFilter>().mesh.normals = temp_nor; }
-
效果如图:
(总结:结果不理想,标注未达到预期效果,重新考虑新的办法(Shader编程 GL来绘制线框(还未更新)),与上述代码报错无关)
2.2 Shader.Find()查找失败
-
NullReferenceException : UnityEngine.Material..ctor (UnityEngine.Shader shader) (at D:/unity/artifacts/generated/common/runtime/ShaderBindings.gen.cs:254)
GameObject line1 = new GameObject("line1"); line1.transform.SetParent(beCutThing.transform); line[0] = line1.AddComponent<LineRenderer>(); line[0].material = new Material(Shader.Find("snapTurnArrow")); line1.GetComponent<LineRenderer>().useWorldSpace = false; line[0].positionCount = points.Count + 1; line[0].startWidth = 0.0003f; line[0].endWidth = 0.0003f; for (int i = 0; i < points.Count; i++) line[0].SetPosition(i, points[i]);//设置渲染顶点 line[0].SetPosition(points.Count, points[0]);
-
错误原因:
此处是因为我查找的是一个格式为Material的材质,而非Shader类型。并且Shader只能找到Resources文件夹中的(来自于网络),但是可以采用如下办法进行规避该错误:public Shader shader;
,并主动进行赋值,则不需要利用Shader.Find()方法进行查找。 -
解决办法:
首先在类开始处定义一个Material变量,并在Unity中赋值
然后将line[0].material = new Material(Shader.Find("snapTurnArrow"));
改为:line[1].material = material;
2.3 修改gameobject的Position和Rotation 不能达到预期
-
Position VS localPosition && Rotation VS localRotation(简单讲解)
-
当前Unity版本为 2017.3.0f ,需要注意的是:在此版本中Transform中对旋转角和位置做了区分
-
对比:
项目 Value position 表示物体的世界坐标 localRotation 表示物体的局部坐标(以父物体为参照) rotation 表示物体的世界旋转角度 localRotation 表示物体的局部旋转角度(以父物体为参照) -
代码:
line1.transform.position = Vector3.zero; line2.transform.position = Vector3.zero; Debug.Log("line1.transform.position: " + line1.transform.position); Debug.Log("line2.transform.position: " + line2.transform.position); Debug.Log("=========修正位置&&角度=========="); //line1.transform.position = Vector3.zero; //line2.transform.position = Vector3.zero; line1.transform.localPosition = Vector3.zero; line2.transform.localPosition = Vector3.zero; Debug.Log("line1.transform.position: " + line1.transform.position); Debug.Log("line2.transform.position: " + line2.transform.position); Debug.Log("============修正完成=============");
通过对比可知,localPosition才将其Position选项变为了(0,0,0)–>局部坐标,Position代表世界坐标,当物体的Position被赋值时,Unity会自动将其转化为当前的局部坐标进行赋值!!
-
采用局部坐标和旋转角度后 获得预期效果
Debug.Log("=========修正位置&&角度=========="); line1.transform.localPosition = Vector3.zero; line2.transform.localPosition = Vector3.zero; Debug.Log("line1.transform.position: " + line1.transform.position); Debug.Log("line2.transform.position: " + line2.transform.position); line1.transform.localRotation = Quaternion.Euler(Vector3.zero); line2.transform.localRotation = Quaternion.Euler(Vector3.zero); Debug.Log("============修正完成=============");
2.4 空指针报错 NullReferenceException -->(Unity三维模型导出插件 Exporter相关)
-
NullReferenceException: Object reference not set to an instance of an object (wrapper stelemref) object:stelemref (object,intptr,object)
-
经过验证,是该数组在定义时未进行内存分配!
而在调用ImgSpcExporter.ObjectsToExport 时,直接进行赋值,导致出错imgSpcExporter.ObjectsToExport[0] = game;
public void ObjExporter() { ImgSpcExporter imgSpcExporter = new ImgSpcExporter(); string path = Application.dataPath + "/ExportFile/" + "第" + Export_num + "个导出的文件.obj"; Directory.CreateDirectory(path + "ExportFile"); Debug.Log("path: " + path); imgSpcExporter.SetFilename(path);//设置导出文件夹 //执行导出操作 GameObject game = GameObject.FindWithTag("ChosenObject"); Debug.Log("game:" + (game == null ? "yes" : "no")); if (game != null) { imgSpcExporter.ObjectsToExport = new Object[1];//需要先进行内存分配 再赋值 避免报错 imgSpcExporter.ObjectsToExport[0] = game; imgSpcExporter.Export(); Debug.Log("已经导出!!"); } else { Debug.Log("未找到物体"); } }
2.5 LineRenderer渲染出错
-
传入LineRenderer的为点集(SetPosition(index,position) 方法),但是渲染出来却是一整块正方形区域,并且大小和预设值不同。
-
问题原因:
我给父物体也增加了LineRenderer组件,导致报错,删去即可。在给物体做额外的标记,仅需要给其子物体加上LineRenderer进行渲染就可以 -
代码
GameObject line2 = new GameObject("line2");
Debug.Log("line2" + line2);
line2.tag = "temp_cutplane_mark";
line2.transform.SetParent(beCutThing.transform);
line[1] = line2.AddComponent<LineRenderer>();//line为LineRenderer数组
line[1].material = material;
//line[1].material = new Material(Shader.Find("snapTurnArrow"));
line2.GetComponent<LineRenderer>().useWorldSpace = false;
line2.transform.localScale.Set(1, 1, 1);//设置其大小,避免出现过大情况 就不会附着在父物体上
line[1].positionCount = points.Count + 1;
line[1].startWidth = 0.0003f;
line[1].endWidth = 0.0003f;
for (int i = 0; i < points.Count; i++)
line[1].SetPosition(i, points[i]);//设置渲染顶点
line[1].SetPosition(points.Count, points[0]);
line2.transform.localPosition = Vector3.zero;
line2.transform.localRotation = Quaternion.Euler(Vector3.zero);
2.6 Failed setting triangles. Some indices are referencing out of bounds vertices
- Mesh中Triangles数组存储的顶点索引值超过了Vertices的大小
- 对于此类问题,首先可以大致确定问题出在
Triangles数组的赋值过程
中,