用mesh.uv改变material在triangles的显示位置

本文介绍如何使用Unity创建一个基于网格的拼图游戏。主要内容包括如何通过编程将原图分割成指定数量的小块,并将其正确地映射到每个网格单元上。通过设置顶点和UV坐标来生成每个拼图块的网格,再利用材质贴图渲染到网格上。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

由于要做一个puzzle拼图游戏,假设为r*c的拼图,所以要把原图分为r行c列,每一个单元显示原图材质的[width*(1/c)*nc,height*(1/r)*nr]的位置,其中nc为列索引,nr为行索引。

1,每一块需要是一个有四个顶点,两个三角形组成的mesh:

MeshRenderer renderer = gameObject.AddComponent<MeshRenderer>();
Mesh mesh = meshfilter.mesh;
mesh.vertices =  new Vector3[]{new Vector3(0,0,0),new Vector3(0,1,0),new Vector3(1,1,0),new Vector3(1,0,0)};
newUV = new Vector2[] { new Vector2(0, 0), new Vector2(0, 1), new Vector2(num, 1), new Vector2(1, 0) };//0,0为材质左下角,1,1为右上角,可以根据切块的大小改变为[width*(1/c)*nc,height*(1/r)*nr]
mesh.uv = newUV;
mesh.triangles =  new int[] { 0, 1, 2, 2, 3, 0 };
2,给每一块添加网格过滤器MeshFilter将材质贴图渲染在Mesh上

MeshRenderer renderer = gameObject.AddComponent<MeshRenderer>();
renderer.material = material;
这样就生成一个quad网格,用来将切割的图片块显示在网格上




