【Unity3D】Unity3D开发《我的世界》之一、创建一个面
转载请注明出处:http://www.cnblogs.com/shamoyuu/p/unity_minecraft_01.html
最近总有人问及我的游戏里跟《我的世界》一样的地形是如何实现的,所以在这里开一个系列教程总结回答一下,也算是对自己的一个梳理和记录。
一、简单分析
对《我的世界》感兴趣,且有一定Unity3D基础的人,应该都或多或少的尝试过自己去做一个吧。
有些人是用Unity3D自带的cube,然后用三层for循环,把cube堆叠起来,但是会发现游戏几乎卡爆了,根本没办法运行。
如果看过我以前换装系统教程人应该都知道,这是因为每一个cube都是独立的物体,它们的每次渲染都要执行一次drawcall,每帧几千上万的drawcall,不卡爆就怪了。
既然这样,那我们把所有的cube合并成一个物体行不行?
也不行。
因为在地底90%的面都是看不到的,这些面实际上不应该存在,也都应该删掉,否则对CPU和GPU都是极大的负担。
基于以上的原因,直接用cube是肯定不行的,那就只能我们自己通过代码来生成面,而且只生成我们需要的面,这样就没有上面的问题了。《我的世界》也是这么做的。
二、理论基础(重点)
1、法线
法线就是垂直于面的一条线,它有方向,没有大小。
法线的方向就是面朝外的方向。比如我们现在盯着显示器看,从显示器的正中心会有一条法线垂直于屏幕指向我们。
法线向外的面就是正面,相反的就是背面,一般来讲,从正面看才能看到面,背面看面是看不到的。
2、三边面和四边面
三边面就是三条边组成的面,四边面就是四条边组成的面。
三边面在三维空间中是不可扭曲的,而四边面在三维空间中可以扭曲。所以Unity里只支持三边面。其他支持四边面的软件例如3dmax在导出fbx的时候,会把四边面转换成三边面。
3、左手坐标系和右手坐标系
我们的三维坐标系,在3dmax里是右手坐标系,而在Unity里是左手坐标系。
左手坐标系和右手坐标系的区别可以看一下这个博客 http://www.cnblogs.com/mythou/p/3327046.html

4、三边面如何组成四边面

先看看上面这张非常传神的图,左边是Unity里的左手坐标系,右边是我们想在这个坐标系里生成的一个面以及它的各个点坐标。
012和230这两个三边面就组成了一个四边面。
如果我问,这个四边面有几个顶点,想必大家都会回答4个,实际上是6个,012和230这是6个顶点,不同面的顶点不公用。
要组成2个三边面可以有很多种顺序,例如012和320、012和032、023和012等等等
但是我们一般都是按照4个点的顺序来画2个三边面组成四边面,所以可选的只有【012和230、230和012】,以及【032和210、210和032】这两大类
这两类画法有什么区别呢?细心的童鞋应该已经发现,这两种方式前者是逆时针,后者是顺时针。
这种循环的方向会导致面的法线方向不同,而这个法线方向会决定这个面的朝向。
我们要确定这个法线方向其实很简单,上面说了,Unity里是左手坐标系,我们拿出左手,伸直,拇指与其他四个指头垂直,然后四指弯曲,指尖朝向循环的方向,拇指就指向法线的方向。
有没有觉得很熟悉?这和初中学过的左手螺旋定则一模一样。

由此我们得出结论,要想生成正确的面(法线指向我们),我们只能用【032和210、210和032】
这里需要注意的一点是,我们确定4个点的循环方向,和生成三边面时的循环方向无关,只要生成三边面时,用到的前4个点的index顺序没错就行了。
三、代码实现
该有的理论知识都有了,下面我们就手动生成一个面试试看
using System.Collections;
using System.Collections.Generic;
using UnityEngine; public class Chunk : MonoBehaviour
{
private Mesh mesh; //面需要的点
private List<Vector3> vertices = new List<Vector3>();
//生成三边面时用到的vertices的index
private List<int> triangles = new List<int>(); void Start()
{
mesh = new Mesh(); AddFrontFace(); //为点和index赋值
mesh.vertices = vertices.ToArray();
mesh.triangles = triangles.ToArray(); //重新计算顶点和法线
mesh.RecalculateBounds();
mesh.RecalculateNormals(); //将生成好的面赋值给组件
GetComponent<MeshFilter>().mesh = mesh;
} void AddFrontFace()
{
//添加4个点
vertices.Add(new Vector3(, , ));
vertices.Add(new Vector3(, , ));
vertices.Add(new Vector3(, , ));
vertices.Add(new Vector3(, , )); //第一个三角面
triangles.Add();
triangles.Add();
triangles.Add(); //第二个三角面
triangles.Add();
triangles.Add();
triangles.Add();
}
}
然后建一个空物体,把这个脚本拖上去,再添加MeshFilter和MeshRenderer组件,然后随便给一个Material,运行

