[Unity3D]水族馆游戏教程一
本次教程使用Unity3D 5.5.5f1版本
首先,打开工程,创建一个名为Aquarium(水族馆)的工程:
在工程中,创建Editor、Scenes、Scripts三个文件夹,分别用来放编辑工具、场景和游戏脚本。
默认场景中,有主相机Main Camera和一个平行光Directional Light。先保存当前场景到Scenes,取名为Entry。
为实现一个水族箱游戏,首先我们需要一个水族箱,鱼的活动范围,将在水族箱内。
在场景中创建一个空的GameObject,名字改为Tank。
在Scripts文件夹中,创建一个名为Tank的c#文件,水箱相关的逻辑将在写在此脚本中。
双击Tank脚本,我们在visual studio中进行编辑。
Tank.cs作为唯一管理水箱的脚本,我们将它写成一个静态的GameObject,之后挂在Tank GameObject上,并且以后可以方便的调用,将Tank的Transform用变量_tr记录下来。
public class Tank : MonoBehaviour { private static Tank _instance; public static Tank instance; private Transform _tr; private void Awake() { _instance = this;_tr = transform; } }
添加三个float变量width、height、depth,分别表示水箱的宽度、高度、深度。
public float width; public float height; public float depth;
将Tank脚本挂在Tank GameObject上,设置Width为50,Height为14,Depth为24。
此时,可以看到在场景中,并不能清楚的展现出水箱的情况,因此,在Tank脚本中,根据width、Height、Depth画出当前水箱的轮廓。在OnDrawGizmos方法中可以将要观察的信息绘制在场景中。注意,如果脚本在Inspector中被折叠,OnDrawGizmos就不会被调用啦。
在OnDrawGizmos中,首先,只在脚本enable的情况下起作用。当_tr为空的时候,重新为_tr赋值。先记下Gizmos的颜色,并且设置新颜色为绿色,在绘制完毕的时候,恢复Gizmos的颜色。
记录Gizmos的Matrix4x4,赋值为Tank Transform的localToWorldMatrix,这样我们就可以绘制Tank Local空间的内容,而当Tank进行平移、旋转、缩放操作时,Gizmos就会自行转换到世界空间了。
使用Gizmos绘制线框立方体,中心位置为local位置的center Vector3.zero,size为变量width、height、depth值。
private void OnDrawGizmos() { if (this.enabled) { if (_tr == null) { _tr = this.transform; } //记录颜色 Color c = Gizmos.color; Gizmos.color = Color.green; //记录matrix Matrix4x4 m = Gizmos.matrix; //赋值为transform的matrix Gizmos.matrix = _tr.localToWorldMatrix; //绘制线框立方体 Gizmos.DrawWireCube(Vector3.zero, new Vector3(width,height,depth)); //恢复matirx和color Gizmos.matrix = m; Gizmos.color = c; } }
现在,在场景中,就可以看到水箱在哪里、有多大啦!
Tank.cs当前的完整代码为:
using UnityEngine; public class Tank : MonoBehaviour { private static Tank _instance; public static Tank instance; private Transform _tr; public float width; public float height; public float depth; private void Awake() { _instance = this; _tr = transform; } private void OnDrawGizmos() { if (this.enabled) { if (_tr == null) { _tr = this.transform; } //记录颜色 Color c = Gizmos.color; Gizmos.color = Color.green; //记录matrix Matrix4x4 m = Gizmos.matrix; //赋值为transform的matrix Gizmos.matrix = _tr.localToWorldMatrix; //绘制线框立方体 Gizmos.DrawWireCube(Vector3.zero, new Vector3(width,height,depth)); //恢复matirx和color Gizmos.matrix = m; Gizmos.color = c; } } } 3.相机
使用透视相机(Main Camera的默认模式就是透视模式),并且调整相机的位置,使得水箱在相机范围内。
相机Position的z值调整为-40。Clipping Panels Far值调整为100,因为用不到1000那么远。效果如下图所示。
当选中相机的时候,在scene中才能看到相机的位置和视野范围,不是很直观。在此,开发一个显示相机视野范围的小工具脚本。
在Scripts文件夹中创建名为CameraOutline的c#脚本,双击打开编辑。
和绘制水箱轮廓一样,在OnDrawGizmos中,绘制相机的视野范围。
记录Gizmos的颜色,并使用黄色进行绘制。
分别处理正交模式和透视模式两种情况。
正交模式比较简单,视野范围是个立方体。需要注意的是,Camera绘制的前方实际上是Camera的back,而不是forward。相对于Camera的Local坐标系中,中心点是(nearClipPanel+farClipPanel)*0.5。相机的宽高比为aspect,而size为视野范围高度的一半。因此,相机的视野高度=orthographicSize*2,宽度=(视野高度*aspect)。深度=远截面-近截面。然后,存储Gizmos的matrix,赋值为相机cameraToWorldMatrix,进行绘制,当相机有平移、旋转、缩放的时候,不用我们再去进行计算了,因为Gizmos使用的cameraToWorldMatrix已经为我们计算过了。最后,恢复Gizmos的matrix。
正交模式代码如下:
if (cam.orthographic) { Vector3 center = Vector3.back * (cam.nearClipPlane + cam.farClipPlane) * 0.5f; Vector3 size = new Vector3(cam.orthographicSize * 2 * cam.aspect, cam.orthographicSize * 2, cam.farClipPlane - cam.nearClipPlane); Matrix4x4 m = Gizmos.matrix; Gizmos.matrix = cam.cameraToWorldMatrix; Gizmos.DrawWireCube(center, size); Gizmos.matrix = m; }
透视模式相对复杂一些,我们需要分别获得近截面的四个点和远截面的四个点,最后通过绘制线的方式绘制出平截头。但是,Gzimos给我们提供了DrawFrustum方法,只需要按参数传入就好了。
Gizmos.matrix = cam.cameraToWorldMatrix; // center是平截头的顶端,即摄像机的位置。相对于自己是zero. Vector3 center = Vector3.zero; Gizmos.DrawFrustum(center, cam.fieldOfView, cam.farClipPlane, cam.nearClipPlane, cam.aspect);
然而,此时的结果,正好是和正确表现反向的。黄色是正确结果,蓝色是反向的。
我们知道,肯定是和cameraToWorldMatrix中,z轴的方向相关,和世界坐标系是相反方向的。
我们只需要改变matrix中z轴的方向就可以了。
已知,矩阵相乘可以看做是一个对另外一个矩阵进行平移、旋转和缩放操作,因此,我们只需要对cameraToWorldMatrix进行z轴相反方向的缩放即可。
Matrix4x4 matrixCam = cam.cameraToWorldMatrix; Matrix4x4 nagtiveZ = Matrix4x4.identity; nagtiveZ.SetTRS(Vector3.zero, Quaternion.Euler(0, 0, 0), new Vector3(1, 1, -1)); Gizmos.matrix = matrixCam * nagtiveZ; // center是平截头的顶端,即摄像机的位置。相对于自己是zero. Vector3 center = Vector3.zero; Gizmos.DrawFrustum(center, cam.fieldOfView, cam.farClipPlane, cam.nearClipPlane, cam.aspect);
最终代码如下:
using UnityEngine; [RequireComponent(typeof(Camera))] public class CameraOutline : MonoBehaviour { private void OnDrawGizmos() { if (this.enabled) { Color c = Gizmos.color; Gizmos.color = Color.yellow; Camera cam = this.GetComponent<Camera>(); if (cam.orthographic) { Vector3 center = Vector3.back * (cam.nearClipPlane + cam.farClipPlane) * 0.5f; Vector3 size = new Vector3(cam.orthographicSize * 2 * cam.aspect, cam.orthographicSize * 2, cam.farClipPlane - cam.nearClipPlane); Matrix4x4 m = Gizmos.matrix; Gizmos.matrix = cam.cameraToWorldMatrix; Gizmos.DrawWireCube(center, size); Gizmos.matrix = m; } else { Matrix4x4 m = Gizmos.matrix; Matrix4x4 matrixCam = cam.cameraToWorldMatrix; Matrix4x4 nagtiveZ = Matrix4x4.identity; nagtiveZ.SetTRS(Vector3.zero, Quaternion.Euler(0, 0, 0), new Vector3(1, 1, -1)); Gizmos.matrix = matrixCam * nagtiveZ; // center是平截头的顶端,即摄像机的位置。相对于自己是zero. Vector3 center = Vector3.zero; Gizmos.DrawFrustum(center, cam.fieldOfView, cam.farClipPlane, cam.nearClipPlane, cam.aspect); Gizmos.matrix = m; } Gizmos.color = c; } } }
先到这里~
相关知识
Unity3d 性能优化篇
无光照可调节透明通道Shader(unity3d)
植物大战僵尸花园水族馆
重建水族馆安卓版下载
开心水族馆攻略揭秘:珍稀装饰获取途径
水族馆日本花园DLC下载
奥比岛手游水族馆怎么进去?奥比岛手游水族馆位置在哪
中班舞台音乐剧《水族馆》
游水族馆400字作文
水族馆三消狂欢安卓版下载
网址: [Unity3D]水族馆游戏教程一 https://www.huajiangbk.com/newsview2201828.html
上一篇: 膨珊瑚对水族箱有什么好处?如何正 |
下一篇: 每天认识一种鱼(376)丨花鮨: |
推荐分享

- 1君子兰什么品种最名贵 十大名 4012
- 2世界上最名贵的10种兰花图片 3364
- 3花圈挽联怎么写? 3286
- 4迷信说家里不能放假花 家里摆 1878
- 5香山红叶什么时候红 1493
- 6花的意思,花的解释,花的拼音 1210
- 7教师节送什么花最合适 1167
- 8勿忘我花图片 1103
- 9橄榄枝的象征意义 1093
- 10洛阳的市花 1039