今天含泪开一个新坑——Unity 3D。由于导师调整任务,最近要和师兄一起搭建3D虚拟仿真平台,特此学习。ROS也会继续学习下去,希望能够兼容到一起。Let’s get it !
在这里给大家推荐一篇教程,很详细,亲测有效!我就不做重复工作了!
目前感觉这种界面布局蛮舒服的,大家可以改成这种形式。
具体设置方式:
click Layout(右上角)——select tall
click Project 右边的设置——select One Column Layout
目前 Unity 只支持 C#脚本文件(Scripts),不再支持 Monodevelop和 Java.
可以将C#文件的编译器直接设置为:Visual Studio Community 2019
步骤:Edit -> Preferences -> External Tools -> External Script Editor
解释一下,之前默认的 Open by file extension 是指根据拓展名进行选择。
设置字体:JetBrains Mono
设置方式:Visual Studio -> 工具 -> 选项 -> 字体和颜色
主要的功能窗口有:Scene、Game、Hierarchy、Project、Inspector 5部分
注意:Unity中不提供复杂游戏物体,需要通过3DMax、Maya等绘制。
前四个最为常用,分别是:
Hand tool 视图工具
Move tool 移动工具
Rotate tool 旋转工具
Scale tool 缩放工具
分别对应快捷键:Q、W、E、R
其余的需要注意的是:Global 和Local 坐标系的切换;Pivot是基准中心(原点),Center是碰撞中心,一般使用 Pivot 和 Local 即可,剩下的具体使用时再进行介绍。
经过前期了解后,正式开始开发第一个案例。
平面默认尺寸问为10x10,要求大小为20x20,即将x和z的scale设置为2
由于初始平面是白色的,我们想要更改颜色(材料)的话,需要给游戏物体添加材料。
在Assets新建一个 Materials 文件夹,创建一个材料属性,修改名字为 BackGround。
此时,双击打开创建的材料文件,设置属性。里面可以选择自己想要的颜色。
将创建好的材料拖拽到平面上即可为平面添加属性。
步骤和创建平面一样
步骤:
此时,Player就拥有了一些物理属性,比如受力、碰撞等。运行游戏进行检查,此时小球可以自由下落到平面上。
//引用系统提供的类
using System.Collections;
using System.Collections.Generic;
//引用Unity引擎
using UnityEngine;
public class PlayerController : MonoBehaviour
{
//设置一个公开属性 private是私有属性,不显示标签
public Rigidbody rd;
//Start is called before the first frame update
void Start()
{
//将代码与Player的刚体组件关联
rd = GetComponent<Rigidbody>();
}
//Update is called once per frame
//60 frame/s 游戏一秒60帧
void Update()
{
//给Player施加一个持续向右 1N 的力
//力用一个三维向量来表示
rd.AddForce(Vector3.right);
}
}
代码:
/引用系统提供的类
using System.Collections;
using System.Collections.Generic;
//引用Unity引擎
using UnityEngine;
public class PlayerController : MonoBehaviour
{
//设置一个标签
public Rigidbody rd;
//Start is called before the first frame update
void Start()
{
rd = GetComponent<Rigidbody>();
}
//Update is called once per frame
//60 frame/s 游戏一秒60帧
void Update()
{
//监听(得到输入)
//得到一个浮点数据
float h = Input.GetAxis("Horizontal");//a=-1,d=1
float v = Input.GetAxis("Vertical");//w=
Debug.Log(h);
rd.AddForce(new Vector3(h, 0, v)*10);
}
}
对比之前的直接输入力的代码相比,有其中三行发生了变动:
float h = Input.GetAxis(“Horizontal”);//a=-1,d=1
float v = Input.GetAxis(“Vertical”);//s=-1,w=1
rd.AddForce(new Vector3(h, 0, v)*10);
其中,input.GetAxis()代表获取键盘上的指令,Horizontal 代表水平方向,也就是左右移动,默认按键是a和d(可以进行修改),Vertical 代表垂直方向,也就是前后移动,默认按键是w和s。
控制效果:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FollowTarget : MonoBehaviour
{
//设置一个公开的属性,通过拖拽Player进行属性添加
public Transform playerTransform;
//定义一个内置属性,类似变量,用于在两个函数之间调用
private Vector3 offset;
// Start is called before the first frame update
void Start()
{
//首先在开始之前,计算相机与小球之间的位置偏差
offset = transform.position - playerTransform.position;
}
// Update is called once per frame
void Update()
{
//控制相机始终按照初始位置偏差跟踪小球
transform.position = playerTransform.position + offset;
}
}
由于之前小球在平面上运动,一不小心就会掉落下去。我们通过添加墙,来给小球的运动添加限制条件。
我们添加4个cube分别作为4堵墙,如下图所示。
此时小球的运动会受到墙的限制,控制结果如下图所示。
直接给 Prefab Food_1添加一个脚本控制文件,可以保证小球持续旋转:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Food : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
transform.Rotate(Vector3.up);
}
}
首先,为食物添加标签,直接给预制体添加即可:
给小球(Player)的C#文件添加碰撞检测事件:
//碰撞系统事件,碰到物体时会触发
private void OnCollisionEnter(Collision collision)
{
//检测碰撞到的游戏物体的标签是不是“Food”
if (collision.gameObject.tag == "Food")
{
//销毁碰撞到的游戏物体
Destroy(collision.gameObject);
}
}
查看游戏效果:
上一小节,我们已经成功控制小球吃掉了食物。但还有一点不足是,碰撞瞬间小球的运动状态发生了变化,这是我们不希望看到的,因此本节将采用另一种方法进行检测,并销毁食物。
触发检测打开方式:
给小球(Player)的C#文件添加触发检测事件:
private void OnTriggerEnter(Collider other)
{
//检测触发到的游戏物体的标签是不是“Food”
if (other.tag == "Food")
{
//销毁触发到的游戏物体
Destroy(other.gameObject);
}
}
在游戏过程中,我们希望每次吃掉食物,都可以获取一定的分数,计分器选择分数累加的结果。
在设计计分器时,需要引进UI模型中的Text:
Hierarchy>>create>>UI>>Text,命名为 ScoreText
我们可以发现,除了我们新建的ScoreText,还多了Canvas和EventSystem,其中Canvas是画布层,也就是我们布置UI的位置,EventSystem是事件交互选项,用来布置按钮之类的,目前不会用到。
在进行UI设计之前,需要先进行Scene窗口设置:将 3D 切换为 2D,双击Canvas即可打开画布。可以调整Text的位置和大小直到得到满意的效果,还可以在属性面板更改颜色等。这里,我们将得分置于右上角:
此时,在游戏界面,得分也会相应显示在右上角:
这时,得分显示是固定的,我们希望分数能够根据我们吃食物的过程动态变化。这就需要我们在Player 的C#脚本中将分数与Text关联。
代码如下:
//引用系统提供的类
using System.Collections;
using System.Collections.Generic;
//引用Unity引擎
using UnityEngine;
//引入UI命名空间
using UnityEngine.UI;
public class PlayerController : MonoBehaviour
{
//设置一个标签
public Rigidbody rd;
//设置一个得分标签
public int score = 0;
//设置一个Text的得分显示标签,在游戏运行之前我们需要将Text拖拽到这个标签下,建立连接
public Text scoreText;
//Start is called before the first frame update
void Start()
{
rd = GetComponent<Rigidbody>();
}
//Update is called once per frame
//60 frame/s 游戏一秒60帧
void Update()
{
//监听(得到输入)
//得到一个浮点数据
float h=Input.GetAxis("Horizontal");//a=-1,d=1
float v = Input.GetAxis("Vertical");//w=1,s=-1
//Debug.Log(h);
rd.AddForce(new Vector3(h, 0, v));
}
//触发检测事件
private void OnTriggerEnter(Collider other)
{
//检测触发到的游戏物体的标签是不是“Food”
if (other.tag == "Food")
{
//销毁触发到的游戏物体
Destroy(other.gameObject);
//每吃掉一个食物,得分加1
score++;
//将得分显示在Text中
scoreText.text = "分数:" + score;
}
}
}
效果显示:
我们希望在吃完所有食物以后,可以显示游戏胜利的字样。
类似得分显示,我们需要先添加一个UI的Text选型,设定好想要显示的字符、样式以及位置。此时,可以先把这一游戏物体关闭,等到吃完所有食物后,再通过代码激活,最终显示在屏幕上。
代码如下图所示:
//引用系统提供的类
using System.Collections;
using System.Collections.Generic;
//引用Unity引擎
using UnityEngine;
//引入UI命名空间
using UnityEngine.UI;
public class PlayerController : MonoBehaviour
{
//设置一个标签
public Rigidbody rd;
//设置一个得分标签
public int score = 0;
//设置一个Text的得分显示标签,在游戏运行之前我们需要将ScoreText拖拽到这个标签下,建立连接
public Text scoreText;
//设置一个游戏物体标签或者Text标签,将对应的WinText拖拽到此标签下,建立连接。
public GameObject winText;
//Start is called before the first frame update
void Start()
{
rd = GetComponent<Rigidbody>();
}
//Update is called once per frame
//60 frame/s 游戏一秒60帧
void Update()
{
//监听(得到输入)
//得到一个浮点数据
float h=Input.GetAxis("Horizontal");//a=-1,d=1
float v = Input.GetAxis("Vertical");//w=1,s=-1
//Debug.Log(h);
rd.AddForce(new Vector3(h, 0, v));
}
//触发系统事件
private void OnTriggerEnter(Collider other)
{
//检测触发到的游戏物体的标签是不是“Food”
if (other.tag == "Food")
{
//销毁触发到的游戏物体
Destroy(other.gameObject);
score++;
scoreText.text = "分数:" + score;
//因为总共有10块食物,当吃光所有食物后,游戏结束,激活游戏胜利显示
if(score == 10)
{
winText.SetActive(true);//激活为 true, 关闭为 false
}
}
}
}
显示效果为:
到这里,游戏设计基本结束了!大家可以发现,我们在实现过程中有些部分还需要拖拽游戏物体到指定标签来建立连接实现。事实上,这些完全可以通过代码来完成,后续将会讲到。
在第3节中,我们完整创建了一个游戏。这一节也是本讲的最后一节,将为大家介绍下制作出来的游戏如何进行打包。
首先,进行打包设置:
File>> Build Settings>>Player Settings :
在这里,我们可以设置分辨率、游戏模式(全屏 or 窗口)等
接着,返回到 Build Settings 进行游戏输出:
依次选择要输出的画面和输出平台
输出到某一指定文件夹中,点击对应的 .exe文件即可打开游戏:
至此,第一个游戏的全部工作已经结束,当然其中涉及到的Unity和C#编程知识还只是冰山一角,后面再接再厉!奥利给!!再次感谢 Siki老师以及Siki学院!