目录

  • 1 逻辑梳理
    • 1.1 生成圆柱体网格
    • 1.2 一个简单的Shader
    • 1.3 相机操控
  • 2 源码

我们知道3D Max中可以很方便的创建出一个圆柱体,那么在Unity中能否用代码创建出一个圆柱体呢,当然可以的,在Unity里面想怎么玩都行的。我们今天来看看在Unity中用代码创建一个圆柱体。
废话少说,先看效果。

1 逻辑梳理

用代码创建圆柱体逻辑其实很简单,关键点就两个:
1.生成圆柱体的网格
2.将网格用合适的Shader渲染出来

1.1 生成圆柱体网格

unity中要渲染一个物体,需要先添加两个组件,一是MeshFilter,二是MeshRenderer。

MeshFilter 网格过滤器
其唯一的作用就是用来指定Mesh。
它有两个属性mesh,sharedMesh;可以把mesh理解为值传递,修改网格只会影响到这一个物体;而shardeMesh是引用传递,修改网格会应用到所有使用这个网格的物体,并且会持久化。

MeshRenderer 网格渲染器

MeshRender 负责渲染 MeshFilter 指定的 Mesh,在 Transform 的位置渲染这个Mesh。
MeshRender参数主要指定是否产生和接受阴影,以及使用的Meterial。

当然光有这两个组件还不行,我们还得生成网格,并将网格幅值给MeshFilter组件。
unity中创建一个网格的步骤如下(这里直接以圆柱体网格为例了):
①先new一个Mesh

Mesh mesh = new UnityEngine.Mesh();

有个问题,我们能不能只使用一个Mesh,然后用不同的材质去渲染Mesh的不同部位呢,就像上面Demo中的网格线和圆柱体表面?当然可以的。
一个Mesh只有一份顶点,但是可以有多个submesh,通过Mesh的subMeshCount属性指定。每个submesh有自己的material,各个submesh的材质通过Mesh的materials(材质数组来确定)。代码类似如下。

mesh.subMeshCount = 2;      // 这里指定2个submesh
meshRenderer.materials = new Material[]{mat1, // 材质球1mat2, // 材质球2
};

②计算出Mesh的所有顶点坐标,并指定给Mesh
Mesh的顶点坐标就是模型坐标,是相对于物体的位置的。
Demo中圆柱体的顶点只计算了下底面和上底面圆周的顶点,上底面、下底面各20个顶点。

List<Vector3> vertices = new List<Vector3>();
// 计算圆柱体上下底面顶点(上下各20个)
const int cnt = 20;
float deltaRad = Mathf.PI * 2 / cnt;
for (int i = 0; i < cnt; i++)
{float rad = i * deltaRad;float x = radius * Mathf.Sin(rad);float z = radius * Mathf.Cos(rad);vertices.Add(new Vector3(x, 0, z));                 // 下底面顶点vertices.Add(new Vector3(x, height, z));            // 上底面顶点
}
// 将顶点指定给网格
mesh.SetVertices(vertices);

指定Mesh的顶点索引数组,及MeshTopology(网格的拓扑结构,不知道这样翻译对不对)

计算出网格所有顶点后,这些顶点该如何使用?是组成三角面还是组成连接成线?如果组合成三角面,那么哪几个顶点组合呢?这就需要我们设定顶点索引数组和MeshTopology。顶点索引数组是和MeshTopology对应的,MeshTopology变了,顶点索引数组也要跟着调整。

