Unity环境搭建
Unity引擎是什么
什么时游戏引擎?
游戏引擎是指一些已编写好的可编辑电脑游戏系统或者一些交互式实时图像应用程序的核心组件。这些系统为游戏设计者提供各种编写游戏所需的各种工具,其目的在于让游戏设计者能容易和快速地做出游戏程序而不用从零开始。
游戏引擎对于我们的意义
1、降低做游戏的门槛
2、提升游戏开发的效率
如何降低开发门槛?
以前做游戏:物理、数学、计算机图形学、计算机原理、操作系统等等与多种程序语言。
现在做游戏:游戏引擎的使用和一种程序语言。
如何提升开发效率?
以前做游戏:图形渲染、物理系统、离子系统、寻路系统、多平台开发等等与上层逻辑。
现在做游戏:游戏引擎和上层逻辑。
如何学习游戏引擎?
1、学习引擎用于开发的主要语言。
2、学习引擎的软件操作。
3、学习引擎提供的API和核心系统
如何学习Unity?
Unity相当于就是一个游戏开发工具包,我们只要学会使用工具包中的各个工具即可,而使用这些工具的媒介就是我们已经学习完毕的C#程序语言。
软件下载和安装
软件下载
Unity官网(访问较慢)
中国官网
注册一个账号,然后下载。
版本选择
1、长期支持版:又称LTS版,适用于希望长时间保持稳定版本的用户。
2、补丁程序版:bug修复版本。
3、Beta版本:包含还未正式发布的新功能。
最新的不是最好的!不管是学习还是开发,都建议使用最稳定的版本。
注意:
一般情况下,Unity版本向下兼容,高版本开低版本工程,问题不大,低版本开高版本工程,会出现兼容问题。
关于版本号:
大版本号.小版本号.bug处理版本号(版本类型后缀) 例如:
2019.4.17f1
2017.2.4p1
2020.2.0b14
软件安装
1、点击“从Unity Hub下载”

2、获取许可证
①打开“偏好设置”

②点击“许可证”–>“添加许可证”–>“获取免费的个人版许可证”。

③在项目中为自己的项目选择合适位置。

④安装编辑器

勾选


工程文件夹
Assets: 工程资源文件夹(美术资源,脚本等)
Library: 库文件夹(Unity自动生成管理)
Logs: 日志文件夹,记录特殊信息(Unity自动生成管理)
obj: 编译产生中间文件(Unity自动生成管理)
Packages: 包配置信息(Unity自动生成管理)
ProjectSettings: 工程设置信息(Unity自动生成管理)
Unity界面基础
Scene场景和Hierarchy层级窗口
场景窗口和层级窗口是息息相关的,层级窗口中看到的内容就是场景窗口中的显示对象。
窗口布局:
推荐使用2 by 3布局

Hierarchy层级窗口:
我们可以在Hierarchy窗口中,创建或拖入各种游戏对象。比如:模型、光源、图片、UI等内容。层级窗口中显示的就是一个场景中的所有对象。
Scene场景窗口:
我们可以在Scene窗口中,查看所有游戏对象,设置所有游戏对象。

关于Unity中的3D世界坐标轴:
红色为X轴正向
绿色为Y轴正向
蓝色为Z轴正向
以屏幕为参照物,垂直屏幕向内为Z正方向,平行屏幕向右为X正方向,平行屏幕向上为Y正方向。


Game游戏和Project工程
Game游戏窗口: 游戏画面窗口,玩家能看到的画面内容。其中显示的内容,是场景中摄像机拍摄范围内的游戏对象。

Project工程窗口: 工程资源窗口,所有的工程资源都会在该窗口中显示,显示的内容为Assets文件夹中的所有内容,主要用来管理资源脚本文件。
默认文件夹Scenes:里面有一个默认空场景
Packages:官方拓展包
资源类型:
图片格式:jpg、png、tga
模型格式:fbx、max、maya
音效:wav、mp3、ogg
文本:txt、json、bytes
视频:mp4
Inspector和Console
Inspector检查窗口: 查看场景中游戏对象关联的C#脚本信息。

Console控制台窗口: 用于查看调试信息的窗口,报错、警告、测试打印都可以显示在其中。
默认未开启可以在Window->General中开启
或使用快捷键:Ctrl + Shift + C

工具栏和父子关系
工具栏
1、文件操作:新建工程、新建场景、工程打包等。
2、编辑操作:对象编辑操作相关,工程设置、引擎设置相关
3、资源操作:基本等同于Project窗口中右键相关功能。
4、对象操作:基本等同于Hierarchy窗口中右键相关功能。
5、脚本操作:Unity自带的脚本,可以添加各系统中的脚本。
6、窗口:可以打开Unity各核心系统的窗口。
7、帮助:检查更新,查看版本等等功能。
父子关系
1、子对象会随着父对象的变化而变化。
2、子对象Inspector窗口中Transform信息是相对父对象的。
3、Scene上方
的作用