【Unity3D】Unity3D开发《我的世界》之一、创建一个面的更多相关文章
- unity3d游戏开发学习之使用3dmax创建导弹模型
在着手研究Unity3D的游戏开发时,3D模型能够考虑从unity的assets store去获取,也能够从网上搜索下载,同一时候咱们也能够尝试下自己动手去做一些简单的模型. 这里就依据unity3d ...
- C#程序员的春天之从零开始学习unity3D游戏开发入门教程二(创建项目及基本面板介绍)
一项目创建: 创建项目是开发的第一步. 运行untiy之后如果是第一次运行会弹出 我们这里随便创建一个项目. 二Untiy面板介绍: 三代码编辑器的切换: 这里我安装了vs2012. 到这里开发环境基 ...
- Unity3D游戏开发从零单排(四) - 制作一个iOS游戏
提要 此篇是一个国外教程的翻译,尽管有点老,可是适合新手入门. 自己去写代码.debug,布置场景,能够收获到非常多.游戏邦上已经有前面两部分的译文,这里翻译的是游戏的最后一个部分. 欢迎回来 在第一 ...
- three.js-走进3d的奇妙世界一创建一个三维场景
一.git代码仓库地址 git clone https://github.com/josdirksen/learning-threejs-third 下载并解压 二.创建一个三维场景 如下图所示 ...
- 【Xamarin开发 Android 系列 8】 创建一个Json读取数据应用(上)
后续将内容贴上来...........
- Unity3D游戏开发之粒子系统实现具体解释
今天为大家分享的是Unity3D中的粒子系统.粒子系统通经常使用来表现烟雾.云等高级效果.是一个十分注重制作技巧的部分.今天我们将以一个气泡的演示实例来一起学习怎样在Unity3D中使用粒子系统 ...
- cocos2d-x游戏开发(二)之创建第一个项目
配置好开发环境之后,尝试创建一个cocos项目 (1)打开cocos2d-x安装目录,如D:\DIY\cocos2d-x-3.3 看到目录下有可执行文件 download-deps 以及 setup ...
- Revit API创建一个拷贝房间内对象布局命令
本课程演示创建一个拷贝房间内对象布局命令,完整演示步骤和代码.这个命令把选中房间内的对象复制到其它选中的一个或多个房间中,而且保持与源房间一致的相对位置.通过本讲座使听众知道创建一个二次开发程序很简单 ...
- Framework7 - 入门教程(安装、配置、创建一个H5应用)
1,Framework7介绍 (1)Framework7 是一个开源免费的框架.可以用来开发混合移动应用(原生和 HTML 混合)或者开发 iOS & Android 风格的 WEB APP. ...
- 【淡墨Unity3D Shader计划】一间 创建一个游戏场景 & 第一Shader写作
本系列文章由@浅墨_毛星云 出品.转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/40723789 作者:毛星云(浅墨) ...
随机推荐
- matlab判断文件或文件夹是否存在
当前目录中包含以下文件及文件夹: startup.m win64/ … 判断当前目录中是否存在startup.m文件 if ~exist('startup.m','file')==0 error ...
- 单元测试系列:Mock工具之Mockito实战
更多原创测试技术文章同步更新到微信公众号 :三国测,敬请扫码关注个人的微信号,感谢! 原文链接:http://www.cnblogs.com/zishi/p/6780719.html 在实际项目中写单 ...
- SAP进度条
一.代码示例: ),"行数 ll_tabix(),"循环标号 ll_pecnt DECIMALS ,"百分比 ll_pecet(),"百分数 ll_text( ...
- python threading queue模块中join setDaemon及task_done的使用方法及示例
threading: t.setDaemon(True) 将线程设置成守护线程,主进行结束后,此线程也会被强制结束.如果线程没有设置此值,则主线程执行完毕后还会等待此线程执行. t. ...
- iOS-主线程刷新UI【+单例】
主线程刷新UI dispatch_async(dispatch_get_main_queue(), ^{ /// }); 单例 static Tools *_sharedManger; @implem ...
- log4j源码解析-文件解析
承接前文log4j源码解析,前文主要介绍了log4j的文件加载方式以及Logger对象创建.本文将在此基础上具体看下log4j是如何解析文件并输出我们所常见的日志格式 附例 文件的加载方式,我们就选举 ...
- 洛谷 [P3398] 仓鼠找sugar
树剖求LCA 我们可以发现,两条路径ab,cd相交,当且仅当 dep[lca(a,b)]>=dep[lca(c,d)]&(lca(lca(a,b),c)==lca(a,b)||lca(l ...
- 百度地图api 区级以下行政区划
我们在使用百度地图api想要展示苏州市吴中区各乡镇的行政区范围: 百度api有提供了“添加行政区划”的示例:http://lbsyun.baidu.com/jsdemo.htm#c1_10 但该功能目 ...
- Newtonsoft.Json 操作 JSON 字符串
Newtonsoft.Json介绍 在做开发的时候,很多数据交换都是以json格式传输的.而使用Json的时候,我们很多时候会涉及到几个序列化对象的使用:DataContractJsonSeriali ...
- 【SSH框架】之Struts2系列(二)
微信公众号:compassblog 欢迎关注.转发,互相学习,共同进步! 有任何问题,请后台留言联 1.Struts2常量配置 (1).Struts2默认常量配置文件路径,如下图: (2).Strut ...