目录
1.主要思路
上下两面圆环,内外是展开的两个矩形面,通过Mesh依次绘制图形。
2.代码展示
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 水管
/// </summary>
[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshRenderer))]
public class DrawConduit : MonoBehaviour
{
[SerializeField]
Texture2D texture;
void Start()
{
DrawCustomConduit(2,1,8,30);
GetComponent<MeshRenderer>().material.mainTexture = texture;
}
/// <summary>
/// 绘制自定义空心柱体(水管)
/// </summary>
/// <param name="r1">外半径</param>
/// <param name="r2">内半径</param>
/// <param name="height">高度</param>
/// <param name="num">分割数 棱数</param>
private void DrawCustomConduit(float r1,float r2,float height,int n)
{
Mesh mesh = GetComponent<MeshFilter>().mesh;
List<Vector3> verties = new List<Vector3>();
List<Vector2> uvlists = new List<Vector2>();
//角度
float angle = (2 * Mathf.PI) / n;
//外部顶点
List<Vector3> outcircleVs = new List<Vector3>();
//内部顶点
List<Vector3> incircleVs = new List<Vector3>();
//上方圆环
for (int i = 0; i < n + 1; i++)
{
//外圆
float x = Mathf.Sin(angle * i) * r1;
float y = Mathf.Cos(angle * i) * r1;
float uvx = i / (float)n;
verties.Add(new Vector3(x, (height / 2), y));
//存储外圆上点
outcircleVs.Add(new Vector3(x, (height / 2), y));
uvlists.Add(new Vector2(uvx, 1));
//内圆
float intx = Mathf.Sin(angle * i) * r2;
float inty = Mathf.Cos(angle * i) * r2;
verties.Add(new Vector3(intx, (height / 2), inty));
//存储内圆上点
incircleVs.Add(new Vector3(intx, (height / 2), inty));
uvlists.Add(new Vector2(uvx, 0));
}
//下方圆环
for (int i = 0; i < n + 1; i++)
{
float x = Mathf.Sin(angle * i) * r1;
float y = Mathf.Cos(angle * i) * r1;
verties.Add(new Vector3(x, -(height / 2), y));
outcircleVs.Add(new Vector3(x, -(height / 2), y));
float uvx = i / (float)n;
uvlists.Add(new Vector2(uvx, 1));
//内圆
float intx = Mathf.Sin(angle * i) * r2;
float inty = Mathf.Cos(angle * i) * r2;
verties.Add(new Vector3(intx, -(height / 2), inty));
incircleVs.Add(new Vector3(intx, -(height / 2), inty));
uvlists.Add(new Vector2(uvx, 0));
}
//上下两个外圈的点 为后面画外部矩形做准备
for (int i = 0; i < outcircleVs.Count; i++)
{
verties.Add(outcircleVs[i]);
float uvx = i / (float)(outcircleVs.Count / 2);
if (i <= (outcircleVs.Count / 2))
{
uvlists.Add(new Vector2(uvx, 1));
}
else
{
uvlists.Add(new Vector2(uvx - 1, 0));
}
}
//上下两个内圈的点 为后面画内部矩形做准备
for (int i = 0; i < incircleVs.Count; i++)
{
verties.Add(incircleVs[i]);
float uvx = i / (float)(incircleVs.Count / 2);
if (i <= (incircleVs.Count / 2))
{
uvlists.Add(new Vector2(uvx, 1));
}
else
{
uvlists.Add(new Vector2(uvx - 1, 0));
}
}
mesh.vertices = verties.ToArray();
mesh.uv = uvlists.ToArray();
//print("verties" + verties.Count);
//print("uvlists" + uvlists.Count);
List<int> indices = new List<int>();
//通过连接上部圆环
for (int i = 0; i < n + 1; i++)
{
if (i < n)
{
indices.Add(2 * i);
indices.Add(2 * (i + 1));
indices.Add(2 * (i + 1) + 1);
indices.Add(2 * i);
indices.Add(2 * (i + 1) + 1);
indices.Add(2 * i + 1);
}
}
//连接下部圆环
for (int i = 0; i < n + 1; i++)
{
if (i < n)
{
indices.Add(2 * i + 2 * (n + 1));
indices.Add(2 * (i + 1) + 1 + 2 * (n + 1));
indices.Add(2 * (i + 1) + 2 * (n + 1));
indices.Add(2 * i + 2 * (n + 1));
indices.Add(2 * i + 1 + 2 * (n + 1));
indices.Add(2 * (i + 1) + 1 + 2 * (n + 1));
}
}
//连接外部矩形
for (int i = 0; i < n + 1; i++)
{
indices.Add(i + 4 * (n + 1));
indices.Add(i + 5 * (n + 1));
indices.Add(i + 4 * (n + 1) + 1);
indices.Add(i + 4 * (n + 1) + 1);
indices.Add(i + 5 * (n + 1));
indices.Add(i + 5 * (n + 1) + 1);
//0 3 1 1 3 4
}
//连接内部矩形
for (int i = 0; i < n; i++)
{
indices.Add(i + 6 * (n + 1));
indices.Add(i + 6 * (n + 1) + 1);
indices.Add(i + 7 * (n + 1));
indices.Add(i + 6 * (n + 1) + 1);
indices.Add(i + 7 * (n + 1) + 1);
indices.Add(i + 7 * (n + 1));
}
//下标路径点赋给mesh
mesh.triangles = indices.ToArray();
Material mat = new Material(Shader.Find("Standard"));
GetComponent<MeshRenderer>().material = mat;
mesh.RecalculateNormals();
}
}
可通过uv坐标贴图,给Textrue附上不同的纹理材质。修改DrawCustomConduit()方法里面的参数可以设置不同的需求效果。