Unity工作原理
反射机制和游戏场景
Unity引擎本质上是一个软件,使用它时是处于运行中的。我们是在一个运行中的软件里制作游戏的,Unity开发的本质就是在Unity引擎的基础上,利用反射和引擎提供的各种功能,进行的拓展开发。
场景中对象的本质是什么?
GameObject类对象是Unity引擎提供给我们的作为场景中所有对象的根本,在游戏场景中出现一个对象,不管是图片、模型、音效、摄像机等等都是依附于GameObject对象的。
Transform是什么?
GameObject对象作为一个出现在舞台(3D场景)中的演员,必须有一个表示自己所在位置的信息。Transform就是一个必不可少的剧本,它的本质就是发了一本表示位置的剧本给演员,用于设置和得到演员在世界中的位置角度缩放等信息。
反射机制的体现
除了Transform这个表示位置的标配剧本外,我们可以为这个演员(GameObject)关联各种剧本(C#脚本)让它按照我们剧本中(代码逻辑中)的命令来处理事情。而为演员添加剧本的这个过程,就是在利用反射new一个新的剧本对象和演员(GameObject)对象进行关联,让其按我们的命令做事。
例如:
1、修改Inspector面板中Transform的内容,前提是Unity帮助我们实现了对象查找和关联。
利用反射:已知对象,类名,变量名,通过反射为该对象设置变量值。
2、新建一个脚本后,添加给一个指定的GameObject对象。
利用反射:已知类名,可以获取所有公共成员,故可以在Inspector面板上创建各公共字段信息。
游戏场景基本知识点
1、游戏场景的保存
2、游戏场景的新建
3、多个游戏场景叠加显示
4、游戏场景的本质
游戏场景文件,后缀为.unity,它的本质就是一个配置文件,Unity有一套自己识别处理它的机制,但是本质就是把场景对象相关信息读取出来,通过反射来创建各个对象关联各个脚本对象。
预设体和资源包的导入导出
预设体:
将组合对象拖入Assest即可成为预设体。
资源包:
在project窗口中右键,点击import package或者export package进行导入导出。
Unity脚本基础
脚本基本规则
创建规则:
1、不在VS中创建脚本了。
2、可以放在Assets文件夹下的任何位置(建议同一文件夹管理)。
3、类和文件名必须一致,不然不能挂载(因为反射机制创建对象,会通过文件名去找Type)。
4、建议不要使用中文名命名。
5、没有特殊需求,不用管命名空间。
6、创建的脚本默认继承MonoBehavior。
MonoBehavior基类:
1、创建的脚本默认都继承MonoBehaviour继承了它才能够挂载在GameObject上。
2、继承了MonoBehavior的脚本不能new只能挂!
3、继承了MonoBehavior的脚本不要去写构造函数,因为我们不会去new它,写构造函数没有意义。
4、继承了MonoBehavior的脚本可以在一个对象上挂多个(如果没有加DisallowMultipleComponent特性)。
5、继承MonoBehavior的类也可以再次被继承,遵循面向对象继承多态的规则。
不继承MonoBehavior的类:
1、不继承Mono的类,不能挂载在GameObject上。
2、不继承Mono的类,想怎么写怎么写,如果要使用需要自己new。
3、不继承Mono的类一般是单例模式的类(用于管理模块)或者数据结构类(用于存储数据)。
4、不继承Mono的类,不用保留默认出现的几个函数。
脚本执行顺序:

默认脚本内容:
从这里打开可以修改默认脚本内容。
Editor\Data\Resources\ScriptTemplates
生命周期函数
帧的概念:
游戏的本质就是一个死循环,每一次循环处理游戏逻辑就会更新一次画面,之所以能看到画面在动是因为切换画面的速度到达一定时人眼就认为画面是流畅的,一帧就是执行一次循环。
Unity底层已经帮助我们做好了死循环,利用Unity生命周期函数做好的规则来执行我们的游戏逻辑。
fps(Frames Per Second):
即每秒钟帧数,一般我们说的60帧30帧,意思是1秒更新60次、30次画面。
1s = 1000ms
60帧:1帧为1000ms/60 ≈ 16.66ms
30帧:1帧为1000ms/30 ≈ 33.33ms
游戏卡顿的原因:
跑1帧游戏逻辑中的计算量过大,或者CPU不给力,不能在一帧的时间内处理完所有游戏逻辑。
生命周期函数的概念:
所有继承MonoBehavior的脚本,最终都会挂载到GameObject游戏对象上。生命周期函数就是该脚本对象依附的GameObject对象从出生到消亡整个生命周期中会通过反射自动调用的一些特殊函数。
Unity帮助我们记录了一个GameObject对象依附了哪些脚本,会自动的得到这些对象,通过反射去执行一些固定名字的函数。
生命周期函数的访问修饰符一般为private和protected,因为不需要在外部自己调用生命周期函数,都是Unity自己帮助我们调用的。
//出生时调用,类似构造函数,一个对象只会调用一次
void Awake()
{
//在Unity中打印信息的两种方式
//1、没有继承MonoBehavior类的时候
Debug.Log("123");
Debug.LogError("出错了");
Debug.LogWarning("警告");
//2、继承了MonoBehavior有一个线程的方法,可以使用
print("123");
}
//依附的GameObject对象每次激活时调用
void OnEnable()
{
}
//从自己被创建出来后,第一次帧更新之前调用,一个对象只会调用一次
void Start()
{
}
//物理帧更新,固定间隔时间执行,间隔时间可以设置
void FixedUpdate()
{
}
//逻辑帧更新,每帧执行
void Update()
{
}
//每帧执行,于Update之后执行
//一般用来处理摄像机位置更新相关内容的
void LateUpdate()
{
}
//依附的GameObject对象每次失活时调用
void OnDisable()
{
}
//对象销毁时调用,依附的GameObject对象被删除时
void OnDestroy()
{
}
生命周期函数继承多态。
为什么不建议在继承Mono的类写构造函数呢?
1.Unity的规则就是,继承MonoBehavior的脚本不能new只能挂载
2.生命周期函数的Awake是类似构造函数的存在,当对象出生就会自动调用
3.写构造函数反而在结构上会破坏Unity设计上的规范
不同对象的生命周期函数是在同一个线程中执行的吗?
Unity中所有对象上挂载的生命周期函数都是在一个主线程中按先后执行的。
理解:Unity会主动把场景上的对象,对象上挂载的脚本都统统记录下来,在主线程的死循环中,按顺序按时机的通过反射,执行记录的对象身上挂载的脚本的对应生命周期函数。
Inspector窗口可编辑的变量
Inspector显示的可编辑内容就是脚本的成员变量。
1、私有和保护无法显示编辑
2、让私有的和保护的也可以被显示
//加上强制序列化字段特性
[SerializeFiedld]
//所谓序列化就是把一个对象保存到一个文件或数据库字段中去
3、公共的可以显示编辑。
4、若使公共的也不让其显示编辑。
[HideInInspector]
5、大部分类型都能显示编辑。
6、让自定义类型可以被访问。
//加上序列化特性,字典怎样都不行
[System.Serializable]
一些辅助特性:
1、分组说明特性Header,为成员分组
[Header("分组说明")]
public int age;
public bool sex;
2、悬停注释Tooltip,为变量添加说明。
[Tooltip("说明内容")]
public int miss;
3、间隔特性Space,让两个字段间出现间隔。
[Space()]
public int crit;
4、修饰数值的滑条范围Range
[Range(最小值,最大值)]
public float luck;
5、多行显示字符串,默认不写参数显示3行,写参数就是对应行。
[Multiline(4)]
public string tips;
6、滚动条显示字符串,默认不写参数就是超过3行显示滚动条。
[TextArea(3,4)]
public string myLife;
7、为变量添加快捷方法ContexMenuItem。
//参数1:显示按钮名
//参数2:方法名,不能有参数
[ContextMenuItem("重置钱","方法名")]
public int money;
public void test()
{
money = 99;
}
8、为方法添加特性能够在Inspector中执行。
[ContextMenu("哈哈哈哈");
private void TestFun()
{
print("测试方法");
}
注意:
1、Inspector窗口中的变量关联的就是对象的成员变量,运行时改变他们就是在改变成员变量。
2、拖拽到GameObject对象后,再该表脚本中变量默认值,界面上不会改变。
3、运行中修改的信息不会保存。
MonoBehavior中的重要内容
重要成员:
1、获取依附的GameObject
print(this.gameObject.name);
2、获取依附的GameObject的位置信息,得到对象位置信息。
print(this.transform.position);//位置
print(this.transform.eulerAngles);//角度
print(this.transform.lossyScale);//缩放大小
this.gameObject.transform;
3、获取脚本是否激活
this.enabled = true;
重要方法:
得到依赖对象上挂载的其他脚本
1、得到自己挂载的单个脚本
//根据脚本名获取
this.GetComponent("Lesson3_Test");
//根据Type获取
this.GetComponent(typeof(Lesson3_Test));
//根据泛型获取,建议使用泛型获取,因为不用二次转换
this.GetCompoent<Lesson3_Test>();
2、得到自己挂载的多个脚本
Lesson3[] array = this.GetComponents<Lesson3>();
3、得到子对象挂载着的脚本(它默认也会找自己身上是否挂载该脚本)
//该参数是:默认不传为false,意思就是如果子对象失活是不会去找这个对象上是否有某个脚本的。
//如果为true即使失活也会找
this.GetComponentInChildren<Lesson3_Test>(false);
this.GetComponentsInChildren<Lesson3_Test>(true);
4、得到父对象挂载的脚本
this.GetComponentInParent<Lesson3_Test>();
5、尝试获取脚本
Lesson3_Test l3t;
if(this.TryGetComponent<

最低0.47元/天 解锁文章
35万+

被折叠的 条评论
为什么被折叠?