void CreateClosedRoad(GameObject customQuadGO, List<Vector3> points, Material loadedMat) { if (points.计数 < 4) throw new ArgumentException(“至少需要4个以上的点才能创建一条闭合道路”); // 确保道路是闭合的,复制首个元素到末尾模拟闭合效果 List<Vector3> closedPoints = DuplicatePathToFormStrip(points); List<int> indices = GenerateTriangleIndicesForClosure(closedPoints.Count); // 构建 Mesh 数据 Mesh mesh = new Mesh(); mesh.vertices = closedPoints.ToArray(); // 设置顶点位置 mesh.triangles = indices.ToArray(); // 设置三角形索引 // 计算法线和 UV 映射 (可选,提升视觉质量) mesh.RecalculateNormals(); // 将生成的 Mesh 应用到游戏对象上 var mf = customQuadGO.AddComponent<MeshFilter>(); mf.mesh = mesh; // 添加渲染组件 customQuadGO.AddComponent<MeshRenderer>(); Renderer renderer = customQuadGO.GetComponent<Renderer>(); renderer.material = loadedMat; // 应用材质 } 私有 List<Vector3> DuplicatePathToFormStrip(List<Vector3> originalPoints) { List<Vector3> duplicatedPoints = new List<Vector3>(); for (int i = 0; i < originalPoints.Count; i++) { // 每个原有点都对应两条平行路径 Vector3 direction = GetDirectionAtPoint(originalPoints, i).normalized; Vector3 perpendicular = Vector3.Cross(direction, Vector3.up).normalized; // 左侧点(偏移向外) duplicatedPoints.Add(originalPoints[i] - perpendicular * roadWidth / 2f); // 右侧点(偏移向内) duplicatedPoints.Add(originalPoints[i] + perpendicular * roadWidth / 2f); } return duplicatedPoints; } // 辅助方法:获取某一点的方向向量(假设两点间方向) 私有 Vector3 GetDirectionAtPoint(List<Vector3> points, int index) { 如果 (索引 == 0) 返回点数[1] - 点数[0];// 第一个点采用下一段方向 else if (index == points.计数 - 1) 返回点数[index] - 点数[index - 1];// 最后一个点采用前一段方向 还 返回 (points[index + 1] - points[index - 1]).normalized;// 其他点取中间方向 } List<int> GenerateTriangleIndicesForClosure(int vertexCount) { if (vertexCount < 4 || vertexCount % 2 != 0) throw new ArgumentException(“顶点计数应为偶数且大于或等于 4。”); List<int> indices = new List<int>(); // 构建内部矩形分割 for (int i = 0; i < vertexCount - 2; i += 2) { int leftStart = i; int rightStart = i + 1; // 添加第一个三角形 indices.AddRange(new int[] { leftStart, rightStart, leftStart + 2 }); // 添加第二个三角形 indices.AddRange(new int[] { rightStart, rightStart + 2, leftStart + 2 }); } // 完善闭环处理 if (vertexCount >= 4) { int firstLeft = 0; int firstRight = 1; int lastLeft = vertexCount - 2; int lastRight = vertexCount - 1; // 关联最后一排回到第一列构成封闭结构 indices.AddRange(new int[] { lastLeft, lastRight, firstLeft }); indices.AddRange(new int[] { lastRight, firstRight, firstLeft }); } return indices; }上面代码中顶点坐标围成的mesh是带状的 如何给围成的区域染色
03-19
void CreateClosedRoad(List<Vector3> points, Material loadedMat) { if (points.Count < 4) throw new ArgumentException("至少需要4个以上的点才能创建一条闭合道路"); // 确保道路是闭合的,复制首个元素到末尾模拟闭合效果 List<Vector3> closedPoints = DuplicatePathToFormStrip(points); List<int> indices = GenerateTriangleIndicesForClosure(closedPoints.Count); GameObject gameObject = new GameObject("Quad"); gameObject.transform.SetParent(transform, true); // 构建 Mesh 数据 Mesh mesh = new Mesh(); mesh.vertices = closedPoints.ToArray(); // 设置顶点位置 mesh.triangles = indices.ToArray(); // 设置三角形索引 // 计算法线和 UV 映射 (可选,提升视觉质量) mesh.RecalculateNormals(); // 将生成的 Mesh 应用到游戏对象上 var mf = gameObject.AddComponent<MeshFilter>(); mf.mesh = mesh; // 添加渲染组件 gameObject.AddComponent<MeshRenderer>(); Renderer renderer = gameObject.GetComponent<Renderer>(); renderer.material = loadedMat; // 应用材质 } // 增强型版本 - 创建更多细分层次增强立体感 List<Vector3> DuplicatePathToFormStrip(List<Vector3> originals) { float segmentDetailFactor = 5F; //控制细分数目因子越大越细致 List<Vector3> refinedResult = new List<Vector3>(); for (int idx = 0; idx < originals.Count() - 1; ++idx) { Vector3 currPnt = originals[idx]; Vector3 nextPnt = originals[(idx + 1) % originals.Count()]; // 插值计算沿途若干中间参考位置以便更好拟合实际轨迹走向 for (float t = 0; t <= segmentDetailFactor; t += 1) { float ratio = t / segmentDetailFactor; Vector3 interpolatedPt = Vector3.Lerp(currPnt, nextPnt, ratio); // 此处同样沿法线方向拓展获得双边布局形式... Vector3 dir = (nextPnt - currPnt).normalized; Vector3 normalVec = Vector3.Cross(dir, Vector3.up).normalized; refinedResult.Add(interpolatedPt - normalVec * roadWidth * .5F); //左半部 refinedResult.Add(interpolatedPt + normalVec * roadWidth * .5F); //右半部 } } return refinedResult; } List<int> GenerateTriangleIndicesForClosure(int vertexCount) { if (vertexCount < 4 || vertexCount % 2 != 0) throw new ArgumentException("Vertex count should be even and greater than or equal to four."); List<int> indices = new List<int>(); // 构建内部矩形分割 for (int i = 0; i < vertexCount - 2; i += 2) { int leftStart = i; int rightStart = i + 1; // 添加第一个三角形 indices.AddRange(new int[] { leftStart, rightStart, leftStart + 2 }); // 添加第二个三角形 indices.AddRange(new int[] { rightStart, rightStart + 2, leftStart + 2 }); } // 完善闭环处理 if (vertexCount >= 4) { int firstLeft = 0; int firstRight = 1; int lastLeft = vertexCount - 2; int lastRight = vertexCount - 1; // 关联最后一排回到第一列构成封闭结构 indices.AddRange(new int[] { lastLeft, lastRight, firstLeft }); indices.AddRange(new int[] { lastRight, firstRight, firstLeft }); } return indices; }上面的代码已经成功绘制出了道面面的外边框的形状 带状的 但是我实际想要的是面状的mesh 如何调整
最新发布
03-20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值