首页 分享 [Unity3D]水族馆游戏教程一

[Unity3D]水族馆游戏教程一

来源:花匠小妙招 时间:2025-07-25 06:40
水族箱 文章目录 水族箱1.工程创建2.创建水箱3.相机 1.工程创建

本次教程使用Unity3D 5.5.5f1版本

首先,打开工程,创建一个名为Aquarium(水族馆)的工程:

image-20200321174341501

在工程中,创建Editor、Scenes、Scripts三个文件夹,分别用来放编辑工具、场景和游戏脚本。

image-20200321174801361

默认场景中,有主相机Main Camera和一个平行光Directional Light。先保存当前场景到Scenes,取名为Entry。

image-20200321175051138

2.创建水箱

为实现一个水族箱游戏,首先我们需要一个水族箱,鱼的活动范围,将在水族箱内。

在场景中创建一个空的GameObject,名字改为Tank。

image-20200321175600217

在Scripts文件夹中,创建一个名为Tank的c#文件,水箱相关的逻辑将在写在此脚本中。

image-20200321175904189

双击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。

image-20200321181620429

此时,可以看到在场景中,并不能清楚的展现出水箱的情况,因此,在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; } }

现在,在场景中,就可以看到水箱在哪里、有多大啦!

image-20200321183829084

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那么远。效果如下图所示。

image-20200321220519048

当选中相机的时候,在scene中才能看到相机的位置和视野范围,不是很直观。在此,开发一个显示相机视野范围的小工具脚本。

在Scripts文件夹中创建名为CameraOutline的c#脚本,双击打开编辑。

image-20200321221008717

和绘制水箱轮廓一样,在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);

然而,此时的结果,正好是和正确表现反向的。黄色是正确结果,蓝色是反向的。

image-20200322172456423

我们知道,肯定是和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)丨花鮨:

推荐分享