[Unity3D]水族馆游戏教程一

本教程介绍如何使用Unity3D 5.5.5f1创建水族箱游戏。首先创建名为Aquarium的工程,组织文件夹结构。接着创建水箱 GameObject 并编写Tank脚本,用于管理水箱逻辑,包括设置尺寸并在OnDrawGizmos中绘制轮廓。最后调整相机视角,确保水箱在相机范围内,并编写CameraOutline脚本来显示相机视野范围。
摘要由CSDN通过智能技术生成

水族箱

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;
        }
    }
}

先到这里~

Unity博物馆源码是指使用Unity游戏引擎开发的博物馆展示类应用程序的源代码。这样的源码通常包含了游戏的各种元素,如场景搭建、模型导入、动画效果、物理引擎等。通过编写Unity博物馆源码,开发者可以实现沉浸式的博物馆展示体验,使用户能够在虚拟环境中逼真地观察文物、艺术品等。 Unity游戏引擎是一款非常强大的跨平台游戏开发引擎,它提供了强大的工具和资源,使得开发者可以快速创建博物馆展示应用。在Unity博物馆源码中,我们可以看到使用Unity的脚本语言编写的代码,通常是C#,用于控制各种游戏对象和实现交互功能。 Unity博物馆源码通常包括以下内容: 1. 场景搭建:通过设置各种游戏对象的位置、旋转和缩放,来构建博物馆的虚拟环境。 2. 模型导入与贴图:将真实的文物或艺术品模型导入Unity中,并为其应用相应的贴图,使其逼真地展示在应用中。 3. 动画效果:通过编写脚本代码,实现文物或艺术品的动画特效,例如旋转、平移等,增加展示的趣味性。 4. 智能交互:利用Unity的物理引擎和碰撞检测功能,实现用户与文物或艺术品之间的交互,例如点击、触摸等操作。 5. 虚拟导览:通过编写脚本代码,实现用户在虚拟博物馆中的导览功能,包括自动导览、路径规划等。 通过使用Unity博物馆源码,开发者可以依据自己的需求进行修改和定制,创造出独特的博物馆展示应用。同时,Unity作为一个跨平台引擎,支持多种设备和操作系统,开发出的应用可以在不同平台上运行,以实现更广泛的展示和分享。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

延澈左

小小心意

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值