Unity开发:如何将GameObject坐标设为Mesh顶点生成动态平面
AR自定义投影平面顶点赋值异常解决方案
核心问题根因
- 坐标空间不匹配:Mesh的顶点数据默认使用Mesh挂载对象的本地坐标系,直接将
transform.position拿到的追踪点世界坐标写入顶点数组,会产生完全错乱的坐标偏移,这是该类问题的最常见诱因。 - 顶点绕序不符合Mesh拓扑规则:四边形平面的4个顶点未按顺时针/逆时针连续顺序排列,会触发Unity正面剔除、三角面拼接错误,视觉上表现为位置偏移、面消失、形状扭曲。
- Mesh数据未触发刷新:修改顶点数组后未重新绑定Mesh、未调用重建接口,Unity不会更新渲染缓存。
- 未对齐追踪对象的旋转/缩放:仅传入位置未做旋转、缩放的坐标转换,会导致平面和追踪图像无法对齐。
修复步骤
- 统一坐标空间
实例化平面对象后,使用平面对象自身的Transform将所有追踪点的世界坐标转换为本地坐标,再写入顶点数组,转换接口为transform.InverseTransformPoint(worldPosition)。建议将平面对象的初始位置设置为4个追踪点的中心,降低浮点计算误差。 - 校准顶点顺序与三角面索引
4个顶点按「左上→右上→右下→左下」的顺时针顺序排列,三角面索引按两个三角形拼接四边形的规则配置,确保正面朝向相机,不会被剔除。如果渲染后平面不可见,反转三角面索引顺序即可。 - 强制刷新Mesh渲染数据
顶点、三角面、UV数据赋值完成后,必须将Mesh重新赋值给MeshFilter组件,同时调用法线、包围盒重建接口,确保渲染数据同步更新。 - 适配追踪图变换属性
如果使用AR Foundation、ARKit、ARCore的图像追踪组件,可读取追踪图像的实际物理尺寸、姿态,对齐平面对象的旋转和缩放,避免投影大小、角度偏差。
可直接运行的参考代码
using UnityEngine; public class ARProjectionPlane : MonoBehaviour { // 在Inspector拖入4个对应追踪图像位置的空物体 public GameObject[] trackPointObjs; // 拖入要投影的图片材质 public Material projectionMaterial; void Start() { BuildProjectionPlane(); } void BuildProjectionPlane() { // 新建独立Mesh实例,不要修改Unity内置共享Plane Mesh Mesh projMesh = new Mesh(); Vector3[] trackWorldPos = new Vector3[4]; // 采集4个追踪点的世界坐标 for (int i = 0; i < trackPointObjs.Length; i++) { trackWorldPos[i] = trackPointObjs[i].transform.position; } // 创建平面承载对象,初始位置设为4个点的中心 GameObject planeHost = new GameObject("ARProjectionImg"); planeHost.transform.position = (trackWorldPos[0] + trackWorldPos[1] + trackWorldPos[2] + trackWorldPos[3]) / 4f; // 世界坐标转平面本地坐标,写入顶点数组 Vector3[] vertices = new Vector3[4]; for (int i = 0; i < 4; i++) { vertices[i] = planeHost.transform.InverseTransformPoint(trackWorldPos[i]); } // 配置三角面索引,顺时针绕序适配Unity正面剔除规则 int[] triangles = new int[] { 0, 1, 2, 0, 2, 3 }; // 配置UV,让投影图片完整拉伸适配四边形 Vector2[] uvs = new Vector2[4] { new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1), new Vector2(0, 1) }; // 写入所有Mesh数据 projMesh.vertices = vertices; projMesh.triangles = triangles; projMesh.uv = uvs; projMesh.RecalculateNormals(); projMesh.RecalculateBounds(); // 挂载组件渲染 MeshFilter mf = planeHost.AddComponent<MeshFilter>(); mf.mesh = projMesh; MeshRenderer mr = planeHost.AddComponent<MeshRenderer>(); mr.material = projectionMaterial; } }
排错提示
- 如果平面显示为透明,将三角面数组替换为
new int[] {0,2,1, 0,3,2}即可翻转渲染正面。 - 如果投影图片拉伸比例不对,可根据4个追踪点的实际距离调整UV坐标,或参考AR追踪图像的物理尺寸参数做缩放校准。
- 运行时不要直接修改Project面板内的Mesh资源,必须新建Mesh实例,否则会导致所有引用该资源的对象显示异常。
内容的提问来源于stack exchange,提问作者gentle_johnny
相关产品推荐
相关产品推荐

