Unity官网提供了详尽的文档和丰富的教学视频,昨天跟着视频做了一个简单的3d游戏“roll-a-ball”。游戏涉及了许多Unity的基本知识,用来入门很不错。
这篇博文并不讲述整个游戏的制作流程,如果您感兴趣,可以访问这里,如果访问遇到什么困难,在B站有一摸一样的视频。
这是完成以后的样子:
运行效果:
作为个人小结,下面写一些做这个游戏的收获:
1、什么是Unity?
一款游戏引擎,至于什么是游戏引擎,这里不展开。
2、下载和安装
官网:Unity官网
作为学习用途,下载personal版即可。
3、熟悉Unity界面
进入Unity后,将会看到这样的界面:
上图将界面划分成了5部分,下面分别解释每部分的功能:
(1)Toolbar
上面的按钮有不同的功能,比如左侧的第一个按钮可以用来移动场景中的物体,第二个按钮用来进行平移变换,第三个按钮用来进行旋转变换等。
(2)Hierarchy window
顾名思义,这个部分显示的是“层次结构”,场景中的对象都会被列到这个窗口中。当我们新建一个Unity项目时,Unity就会自动为我们添加两个东西:Main Camera和Directional Light,一个是相机,一个是光照。Hierarchy window上面有一个create按钮,点击这个按钮,我们可以看到一个包含了空对象、2d,3d对象、UI、光照、相机等在内的菜单,在这里你可以点击你想创建的东西。
(3)Scene view
这是游戏的场景,我们可以通过调整右上角的坐标系图案来调整观察场景的位置。
(4)Inspector window
当我们选中一个对象,打开Inspector window,这个对象的信息,例如所在的位置,平移了多少等等都会在这个窗口显示,当然也可以用这个窗口来调整场景中的对象,例如为了编辑方便,一开始我们会使用transform中的reset,将对象放置在坐标原点(0,0,0)。Inspector window最下面有一个Add Component按钮,通过这个按钮可以给对象增加其它的component,例如添加一条C#脚本等。
(5)Project window
这个窗口显示的是这个游戏使用的资源,通常我们会在这里建立一些文件夹,例如Scenes文件夹专门保存场景,Materials文件夹专门保存材质,Scripts文件夹专门保存脚本等。Project window上有一个不起眼的create按钮,这个按钮很有用,例如我们可以点击create->folder来新建一个文件夹等等。
事实上,这只是Unity界面一个最基本的布局,你可以自己拖动这些window或者view来将它们放置在自己喜欢的位置,也就是说,操作界面是可以个性化的。其实上面漏掉了一个很重要的view:game view,如下图所示:
这个view的按钮就在scene view旁边,上图中我已经将它拖动到了scene view下面,这个视图显示的是我们的游戏最终呈现给用户的样子,制作好一个游戏后,可以点击Toolbar中间那个表示Play的按钮进行试玩,游戏的运行情况就显示在这个视图中。
为了方便编辑,我们常把Scene view和Game view并列在一起,就像上图一样,这样,在用Play试玩调试的时候可以不用频繁切换视图,从而节省了时间。
4、怎么理解游戏中的几个脚本?
Unity会自动为每个新建的C#脚本生成void Start()和void Update()两个方法,第一个在第一帧,也就是游戏刚开始时调用,第二个在画面更新时调用(准确地说是在渲染每一帧之前被调用)。
在这个游戏中我们会用到三个脚本:
(1)CameraController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraController : MonoBehaviour {
public GameObject player;
private Vector3 offset;
void Start () {
offset = transform.position - player.transform.position;
}
void LateUpdate () {
transform.position = player.transform.position + offset;
}
}
脚本的作用是当Player移动时,让相机也随着移动。
这里有一个问题:要达到类似的效果,为什么不直接把Main Camera设置成Player的孩子?
(2)PlayerController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class PlayerController : MonoBehaviour {
public float speed;
public Text countText;
public Text winText;
private Rigidbody rb;
private int count;
void Start()
{
rb = GetComponent();
count = 0;
SetCountText();
winText.text = "";
}
void FixedUpdate()
{
float moveHorizontal = Input.GetAxis("Horizontal");
float moveVertical = Input.GetAxis("Vertical");
Vector3 movement=new Vector3(moveHorizontal,0.0f,moveVertical);
rb.AddForce (movement*speed);
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag ("PickUp"))
{
other.gameObject.SetActive (false);
count++;
SetCountText();
}
}
void SetCountText()
{
countText.text = "Count:" + count.ToString ();
if(count>=12)
{
winText.text="You Win!";
}
}
}
这个脚本被添加到了叫做Player的小球上,Start函数用来做初始化,其中的getComponent用来获取刚体对象,也就是添加到叫做Player的小球上的那个RigidBody。为什么用FixedUpdate()不用Update()?因为FixedUpdate在做物理计算之前被调用,这个游戏中的碰撞属于physics的范畴,所以用FixedUpdate()。还有一个要注意的函数是OnTriggerEnter(),这个函数在对象碰到collider的时候会被触发,在这个例子中,我们给12个Pickup关联上了一个叫“PickUp”的Tag,当碰撞发生时如果发现Tag是PickUp,就deactivate这个PickUp(每个PickUp的is trigger需要勾选上)。教学视频中提到一个问题:除了要给PickUp的collider勾选is trigger,还要加上rigidbody(is kinematic),这是因为Unity计算所有collider的体积后把它们放在一个cache里,如果collier是静态的(static),这样做可以避免在每帧更新的时候重复计算,但是在我们这个游戏中,因为每次collider都在旋转,所以每次它的体积都会被重复计算,为了节省资源,可以把collider设置成动态的(dynamic=collider+rigidbody)。
(3)Rotater.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Rotator : MonoBehaviour {
// Update is called once per frame
void Update () {
transform.Rotate (new Vector3(15,30,45)*Time.deltaTime);
}
}
这里要用的是Update而不是FixedUpdate(和物理无关)。
5、其他
(1)prefab
类似模板一样,可以将需要复用某个逻辑的一堆对象放到prefab文件夹中,这就可以对整体进行编辑、修改了。
(2)快捷键
例如ctrl+D用来duplicate
(3)有不懂的查文档!!!