在 Unity 中创建二维圆形网格
Creating a 2D Circular Mesh in Unity
我目前有一个 "CreateMesh" 脚本,它可以作为一个对象的一个组件,带有网格渲染器和网格过滤器,并且二维网格是用多边形碰撞器创建的给定 "MeshType" 变量的网格设置为 "tri" 或 "box"(分别用于三角形和矩形网格。)我还想添加创建圆形网格的功能,但是根据一些研究我意识到这并不像我最初想的那么简单。但是我还没有找到任何有用的东西。
这是我的长方体和三角形网格的代码:
public float width = 5f;
public float height = 5f;
public string meshType;
public PolygonCollider2D polyCollider;
void Start()
{
polyCollider = GetComponent<PolygonCollider2D>();
}
// Update is called once per frame
void Update () {
if (meshType == "tri")
{
TriangleMesh(width, height);
}
if (meshType == "box")
{
BoxMesh(width, height);
}
}
void TriangleMesh(float width, float height)
{
MeshFilter mf = GetComponent<MeshFilter>();
Mesh mesh = new Mesh();
mf.mesh = mesh;
//Verticies
Vector3[] verticies = new Vector3[3]
{
new Vector3(0,0,0), new Vector3(width, 0, 0), new Vector3(0, height, 0)
};
//Triangles
int[] tri = new int[3];
tri[0] = 0;
tri[1] = 2;
tri[2] = 1;
//normals
Vector3[] normals = new Vector3[3];
normals[0] = -Vector3.forward;
normals[1] = -Vector3.forward;
normals[2] = -Vector3.forward;
//UVs
Vector2[] uv = new Vector2[3];
uv[0] = new Vector2(0, 0);
uv[0] = new Vector2(1, 0);
uv[0] = new Vector2(0, 1);
//initialise
mesh.vertices = verticies;
mesh.triangles = tri;
mesh.normals = normals;
mesh.uv = uv;
//setting up collider
polyCollider.pathCount = 1;
Vector2[] path = new Vector2[3]
{
new Vector2(0,0), new Vector2(0, height), new Vector2(width, 0)
};
polyCollider.SetPath(0, path);
}
void BoxMesh(float width, float height)
{
MeshFilter mf = GetComponent<MeshFilter>();
Mesh mesh = new Mesh();
mf.mesh = mesh;
//Verticies
Vector3[] verticies = new Vector3[4]
{
new Vector3(0,0,0), new Vector3(0, height, 0), new Vector3(width, height, 0), new Vector3(width, 0, 0)
};
//Triangles
int[] tri = new int[6];
tri[0] = 0;
tri[1] = 1;
tri[2] = 3;
tri[3] = 1;
tri[4] = 2;
tri[5] = 3;
//normals
Vector3[] normals = new Vector3[4];
normals[0] = -Vector3.forward;
normals[1] = -Vector3.forward;
normals[2] = -Vector3.forward;
normals[3] = -Vector3.forward;
//UVs
Vector2[] uv = new Vector2[4];
uv[0] = new Vector2(0, 0);
uv[1] = new Vector2(0, 1);
uv[2] = new Vector2(1, 1);
uv[3] = new Vector2(1, 0);
//initialise
mesh.vertices = verticies;
mesh.triangles = tri;
mesh.normals = normals;
mesh.uv = uv;
//setting up collider
polyCollider.pathCount = 1;
Vector2[] path = new Vector2[4]
{
new Vector2(0,0), new Vector2(0, height), new Vector2(width, height), new Vector2(width, 0)
};
polyCollider.SetPath(0, path);
}
所以基本上我想要一个可以在更新方法中调用的函数,它只会创建一个圆形网格。例如:
void Update () {
if (meshType == "tri")
{
TriangleMesh(width, height);
}
if (meshType == "box")
{
BoxMesh(width, height);
}
if (meshType == "circle")
{
CircleMesh(radius);
}
}
我设法找到的解决方案是创建一个 n 边大且 n 值大的正多边形。我有一个名为 PolyMesh 的函数,它创建一个具有 n 边和给定半径的正多边形网格。
生成顶点
对于 n 边的正多边形的每个顶点,相对于多边形中心的坐标由 x = r*i*sin(θ)
和 y = r*i*cos(θ)
给出,因此 x = r*i*sin(2π/2)
和 y = r*i*cos(2π/2)
.其中 i 从 0 迭代到 n-1。因此,我们可以有一个列表,其中分配有顶点,然后转换为数组:
//verticies
List<Vector3> verticiesList = new List<Vector3> { };
float x;
float y;
for (int i = 0; i < n; i ++)
{
x = radius * Mathf.Sin((2 * Mathf.PI * i) / n);
y = radius * Mathf.Cos((2 * Mathf.PI * i) / n);
verticiesList.Add(new Vector3(x, y, 0f));
}
Vector3[] verticies = verticiesList.ToArray();
生成三角形
一个给定的有n条边的正多边形可以从同一个点分成n-2个三角形。所以我们可以生成每个三角形如下:
//triangles
List<int> trianglesList = new List<int> { };
for(int i = 0; i < (n-2); i++)
{
trianglesList.Add(0);
trianglesList.Add(i+1);
trianglesList.Add(i+2);
}
int[] triangles = trianglesList.ToArray();
生成法线
因为这是一个 2d 对象,我们可以将每个法线都设为 -Vector3.forward
,如下所示:
//normals
List<Vector3> normalsList = new List<Vector3> { };
for (int i = 0; i < verticies.Length; i++)
{
normalsList.Add(-Vector3.forward);
}
Vector3[] normals = normalsList.ToArray();
生成对撞机
我们可以只使用具有相同半径的圆形碰撞器,但为了使此函数适用于 n 值较小的多边形,我们必须使用 PolygonCollider2D
。由于顶点数组中的顶点已经按顺序排列,我们可以简单地将它们用作 PolygonCollider2D
.
的路径
//polyCollider
polyCollider.pathCount = 1;
List<Vector2> pathList = new List<Vector2> { };
for (int i = 0; i < n; i++)
{
pathList.Add(new Vector2(verticies[i].x, verticies[i].y));
}
Vector2[] path = pathList.ToArray();
polyCollider.SetPath(0, path);
完整的代码应该是这样的:
public PolygonCollider2D polyCollider;
void Start()
{
polyCollider = GetComponent<PolygonCollider2D>();
}
void PolyMesh(float radius, int n)
{
MeshFilter mf = GetComponent<MeshFilter>();
Mesh mesh = new Mesh();
mf.mesh = mesh;
//verticies
List<Vector3> verticiesList = new List<Vector3> { };
float x;
float y;
for (int i = 0; i < n; i ++)
{
x = radius * Mathf.Sin((2 * Mathf.PI * i) / n);
y = radius * Mathf.Cos((2 * Mathf.PI * i) / n);
verticiesList.Add(new Vector3(x, y, 0f));
}
Vector3[] verticies = verticiesList.ToArray();
//triangles
List<int> trianglesList = new List<int> { };
for(int i = 0; i < (n-2); i++)
{
trianglesList.Add(0);
trianglesList.Add(i+1);
trianglesList.Add(i+2);
}
int[] triangles = trianglesList.ToArray();
//normals
List<Vector3> normalsList = new List<Vector3> { };
for (int i = 0; i < verticies.Length; i++)
{
normalsList.Add(-Vector3.forward);
}
Vector3[] normals = normalsList.ToArray();
//initialise
mesh.vertices = verticies;
mesh.triangles = triangles;
mesh.normals = normals;
//polyCollider
polyCollider.pathCount = 1;
List<Vector2> pathList = new List<Vector2> { };
for (int i = 0; i < n; i++)
{
pathList.Add(new Vector2(verticies[i].x, verticies[i].y));
}
Vector2[] path = pathList.ToArray();
polyCollider.SetPath(0, path);
}
我的声望不到 50,所以我不能只评论@Tom Ryan 的回答。
尽管如此,请注意他的解决方案不包括网格的 UV。这是加法:
//uvs
Vector2[] uvs = new Vector2[vertices.Length];
for (int i = 0; i < uvs.Length; i++)
{
uvs[i] = new Vector2(vertices[i].x / (radius*2) + 0.5f, vertices[i].y / (radius*2) + 0.5f);
}
// Later...
mesh.uv = uvs;
我目前有一个 "CreateMesh" 脚本,它可以作为一个对象的一个组件,带有网格渲染器和网格过滤器,并且二维网格是用多边形碰撞器创建的给定 "MeshType" 变量的网格设置为 "tri" 或 "box"(分别用于三角形和矩形网格。)我还想添加创建圆形网格的功能,但是根据一些研究我意识到这并不像我最初想的那么简单。但是我还没有找到任何有用的东西。
这是我的长方体和三角形网格的代码:
public float width = 5f;
public float height = 5f;
public string meshType;
public PolygonCollider2D polyCollider;
void Start()
{
polyCollider = GetComponent<PolygonCollider2D>();
}
// Update is called once per frame
void Update () {
if (meshType == "tri")
{
TriangleMesh(width, height);
}
if (meshType == "box")
{
BoxMesh(width, height);
}
}
void TriangleMesh(float width, float height)
{
MeshFilter mf = GetComponent<MeshFilter>();
Mesh mesh = new Mesh();
mf.mesh = mesh;
//Verticies
Vector3[] verticies = new Vector3[3]
{
new Vector3(0,0,0), new Vector3(width, 0, 0), new Vector3(0, height, 0)
};
//Triangles
int[] tri = new int[3];
tri[0] = 0;
tri[1] = 2;
tri[2] = 1;
//normals
Vector3[] normals = new Vector3[3];
normals[0] = -Vector3.forward;
normals[1] = -Vector3.forward;
normals[2] = -Vector3.forward;
//UVs
Vector2[] uv = new Vector2[3];
uv[0] = new Vector2(0, 0);
uv[0] = new Vector2(1, 0);
uv[0] = new Vector2(0, 1);
//initialise
mesh.vertices = verticies;
mesh.triangles = tri;
mesh.normals = normals;
mesh.uv = uv;
//setting up collider
polyCollider.pathCount = 1;
Vector2[] path = new Vector2[3]
{
new Vector2(0,0), new Vector2(0, height), new Vector2(width, 0)
};
polyCollider.SetPath(0, path);
}
void BoxMesh(float width, float height)
{
MeshFilter mf = GetComponent<MeshFilter>();
Mesh mesh = new Mesh();
mf.mesh = mesh;
//Verticies
Vector3[] verticies = new Vector3[4]
{
new Vector3(0,0,0), new Vector3(0, height, 0), new Vector3(width, height, 0), new Vector3(width, 0, 0)
};
//Triangles
int[] tri = new int[6];
tri[0] = 0;
tri[1] = 1;
tri[2] = 3;
tri[3] = 1;
tri[4] = 2;
tri[5] = 3;
//normals
Vector3[] normals = new Vector3[4];
normals[0] = -Vector3.forward;
normals[1] = -Vector3.forward;
normals[2] = -Vector3.forward;
normals[3] = -Vector3.forward;
//UVs
Vector2[] uv = new Vector2[4];
uv[0] = new Vector2(0, 0);
uv[1] = new Vector2(0, 1);
uv[2] = new Vector2(1, 1);
uv[3] = new Vector2(1, 0);
//initialise
mesh.vertices = verticies;
mesh.triangles = tri;
mesh.normals = normals;
mesh.uv = uv;
//setting up collider
polyCollider.pathCount = 1;
Vector2[] path = new Vector2[4]
{
new Vector2(0,0), new Vector2(0, height), new Vector2(width, height), new Vector2(width, 0)
};
polyCollider.SetPath(0, path);
}
所以基本上我想要一个可以在更新方法中调用的函数,它只会创建一个圆形网格。例如:
void Update () {
if (meshType == "tri")
{
TriangleMesh(width, height);
}
if (meshType == "box")
{
BoxMesh(width, height);
}
if (meshType == "circle")
{
CircleMesh(radius);
}
}
我设法找到的解决方案是创建一个 n 边大且 n 值大的正多边形。我有一个名为 PolyMesh 的函数,它创建一个具有 n 边和给定半径的正多边形网格。
生成顶点
对于 n 边的正多边形的每个顶点,相对于多边形中心的坐标由 x = r*i*sin(θ)
和 y = r*i*cos(θ)
给出,因此 x = r*i*sin(2π/2)
和 y = r*i*cos(2π/2)
.其中 i 从 0 迭代到 n-1。因此,我们可以有一个列表,其中分配有顶点,然后转换为数组:
//verticies
List<Vector3> verticiesList = new List<Vector3> { };
float x;
float y;
for (int i = 0; i < n; i ++)
{
x = radius * Mathf.Sin((2 * Mathf.PI * i) / n);
y = radius * Mathf.Cos((2 * Mathf.PI * i) / n);
verticiesList.Add(new Vector3(x, y, 0f));
}
Vector3[] verticies = verticiesList.ToArray();
生成三角形
一个给定的有n条边的正多边形可以从同一个点分成n-2个三角形。所以我们可以生成每个三角形如下:
//triangles
List<int> trianglesList = new List<int> { };
for(int i = 0; i < (n-2); i++)
{
trianglesList.Add(0);
trianglesList.Add(i+1);
trianglesList.Add(i+2);
}
int[] triangles = trianglesList.ToArray();
生成法线
因为这是一个 2d 对象,我们可以将每个法线都设为 -Vector3.forward
,如下所示:
//normals
List<Vector3> normalsList = new List<Vector3> { };
for (int i = 0; i < verticies.Length; i++)
{
normalsList.Add(-Vector3.forward);
}
Vector3[] normals = normalsList.ToArray();
生成对撞机
我们可以只使用具有相同半径的圆形碰撞器,但为了使此函数适用于 n 值较小的多边形,我们必须使用 PolygonCollider2D
。由于顶点数组中的顶点已经按顺序排列,我们可以简单地将它们用作 PolygonCollider2D
.
//polyCollider
polyCollider.pathCount = 1;
List<Vector2> pathList = new List<Vector2> { };
for (int i = 0; i < n; i++)
{
pathList.Add(new Vector2(verticies[i].x, verticies[i].y));
}
Vector2[] path = pathList.ToArray();
polyCollider.SetPath(0, path);
完整的代码应该是这样的:
public PolygonCollider2D polyCollider;
void Start()
{
polyCollider = GetComponent<PolygonCollider2D>();
}
void PolyMesh(float radius, int n)
{
MeshFilter mf = GetComponent<MeshFilter>();
Mesh mesh = new Mesh();
mf.mesh = mesh;
//verticies
List<Vector3> verticiesList = new List<Vector3> { };
float x;
float y;
for (int i = 0; i < n; i ++)
{
x = radius * Mathf.Sin((2 * Mathf.PI * i) / n);
y = radius * Mathf.Cos((2 * Mathf.PI * i) / n);
verticiesList.Add(new Vector3(x, y, 0f));
}
Vector3[] verticies = verticiesList.ToArray();
//triangles
List<int> trianglesList = new List<int> { };
for(int i = 0; i < (n-2); i++)
{
trianglesList.Add(0);
trianglesList.Add(i+1);
trianglesList.Add(i+2);
}
int[] triangles = trianglesList.ToArray();
//normals
List<Vector3> normalsList = new List<Vector3> { };
for (int i = 0; i < verticies.Length; i++)
{
normalsList.Add(-Vector3.forward);
}
Vector3[] normals = normalsList.ToArray();
//initialise
mesh.vertices = verticies;
mesh.triangles = triangles;
mesh.normals = normals;
//polyCollider
polyCollider.pathCount = 1;
List<Vector2> pathList = new List<Vector2> { };
for (int i = 0; i < n; i++)
{
pathList.Add(new Vector2(verticies[i].x, verticies[i].y));
}
Vector2[] path = pathList.ToArray();
polyCollider.SetPath(0, path);
}
我的声望不到 50,所以我不能只评论@Tom Ryan 的回答。
尽管如此,请注意他的解决方案不包括网格的 UV。这是加法:
//uvs
Vector2[] uvs = new Vector2[vertices.Length];
for (int i = 0; i < uvs.Length; i++)
{
uvs[i] = new Vector2(vertices[i].x / (radius*2) + 0.5f, vertices[i].y / (radius*2) + 0.5f);
}
// Later...
mesh.uv = uvs;