Unity中MeshTopology有五种。

  public enum MeshTopology{// 三角面Triangles = 0,// 四边形Quads = 2,// 线段Lines = 3,// 线带LineStrip = 4,// 点Points = 5,}

比如说我们打算将MeshTopology设置为三角面,那么我们的顶点索引数组长度应该就是3的倍数(因为一个面要3个顶点嘛)。顶点索引数组中,第0、1、2组成第一个三角面,第3、4、5组成第二个三角面,以此类推。
但是要注意顶点的排列顺序,默认情况下,Unity中的所有Shader都是单面的,它都把反面的渲染给关闭掉了(Cull On)。所以顶点索引顺序不对,Shader中又没有Cull Off的话,我们可能就看不见那个面(因为是反面,被剔除啦)。
那怎样的顶点索引顺序才是正面呢?
很简单,三角面的法线方向和我们的视线方向相反,那么我们看到的这个面就是正面,反之为反面。
那么如何判断三角面的法线方向呢?
也很简单,假设我们的顶点索引排列顺序是ABC。
由于Unity局部坐标使用的是左手坐标系,那么举起你的左手,大拇指竖着,食指和小指并拢,由A朝向B弯曲,大拇指的方向就是这个面的法线方向,所以下图中ABC的的法线是朝屏幕外的。而我们是看向屏幕的,即我们的视线方向与面的法线方向相反,所以ABC这个面为正面。

核心方法就是Mesh的SetIndices。

// 最后的0是subMesh的索引值,从0开始
mesh.SetIndices(indexList.ToArray(), MeshTopology.Triangles, 0);

Demo中绘制侧面的方法。

// 侧面
List<int> indexList = new List<int>();
for (int i = 0; i < cnt; i++)
{if (i == cnt - 1){// 最后一个点和第一个点连接起来indexList.Add(2 * i);indexList.Add(2 * i + 1);indexList.Add(0);indexList.Add(0);indexList.Add(2 * i + 1);indexList.Add(1);}else{// 要注意顶点的排列顺序,如果shader没有Cull Off,这个面可能不可见indexList.Add(2 * i);indexList.Add(2 * i + 1);indexList.Add(2 * (i + 1));indexList.Add(2 * (i + 1));indexList.Add(2 * i + 1);indexList.Add(2 * i + 3);}
}
mesh.SetIndices(indexList.ToArray(), MeshTopology.Triangles, 0);

MeshTopology中的Lines和LineStrap都可以用来画线,但是顶点索引数组有点不同。
假设顶点索引数组为[0, 1, 2, 3, 4,5]。
那么MeshTopology为Lines时,0-1、2-3、4-5将分别组成一条线段,共3条线段。
而MeshTopology为LineStrap时,0-1、1-2、2-3、3-4、4-5将分别组成一条线段,共5条线段。

Demo中使用Lines模式来画网格线。

// 网格线
List<int> gridIndexList = new List<int>();
for (int i = 0; i < cnt; i++)
{if (i == cnt - 1){gridIndexList.Add(2 * i);gridIndexList.Add(0);gridIndexList.Add(2 * i + 1);gridIndexList.Add(1);gridIndexList.Add(2 * i);gridIndexList.Add(2 * i + 1);gridIndexList.Add(2 * i + 1);gridIndexList.Add(0);}else{gridIndexList.Add(2 * i);gridIndexList.Add(2 * (i + 1));gridIndexList.Add(2 * i + 1);gridIndexList.Add(2 * i + 3);gridIndexList.Add(2 * i);gridIndexList.Add(2 * i + 1);gridIndexList.Add(2 * i + 1);gridIndexList.Add(2 * (i + 1));}
}
// 这里subMesh为1了
mesh.SetIndices(gridIndexList.ToArray(), MeshTopology.Lines, 1);

指定Mesh的法线和uv坐标
如果网格需要贴上贴图和光照则需要设置Mesh的法线和uv坐标,每个顶点都需要设置。

// 法线
mesh.normals
// 贴图
mesh.uv

法线也可通过mesh.RecalculateNormals()自动计算出来,但MeshTopology为Lines或Points会报错。
由于Demo中不需要给圆柱体计算光照和贴上贴图,所以Demo中没设置它们。

1.2 一个简单的Shader

由于Shader是透明的,所以关闭深度写入ZWrite Off。由于要两面都要可见,所以关闭剔除Cull Off

Shader "Custom/Cylinder"
{Properties{_MainColor ("Main Color", Color) = (1, 1, 1, 0.5)}SubShader{Tags { "Queue" = "Transparent" "RenderType" = "Transparent" }LOD 100Pass{ZWrite OffCull OffBlend SrcAlpha OneMinusSrcAlphaCGPROGRAM#pragma vertex vert#pragma fragment frag#include "Lighting.cginc"#include "UnityCG.cginc"struct appdata{float4 vertex : POSITION;};struct v2f{float4 vertex : SV_POSITION;};fixed4 _MainColor;v2f vert (appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);return o;}fixed4 frag (v2f i) : SV_Target{return _MainColor;}ENDCG}}
}

1.3 相机操控

Demo中我们可以360拖动、放大缩小、旋转查看物体。
之前已经实现过了,具体见这篇文章《Unity3D相机操控(完整模拟Scene视图操作)》。

2 源码


项目放到这儿了。
链接:https://pan.baidu.com/s/1DgHNuG-nBPSrE5bh4f03kA
提取码:6yg8

博主个人博客本文链接。

Unity3D C#数学系列之创建圆柱体相关推荐

  1. Unity3D C#数学系列之矩阵基础

    目录 1 引言 2 矩阵的作用 3 矩阵的乘法 3.1 矩阵与标量的乘法 3.2 矩阵与矩阵的乘法 4 特殊矩阵 4.1 方块矩阵 4.1.1 对角矩阵 4.1.2 单位矩阵 4.2 转置矩阵 4.3 ...

  2. Unity3D C#数学系列之判断两条线段是否相交并求交点

    1 引言 问题:已知三维空间中四点A.B.C.D,如何判断线段AB与CD是否相交,若相交则求出交点. 分析: AB.CD要相交,则AB.CD必须要在同一平面内 快速排斥和跨立实验判断是否相交 几何法分 ...

  3. Unity3D C#数学系列之三角函数

    目录 1 定义 2 常用公式推导 2.1 sin²θ + cos² = 1 2.2 sinθ = cos(90°-θ). cosθ = sin(90°-θ) 2.3 sin(-θ) = -sinθ. ...

  4. Unity3D C#数学系列之点积

    文章目录 1 定义 2 几何意义 3 向量a·向量b = xaxb+yayb+zazb 4 应用案例 4.1 求两向量的夹角 4.2 判断两向量是否垂直 4.3 判断NPC是否在攻击范围内 4.4 已 ...

  5. Unity3D开发之代码创建圆柱体

    看到这篇文章你可能好奇unity自带圆柱体组件,直接就可以生成,为什么我们还要用代码生成.其实是最近领导对项目有一个要求,就是我们要在自写编辑器内操作圆管,也就是圆柱体.功能类似3DMax里的拉伸管线 ...

  6. Unity3D脚本中文系列教程(七)

    http://dong2008hong.blog.163.com/blog/static/4696882720140311445677/?suggestedreading&wumii Unit ...

  7. Unity3D脚本中文系列教程(五)

    http://dong2008hong.blog.163.com/blog/static/4696882720140302848544/?suggestedreading&wumii Unit ...

  8. 数学系列:数学在计算机图形学中的应用

    宇宙的琴弦 博客园 首页 新随笔 联系 订阅 管理 随笔 - 60   文章 - 0   评论 - 0 数学系列:数学在计算机图形学中的应用 Copyright © 1900-2016, NORYES ...

  9. [原创]windows server 2012 AD架构 试验 系列 – 3 创建备份DC2

    [原创]windows server 2012 AD架构 试验 系列 – 3 创建备份DC2 环境: DC2 ,192.168.20.101 ,DNS 指向根域 1 添加角色和功能 2提升域控 在提升 ...

  10. Unity3D的坑系列:动态加载dll

    Unity3D的坑系列:动态加载dll 我现在参与的项目是做MMO手游,目标平台是Android和iOS,iOS平台不能动态加载dll(什么原因找乔布斯去),可以直接忽略,而在Android平台是可以 ...

最新文章

  1. linux的上传工具,Linux下精简版上传工具lrzsz
  2. 收集了100+论文的最新综述来了!基于深度学习的图像深度重建
  3. Python中使用Flask、MongoDB搭建简易图片服务器
  4. 网络推广人员需要掌握的九大查询工具
  5. UI超实用通用图标素材模板
  6. 再品Resnet残差网络
  7. vmware虚拟机linux的扩容问题导致redhat无法启动!
  8. [Regular] 4、正则表达式的匹配原理原则
  9. oracle学习笔记 学习前奏
  10. gsp计算机管理系统,速拓医药GSP管理系统pc版
  11. 中原工学院信息商务学院计算机二级,中原工学院信息商务学院教务系统网址入口...
  12. PNP与NPN三极管开关特性
  13. 有向图和无向图转化为邻接表后链表中结点个数
  14. 教程丨键盘上的各按键的作用与常用办公快捷键大全
  15. mysql增加连接_mysql增加连接数
  16. vs2017c语言playsound,VS2010播放.WAW音频文件
  17. UITableView去掉Grouped样式的第一组Header组头
  18. 嵌入式Linux--U-Boot(四)MMC命令使用
  19. 大文件MD5计算 C语言 (从OpenSSL库中分离算法:三)
  20. HyperLynx仿真(一)LineSim简单介绍

热门文章

  1. android 动态库符号表,Android NDK隐藏jni动态库的内部符号表
  2. 金额中文大写c语言,C语言编程:数字金额转换为中文大写金额?
  3. HTTP无状态协议到底指的什么?
  4. win7黑屏怎么办?最后一批win7旗舰版珍藏版密钥。
  5. 我不曾忘记的初心-屌丝逆袭
  6. 项目管理PMP:项目绩效考核管理制度(全岗位流程图66页)
  7. 电子计算机分类 可以分为哪些,计算机按照工作原理进行分类可以分为
  8. VS2017的离线下载
  9. ora-20011 ora-01555
  10. 物质世界微观粒子运动规律——量子力学