美文网首页Android游戏
【Unity3D】二、制作滚球游戏学习Unity3D(上)

【Unity3D】二、制作滚球游戏学习Unity3D(上)

作者: 超级超级小天才 | 来源:发表于2019-02-10 20:55 被阅读298次

    从创建项目开始

    创建一个项目

    打开unity,在Projects中可以查看当前的本地项目或者云端项目,点击New project或者右上角的New都可以新建项目。


    创建一个项目

    然后在1处填写创建项目的名称,2处选择创建地址,3处选择Template(模板),可以选中3D或者2D。


    创建一个项目
    稍等片刻即可进入unity的主页面。

    保存Scene并管理Assets

    进入unity之后,可以看到已经预设的SampleScene和其中的Main Camera(主摄像机)和Directional Light(平行光)组件,如果你不喜欢这些预设的名字,直接点击修改并使用Ctrl+S保存你的修改即可。


    保存Scene

    为了使我们的Assets文件夹管理地更加井井有条,推荐对不同的assets进行分文件夹管理,这时一些文件夹的命名可以自己定义,但通常可以遵循一定的不成文的规定,比如通常将场景存放在Scenes目录、将脚本存放在Scripts目录等等,要根据自己来管理好Assets目录,以后对于大量的assets可以很方便快捷。

    创建游戏场景

    创建Plane

    可以使用unity的内置GameObject的Plane(平面)类型来作为游戏场景的“地面”。
    可以在Hierarchy视窗下右键选择3D Object下找到Plane创建,也可以在顶部菜单栏的GameObject下的3D Object下找到Plane创建。当然也可以看到unity为我们创建了很多预置的Game Object,比如3DO bject、2D Object、Effects、Light、Audio、 Video、UI、Camera等等,当然每一个分类下还有更详细的分类,这些都可以直接拿来使用,非常方便,一些重要的Game Object以后还会慢慢使用。


    新建GameObject的Plane

    这里只需要创建一个Plane并将其命名为Ground来作为我们游戏的“地面”,可以看到Plane出现在了MainScene中,同时我们可以注意到Hierarchy视窗中的MainScene右上角出现了一个*号,这就表示该Scene处于待保存的状态,可以通过菜单栏的File->Save或者快捷键Ctrl+S保存Scene。


    待保存的Scene
    选中刚刚创建的Ground,Inspector视窗中就会出现其所有的Components,这些都是预先被untiy设置给Plane的,点击Transform这一Component的右侧的齿轮状图标,可以选择Reset(重置)选项,这样,刚刚创建的Plane的Transform就会被重置为初始值,它的Position会被设置为(0,0,0),这是整个游戏世界的原点坐标,游戏中的所有GameObject的坐标都是基于此原点进行计算的。
    初始化Transform
    选中任何一个GameObject,比如选中Ground,然后按F键,或者在菜单栏中点击Edit->Frame Select可以快速地调整Scene的角度,让我们有一个非常合适的角度来观察Ground的全貌。

    改变Transform

    改变Transform的三组值的方法有很多。

    直接赋值

    可以在Inspector面板中对Transform的九个值直接输入数值来设置


    在Inspector面板中设置Transform的值

    拖动输入框调节

    当我们把鼠标指向每一个值的输入框的左侧边界时,就会发现鼠标成为了一个左右双箭头的形状,此时按下鼠标左键所有拖动,就会发现该输入框变成了蓝色,并可以随着拖动改变它的值。


    拖动输入框

    在Scene窗口中改变

    在左上方有六个按钮,分别表示对Scene中GameObject的操作。
    这里提一句:不管选中六个按钮中的哪一个,只要按住Alt键在Scene中拖动鼠标就可以转动视角,只要滚动鼠标滚轮即可放大/缩小视角。
    这六个按钮从左到右依次为:


    六个改变Scene中GameObject的选项
    • 第一个:拖动Scene的视角
    • 第二个:选中后,再选中Scene中的任何一个GameObject,就可以通过拖动它的三个方向箭头(x、y、z)以及三个平面(xy平面、xz平面、yz平面)来改变Position的值。


      改变Position
    • 第三个:选中后可以在Scene中对选中的GameObject改变其Rotation的值


      改变Rotation
    • 第四个:选中后在Scene中可以对选中的GameObject进行三个方向的Scale的调整


      改变Scale
    • 第五个:选中后可以在Scene中对选中的GameObject进行顶点的位置调整从而改变Scale的值


      改变Scale
    • 第六个:选中后可以同时改变Position、Rotation、Scale的值,是第二三四个的结合。


      同时改变所有的Transform

    创建游戏对象

    创建Sphere

    接下来创建小球,同样地,在MainScene下右键->3D Object->Sphere来创建一个unity预置的Sphere(球体),命名为Player,并通过reset其Transform来使其位置重置到原点。


    新建一个Sphere

    这样我们看到小球的中心已经被定位到了(0,0,0)处,为了让小球能在平面上滚动,我们需要将小球放到平面上。
    观察小球的Transform我们可以得到,它的Scale的值为(1,1,1),也就是说它的三个方向的大小都为1单位,为了让小球放到平面上边,显然我们需要将其向上移动半个球的距离,即将Position的Y值设置为0.5,小球就刚好在平面上了。


    将小球放到平面上

    关于光源

    其实我们可以看到小球是有影子的,这是最开始unity为我们准备的Directional Light作用的结果,我们可以看到Scene中的一个小太阳的标志,这个就是我们的光源,使用Directional Light来模拟太阳的平行光。它的Transform则显示了光源的位置、角度(也就是平行光的照射方向),如果我们将这个GameObject去掉的话就没有了光的效果。
    当然通过改变Rotation的值就可以调节光源的方向,比如为了效果我将Rotation的Y值改为60。


    关闭光源后的效果

    创建Material

    为了使GameObject美观,我们通常会对其表面进行一系列装饰,而其表面的表现是通过为这个GameObject添加Material(材料)来实现的。
    接下来为我们的Ground和Player添加最简单材料:纯颜色。
    在Assets下新建Materials目录用于管理各种材料,然后右键该目录选择Create->Material新建一个材料命名为Background。


    新建一个Material

    选中Background,就可以看到它的Inspector面板了,我们在Albedo(反射率)一栏中可以选择一种颜色,在下方的预览中就可以看到效果了,这里我们选择RGB色(0,32,64)作为我们的Background的颜色。


    为Material选择颜色
    想要将创建的Material运用在某个GameObject上,很简单,只需要拖动该Material到Scene中的目标GameObject上或者拖动到Hierarchy的该GameObject上即可。
    将Material运用到Scene中
    可以看到我们的Ground已经变成了蓝色
    成功改变Plane的颜色

    让小球滚动起来

    让小球拥有成为刚体

    为了让小球有滚动的效果,我们需要小球拥有一系列的物理属性,物理属性已经由unity内置,我们只需为需要增加物理属性的GameObject添加一个Rigidbody的Component即可。如上一节中所示,选中Player,在Inspector面板中通过Add Component中找到Physics下的Rigidbody即可。


    添加Rigidbody属性

    为小球添加控制脚本

    有了刚体属性的小球需要在我们的控制下滚动,比如我们规定使用W,S,A,D四个按键来控制小球的方向,那么对于一个有物理属性的刚体来说,为了能够动起来,当然需要力(Force)作用在物体上,这些有关于如何控制GameObject的方法需要我们使用脚本(Scripts)来完成,假如你已经拥有了一定的C#编程基础。
    同样我们在Assets下创建Scripts目录来管理脚本,在该目录处右键->Create->C# Script创建一个脚本,这里我们命名为PlayerController。


    新建脚本

    为了让我们创建的脚本与Player联系起来,可以在Player的Inspector面板下选择Add Component,在其中搜索我们的脚本名字就可以找到该脚本,根据unity的命名规范,喜欢将脚本各个单词使用“驼峰法”并且首字母同样大写的方式,有趣的是,unity对于这些脚本通常都会在每个大写字母处将这些单词分开,我也不知道为什么。简单点儿的话可以直接将Assets中的脚本拖到Inspector面板下,就可以添加成功。


    将脚本添加给GameObject

    打开脚本

    编辑脚本需要编辑器,Visual Studio是较好的选择,它和unity之间有很好的合作关系,使用起来也很方便。双击脚本文件或者在Inspector面板中点击脚本的右上角的齿轮图标选择Edit Scrpit都可以打开编辑器对其进行编辑。


    Unity的预置脚本内容

    unity已经为我们预置好了脚本的最基本结构,最基本的,我们可以看到所有的unity脚本都继承自MonoBehaviour类,然后有两个预设函数,Start函数是在第一帧开始渲染前调用,Update函数在每一帧刷新前调用,都是非常常用的函数。
    接下来思考我们要做的事情,我们需要检测用户的输入,并且通过输入的按键来控制小球的滚动方向,检测用户的输入同时也需要识别输入的是哪一个按键,除此之外我们还需要一些物理学有关的逻辑,比如我们需要添加一个力来控制小球的移动,这就是物理学逻辑,这些逻辑当然是每一帧都要进行一次,所以我们需要将这些逻辑写在每一帧更新都要执行的函数中。
    显然我们可以写到Update函数下,因为Update函数是每一帧刷新前都会调用的,同时我们还有另外的选择,即使用FixedUpdate函数,它在每一次进行物理学运算的时候调用,每次检测到用户输入都需要进行物理学运算,所以我们可以将逻辑写到FixedUpdate函数下。

    开始编写脚本

    首先我们需要创建一个对于这个Player小球的引用,这样才能知道我们控制的是哪个小球,这里小球是刚体,所以我们创建一个刚体(Rigidbody)的引用,并且需要在第一帧开始渲染之前通过GetComponent方法来找到小球创建刚体的引用,这一逻辑自然就需要写到Start函数中了。

    private Rigidbody rigidbodyPlayer;
    
    void Start()
    {
        rigidbodyPlayer = GetComponent<Rigidbody>();
    }
    

    接下来对用户输入的读取就需要写到FiexedUpdate函数中了,我们使用Input类的GetAxis方法来获取水平或者垂直的运动轴,这个方法会返回一个float值作为该轴的移动距离。

    float moveHorizontal = Input.GetAxis("Horizontal");
    float moveVertical = Input.GetAxis("Vertical");
    

    通过以上两行代码我们就可以将用户的W,S,A,D输入转化为水平轴和垂直轴的移动距离,分别存储在moveHorizontal和moveVertical两个float类型的变量中。

    接下来通过Rigidbody类的AddForce方法可以为刚体添加作用力,AddForce方法接受一个三维向量(Vector3)参数,这个三维向量就可以表示力,显然我们的三维向量可以用刚才的moveHorizontal和moveVertical两个变量作为X值和Z值,同时我们是不需要小球在Y方向上移动的,也就是将Y方向的力作用设置为0.0f即可,经过调试我们会发现小球的移动速度过慢,为了方便调节小球的速度,只需要在表示力的三维向量前乘以一个倍数即可,为了方便调整,我们设置一个public的float类型的变量speed来调节这个乘积。
    这里必须说明的是,凡在unity的脚本中被声明为public类型的变量,在unity的Inspector界面中的该脚本的Component下都会出现一个可以设置的值的方框。

    public float speed;
    void FixedUpdate()
    {
        Vector3 movement = new Vector3(moveHorizontal,0.0f,moveVertical);
        rigidbodyPlayer.AddForce(movement*speed);
    }
    
    更改public的Speed的值

    此处我们将speed的值设为10比较合理,运行游戏就会发现通过W,S,A,D的控制,小球动了起来。


    让小球滚动起来

    完整的代码:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class PlayerController : MonoBehaviour
    {
        private Rigidbody rigidbodyPlayer;
        public float speed;
    
        void Start()
        {
            rigidbodyPlayer = GetComponent<Rigidbody>();
        }
    
        void FixedUpdate()
        {
            float moveHorizontal = Input.GetAxis("Horizontal");
            float moveVertical = Input.GetAxis("Vertical");
    
            Vector3 movement = new Vector3(moveHorizontal,0.0f,moveVertical);
    
            rigidbodyPlayer.AddForce(movement*speed);
        }
    }
    

    当然你也会发现,小球超出了Plane的边界居然掉了下去,其实这是合理的,因为小球为刚体,也就拥有物理引擎,当然受到重力的影响,在没有Plane的向上的作用力的情况下自然会下落。

    设置摄像机

    可以发现,我们的Camera的角度和位置都比较刁钻,这导致我们的游戏看到的画面并不完整,接下来我们对Camera进行设置,使其能够跟随我们的小球滚动来同时移动。
    首先调节Main Camera的Position和Rotation使得画面和角度比较合适,比如这里将Position的Y值设为6,Z值设为-6,将Rotation的X值设为45得到了一个较为合适的位置。


    改变摄像机的Transform

    接下来通过脚本控制Main Camera跟随小球Player一同移动,即在Position上保持相对静止。
    可能你会想到,只需要将Main Camera拖动给Player使其成为Player的子物体不就可以保持两者相对位置不变化了吗?但是问题在于球体Player是滚动的,如果两者的位置完全相对静止,就会导致球滚动时Main Cmaera也会跟着球滚动,有一种天旋地转的感觉。感兴趣的话可以尝试一下。
    新建脚本CameraController并添加给Main Camera做一个Component。为了使Main Camera的Transform的Position和Player的保持相对静止,Rotation并不和其保持一致,可以想到一个办法:设置一个偏移量,这个值初始化为游戏开始时Main Camera和Player之间的Position的差值,然后在球滚动时,每一次滚动都改变Main Cmaera的Position,使其新的Position等于现在球的Position的值加上刚才的偏移量,这样就会在每次球的位置改变时Main Camera都会跟上它的步骤。
    显然,偏移量的设置需要在Start函数中完成,每一次球的位置发生变化时的逻辑可以在Update函数中完成,但还有一个更好的选择,就是LateUpdate函数,该函数在每次有GameObject发生变动时才会调用。
    同时,我们的脚本使加在Main Camera上的,所以Main Camera的Transform可以直接调用,但是球的Transform则需要单独获取,这里我们设置一个public的GameObject量,然后在unity中将球Player拖动到这个量处作为参数即可。

    private Vector3 offset;
    public GameObject player;
    
    void Start()
    {
        offset = transform.position - player.transform.position;
    }
    
    void LateUpdate()
    {
        transform.position = player.transform.position + offset;
    }
    
    添加Player实例

    这时候运行游戏就可以发现Main Camera的位置随着球的改变而发生了改变。


    MainCamera成功跟随小球变化位置

    完整的代码:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class CameraController : MonoBehaviour
    {
        private Vector3 offset;
        public GameObject player;
    
        void Start()
        {
            offset = transform.position - player.transform.position;
        }
    
        void LateUpdate()
        {
            transform.position = player.transform.position + offset;
        }
    }
    

    建立围墙

    为了不让小球总是滚落到Plane之外,可以在其四周围建立起一圈儿围墙,很简单,使用预设的Cube就可以了。
    为了更好的管理四个围墙,我们可以先创建一个空的GameObject,将其命名为Walls,Reset使其重置位置,然后在其上右键新建一个Cube,并命名为WestWall,这样这个Cube就成为了Walls的子物体。


    新建Cube

    接下来如何调整这面墙的大小、位置就很简单了,可以在Inspector中直接输入具体数值,也可以直接在Scene中拖动和缩放,最好我们可以得到这个墙体结构。


    改变Cube的Transform
    为了简单方便,只要选中WestWall,在菜单栏的Edit中选择Duplicate(复制)(快捷键:Ctrl+D)即可,然后将复制好的墙拖动到适合的地点,在复制,最后可以得到四面墙。
    复制Cube建立围墙
    接下来测试游戏,墙起作用了!
    围墙正常运行

    下一篇文章:https://www.jianshu.com/p/7e0e85092e5a

    参考资料:https://unity3d.com/learn/tutorials/s/roll-ball-tutorial
    本节内容的完整官方教程视频分享(英文无字幕):https://pan.baidu.com/s/1TNMMFjs7pZqLPhGQZ1tPqQ 提取码:1u70


    转载请注明出处,本文永久更新链接:https://blogs.littlegenius.xin/2019/02/10/从滚球游戏初步体验Unity3D/

    相关文章

      网友评论

        本文标题:【Unity3D】二、制作滚球游戏学习Unity3D(上)

        本文链接:https://www.haomeiwen.com/subject/vuixeqtx.html