本次教程使用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; } } 123456789101112131415
添加三个float变量width、height、depth,分别表示水箱的宽度、高度、深度。
public float width; public float height; public float depth; 123
将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; } }
12345678910111213141516171819202122现在,在场景中,就可以看到水箱在哪里、有多大啦!
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; } } }
1234567891011121314151617181920212223242526272829303132333435363738394041 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; } 1234567891011
透视模式相对复杂一些,我们需要分别获得近截面的四个点和远截面的四个点,最后通过绘制线的方式绘制出平截头。但是,Gzimos给我们提供了DrawFrustum方法,只需要按参数传入就好了。
Gizmos.matrix = cam.cameraToWorldMatrix; // center是平截头的顶端,即摄像机的位置。相对于自己是zero. Vector3 center = Vector3.zero; Gizmos.DrawFrustum(center, cam.fieldOfView, cam.farClipPlane, cam.nearClipPlane, cam.aspect); 1234
然而,此时的结果,正好是和正确表现反向的。黄色是正确结果,蓝色是反向的。
我们知道,肯定是和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); 1234567
最终代码如下:
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; } } }
12345678910111213141516171819202122232425262728293031323334353637先到这里~
相关知识
[Unity3D]水族馆游戏教程一
如何使用unity3D制作游戏
水族馆像素恐怖游戏攻略 水族馆人像
宠物水族馆游戏专题
宠物水族馆游戏资料
巨型水族馆下载
热带鱼水族馆游戏
怪怪水族馆修改器(九项)下载
疯狂水族馆豪华版修改器
怪怪水族馆下载
网址: [Unity3D]水族馆游戏教程一 https://m.mcbbbk.com/newsview676456.html
上一篇: 哺育鱼 |
下一篇: 宠物:你们鱼缸里放多少鱼是最好的 |