Unity官方案例--Roll a ball
现在的我还是一名 Unity3d 游戏开发初学者,所以现在都在围绕 Unity3d 的官方案例来做练习,为此写下一些文章作为笔记,文章中难免会有一些疏漏,有些不当之处还望指正。
项目简介
首先玩家可以控制一个小球,去吃那些悬浮在平面上的小方块,全部吃玩就游戏结束了,是一个很简单的小游戏。
创建工程
首先我们创建一个空的工程
环境搭建
创建地面
在 Hierarchy 界面中右键选择 3D Object 中的 Plane 创建一个地面,其中将他 Inspector 界面中的 Scale(X:2,Y:1,Z:2)使地面扩大一下,这里需要让大家养成一个好的习惯就是物体的需要命名并且要有意义,所以我将我们的 Plan物体名改为 Ground。
给地面添加材质
但由于这地面太白了,再加上默认的灯光效果很亮表现得很刺眼,所以我给地面添加了一个黑色的材质,这里有需要大家养成一个文件分类的好习惯,所以我在我们的 Assets 文件夹中新建了一个 Materials 文件夹用来存放我们需要用到的材质文件,选中 Materials 文件夹后右键选择 Create 选项中选择 Material 就可以创建一个材质文件了,我将它改名为 Ground,其中在他的 Inspector 界面中将 Main Maps 中的 Albedo 的颜色调整为黑色,最后只需将这个材质文件拖到我们场景中的地面上即可。
添加墙
在 Hierarchy 界面中右键选择 3D Object 中的 Cube 来创建四周的墙,其中在它们的 Inspector 界面中都设置 Scale(X:21,Y:1,Z:1),它们的位置分别设置为
Wall[Positon(X:0,Y:0,Z:10)],
Wall1[Positon(X:0,Y:0,Z:-10)],
Wall2[Position(X:10,Y:0,Z:0),Rotation(X:0,Y:90,Z:0)],
Wall3[Position(X:-10,Y:0,Z:0),Rotation(X:0,Y:90,Z:0)]
这里又有一点需要大家养成的习惯就是若有相同的物体应该创建一个空的物体将他们都存放在你里面,所以我在 Hierarchy 中创建了一个空的物体改名为 Walls 将这四个墙存放在其中。
设置摄像机
选择我们场景中的 Main Camera 设置它的 Position(X:0,Y:10,Z:-10),Rotation(X:45,Y:0,Z:0)即可。
添加 Player
在 Hierarchy 界面中右键选择 3D Object 中选择 Sphere 将它改名为 Player,设置它的 Position(X:0,Y:0.5,Z:0)
添加 Pick Up
在 Hierarchy 界面中右键选择 3D Object 中选择 Cube 将他改名为 Pickup ,其中几个比较关键的设置是 Position 的y的值最好要大于1因为过低 他会卡在地面里,Rotation(X:45,Y:45,Z:45),还有一个特别关键的就是将 Box Collider 中的 Is Trigger 勾上,它的作用是做触发器,简单来说就是就是当两个物体发生碰撞不产生碰撞效果,但会触发碰撞事件(如果还不能理解,自己在 Unity 中实验一下),然后就是多创建几个 Pick Up 位置你们随便放,不过这里也有一个方法方便我们创建多个相同的物体并且还可以同步之后需要更改的设置,那就是创建 Prefab。我们在 Assets 文件夹中创建一个 Prefabs 文件夹,将我们创建的 Pickup物体拖至此文件夹,当我们看到 Pickup 物体的名称变蓝后,这就意味着我们的 prefab 创建完成,当我们需要创建 Pickup 物体时,现在只需将 prefab 中的 Pickup 拖至我们的场景中即可创建,然后就是创建一个空的物体改名为 Pickups 用来存放我们创建的 Pickup 。
在 Inspector 界面中找到 Tag 选项后单机再选择选项中最下方的 Add Tag... 后会来到我们的 Tags & Layers 界面,在下方会看见一个 + 标志后单机在输入框中输入 PickUp 后选择 Sa7e 后即可添加标签
添加 UI
在 Hierarchy 界面中右键选择 UI 后再选择 Text 选项就可以添加我们的 UI 了,我们将创建出来的 Text 文件改名为 CountText,我们可以在 Inspector 界面中的 Text(Script) 中调整文字内容、字体、字体大小、颜色等多种属性,我们必须要做的是将文本默认的内容给删掉就行了,其他的设置看自己喜好了,但我们要将它至于界面的左上角该如何操作呢?我们可以在 Rect Transform 中看到一个田字格,我们单机一下它就会出现很多位置选项,但是并没有我们所需要的左上角,这时候我们只需要一直按住键盘上的 Alt 键就会发现上面的位置选项发生了变化,之后就可以很明显的看到左上角的选项然后我们选择它就可以了,然后在 Canvas 文件夹下在创建一个 Text 改名为 WinText 用来存储我们的胜利文本的,也要将文本内容删去,位置居中默认就行了,其他设置自定义。
游戏运行
从这儿起就要开始我们的脚本编写了,现在 Unity3D 主流脚本编辑语言是 C#,不过像我现在用的 Unity 3D 2018.2的版本脚本语言只剩下了 C#,所以推荐大家写脚本还是用 C# 来编写,学过的朋友理解起来就很方便了,没学过的朋友可以从网上找找相关教学视频了解一下,不过有一点编程经验的其实理解起来还是很简单的,我会在下面脚本中写下相应注释的,方便一些初学者理解的。
Unity官方有一个脚本文档,在遇到什么不懂得问题或者需要完成什么操作脚本忘了怎么写时可以进行查阅。
Player 的移动
选择我们的 Player 物体文件,在 Inspector 的下方点击 Add Component 在其中的输入框中输入 Rigidbody 回车确定选择,即可给我们的 Player物体添加刚体组件,刚体组件的用处就是给物体添加物理属性的,其中我们将 Angular Drag 的值改为0,意思是取消小球的摩擦力。
还是点击 Add Component 在输入框中输入 PlayerController 选择 New script 再点击下方的 Create and Add 即可给我们的 Player 挂载脚本了,然后我在我们的 Assets 文件夹中创建一个 Scripts 文件夹用来存储我们游戏中的所有用到的脚本文件,将我们刚刚创建的脚本文件拖进此文件夹。
双击我们的脚本文件,就打开了我们默认的脚本编辑器来编辑我们的脚本,我使用的是 visual studio 2017。
下面就开始编辑我们的脚本,来完成小球 Player 的移动。
脚本文件名:PlayerController
代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour {
//public 公共的,会使此变量显示在 unity 编辑器中方便我们调节数值
//此处定义一个 speed 变量是为了控制 Player 的运动速度
public float speed;
public void FixedUpdate()
{
//获取横向要使 Player 位移的量
float moveHorizontal = Input.GetAxis("Horizontal");
//获取纵向要使 Player 位移的量
float moveVertical = Input.GetAxis("Vertical");
//定义一个新的三维向量,来确定 Player 的运行方向
Vector3 movement = new Vector3(moveHorizontal, 0.0f, moveVertical);
//给 Player 添加一个力使其运动,力的大小我们可以在 Unity 编辑器中编辑
//这里再乘以一个Time.deltaTime是为了使 Player 完成的是每秒移动 speed 米,而不是每帧 speed 米,你们可以试试将这个Time.detalTime删去后 Player 的运行效果
GetComponent<Rigidbody>().AddForce(movement * Time.deltaTime * speed);
}
}
脚本写完后记得保存一下,再来到我们的 Unity 编辑器中,选择 Player 物体后你会发现在脚本中多出来一个 Speed 项,这就是我们之前定义它为 public 公共项的作用了,我们将他设置值为120,然后点击 Unity 编辑器上方的播放按钮运行,之后我们就可以按 W、A、S、D 键来控制我们的 Player 运动了。
相机跟随
让相机跟随 Player 一起运动,使相机和物体为关联关系但不是父子级别的关系,若是父子关系由于 Player 是球体运动时会滚动,所以相机也会随着 Player 的滚动而滚动,这不是我们需要的效果。
选择 Main Camera 物体用上文同样的方法添加 CameraController 脚本文件,然后拖至 Scripts文件夹中存放,双击脚本文件进行编辑。
脚本文件名:Camera Controller
代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraController : MonoBehaviour {
//创建一个公共的游戏物体,在Unity编辑器中可以将一个物体拖至脚本处的 player 的框中,脚本中就可以直接获取此物体,就不需要查找的步骤
//此处的功能就是将我们需要摄像机跟随的物体添加进去,也就是 Player
public GameObject player;
//创建一个变量,用来存储摄像机与物体 Player 未知的默认的差值
private Vector3 offSet;
private void Start()
{
//我们给 offSet 赋值,值的的大小为摄像机的 Position 三维向量的值减去 物体 Position 三维向量的值,也就是相机与物体之间的距离
offSet = transform.position - player.transform.position;
}
private void LateUpdate()
{
//使我们的相机的位置永远位于物体的位置+ offSet 这个差值
transform.position = player.transform.position + offSet;
}
}
脚本编写完后我们来到 Unity3D编辑器,选择 Main Camera 物体文件后会发现在脚本下方出现了一个叫 Player 的项,我们可以吧 Player 物体拖至后方的框子中,然后运行移动 Player 就会发现摄像机也在跟随着 Player 一起运动。
Pick Up 的自转
这次我们要完成的是将 Pick Up 旋转起来。
选择 Prefabes 中的 Pickup 物体,添加名为 Rotation 的脚本文件后拖至 Scripts 文件夹中,然后双击我们的脚本文件编辑我们的脚本。
脚本文件名: Rotation
代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Rotation : MonoBehaviour {
private void FixedUpdate()
{
transform.Rotate(new Vector3(15, 30, 45) * Time.deltaTime);
}
}
回到 Unity 编辑器运行我们的游戏就可以看到 Pickup 开始自己转了起来。
UI 的控制
打开我们的 PlayerController 脚本,我们在其中编辑 UI 的控制脚本。
脚本文件名:PlayerController
代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//切记一定要调用 UI
using UnityEngine.UI;
public class PlayerController : MonoBehaviour {
//public 公共的,会使此变量显示在 unity 编辑器中方便我们调节数值
//此处定义一个 speed 变量是为了控制 Player 的运动速度
public float speed;
//获取我们创建的 CountText
public Text countText;
//获取我们的创建的 WinText
public Text winText;
//定义个变量记录我们的得分
private int count;
public void Start()
{
//调用我们的自定义函数 SetCount
SetCount();
//初始化我们的winText里的文本为空,功能相当于隐藏了此文本
winText.text = "";
}
public void FixedUpdate()
{
//获取横向要使 Player 位移的量
float moveHorizontal = Input.GetAxis("Horizontal");
//获取纵向要使 Player 位移的量
float moveVertical = Input.GetAxis("Vertical");
//定义一个新的三维向量,来确定 Player 的运行方向
Vector3 movement = new Vector3(moveHorizontal, 0.0f, moveVertical);
//给 Player 添加一个力使其运动,力的大小我们可以在 Unity 编辑器中编辑
//这里再乘以一个Time.deltaTime是为了使 Player 完成的是每秒移动 speed 米,而不是每帧 speed 米,你们可以试试将这个Time.detalTime删去后 Player 的运行效果
GetComponent<Rigidbody>().AddForce(movement * Time.deltaTime * speed);
}
private void OnTriggerEnter(Collider other)
{
//当 Player 碰到了物体的 Tag 名为 PickUp 的物体时运行 if 的程序
//为何要加 Tag呢?因为 Player 在运行中会碰到很多东西,比如:地面、墙壁,这些都不是我想要销毁的物体,所以我们给我们需要销毁的物体添加个“名字”
if (other.gameObject.tag == "PickUp")
{
//销毁 Pickup
Destroy(other.gameObject);
//分数+1
count += 1;
//更新 CountText 的文本内容
SetCount();
//当我们的分数大于我们定义的 Pickup 的个数(因为我创建了8个 Pickup,所以我的是 count >= 8)
if (count >= 8)
{
//给我们的 WinText 的文本内添加获胜内容,其功能也就是显示获胜信息
winText.text = "You Win!";
}
}
}
public void SetCount()
{
//使我们的 CountText 显示分数,其格式为 Count:[分数]
countText.text = "Count:" + count;
}
}
保存我们的代码并打开 Unity 编辑器,选择 Player 物体后将我们的创建的 CountText 和 WinText 物体拖至 PlayerCOntroller 脚本下方相对应的地方,然后运行我们的游戏,此时我们的 Roll a ball 的游戏已经制作完成了。
总结
- 我们写完代码一定要记得将我们需要使用到的物体挂上,不然运行时没有效果或者报错。
- Tag 的添加一定要注意自己的大小写,在脚本添加中判断物体的 Tag 时一定要与我们创建的 Tag 完全一样。
- 其中游戏的实现可能会有很多种方法,自己可以翻阅 Unity 官方的脚本文档然后去尝试使用其他的一些方法来实现我们的游戏。
- 如果自己有能力,可以尝试改编游戏加入自己的想法,然后一一去实现它,这样对于我们的游戏开发很有帮助。
- 游戏开发其实很简单,但是如果想要真正的在这个领域成为“大牛”级别的人物,还需要很多很多的努力,我们一起坚持,一起努力!
欢迎大家收藏我的博客,我会努力更新更多的作品的,给自己加个油!