组件
RigidBody
刚体,会给物体增加重力
spring joint:
弹簧关节,可以连接两个刚体,使得两个物体能够像弹簧一样运动。
Box Collision
增加碰撞检测
图片渲染器
Sprite精灵,游戏开发中指一张图片
- Sprite Render 图片渲染器,是用来渲染图片的组件
1 | // 随机生成怪物头像 |
所以图片对象其实是, Empty Gameobject+Sprite Render组件构成的
注:UI下的Image不是Sprite
API:
Transform
Translate()
根据
translation
的方向和距离移动变换。如果relativeTo
被省略或设置为 Space.Self,则会相对于变换的本地轴来应用该移动。(在场景视图中选择对象时显示的 X、Y 和 Z 轴。) 如果relativeTo
为 Space.World,则相对于世界坐标系应用该移动。
Rotate
使用 Transform.Rotate 以各种方式旋转 GameObjects。通常以欧拉角而不是四元数提供旋转。
获得键鼠操作
获取鼠标:
1 | Input.GetMouseButton(int) |
获取方向键盘:
1 | Input.Getkey(KeyCode.UPArrow) 上键 |
获得对象上的组件
- 每个组件上都有transform组件,因此在scripts脚本中可以通过
transform.position
和transform.rotation
来获得位置和朝向。 - 获得对象下的刚体组件:
Rigidbody rd = bullet.GetComponent<Rigidbody>();
镜头跟随——移动摄像头位置
Camera.main.transform.position = Vector3.Lerp( Camera.main.transform.position, new Vector3(Mathf.Clamp(posX, 0, 15), Camera.main.transform.position.y, Camera.main.transform.position.y,), smooth* Time.deltaTime)
注:被挂载的脚本也算个组件,其名称为脚本名称,如下GetComponent<Bird>
的Bird为挂载的Bird.cs脚本
1 | collision.transform.GetComponent<Bird>().Hurt(); |
获得脚本挂载的对象以及上级对象
1 | // 在脚本中transform为脚本挂载对象的transform组件 |
有获得父对象就有获得子对象
1 | for (int i = 0; i < transform.childCount; i ++ ){ |
脚本获得对象:
-
public Text TimeText
将对象通过public暴露,然后手动拖拽指定 -
private Text TimeText
指定为private,然后Aware()
中TimeText = GameObject.Find("TimeText").GetComponent<Text>();
1.无法查找隐藏对象
- 隐藏对象包括查找路径的任何一个父节点隐藏(active=false)
- ▲:解决方案,可以先让它设置为active=true,然后在start中找到后设置为active=false,再在用的时候设置为true
2.如果查找不在最上层,建议合理使用路径查找,路径查找是把双刃剑
**优点1:**解决查找中可能出现的重名问题。
**优点2:**如果有完全的路径,减少查找范围,减少查找时间。注:与GameObject.Find相似的api还有GameObject.FindWithTag
-
Transform.Find
1.可以查找隐藏对象
2.支持路径查找
3.查找隐藏对象的前提是transform所在的根节点必须可见,即active=true
实际开发中会将功能预制体放到一个可见的GameObject目录下,将这个GameObject目录作为查找根节点,下面的所有对象(隐藏、非隐藏)都可以查找到。
SetActive和enable区别
相同点:
- gameObject.SetActive函数控制的是上图复选框1是否勾选,不勾选,那么隐藏,勾选即显示;
- enabled属性控制的是复选框2是否勾选,显隐规则同上;
不同点:
- SetActive是针对元素对象gameObject的;enabled是针对gameObject下的某个component的
- 如果UI的复选框1默认不勾选, 无论复选框2是否勾选, 那么当UI显示时, MyImage.cs的所有函数都不会执行, 这就说明没有加载此脚本到内存;
- 如果UI的复选框1默认勾选,复选框2默认不勾选,那么当UI显示时, MyImage.cs的Awake函数会执行,其他函数均不会执行,这就说明此脚本会加载到内存中, 除了执行Awake函数外,其他函数均不执行.
1 | // enable |
本地持久化保存与读取的类
PlayerPrefs: 工作原理非常简单,以键值对的形式将数据保存在文件中,然后程序可以根据这个名称取出上次保存的数值。
Playerprefs静态方法
- SetFloat(),SetInt(),SetString()` 写入数据
GetFloat(),GetInt(),GetString()
读取数据DeleteKey(),DeleteAll()
删除数据HasKey("SS")
检查数据,是否有该键Save()
创建和销毁prefab对象
1 | // 通过预制体来动态创建实例对象, Instantiate参数有很多, 具体见api文档 |
场景切换
Unity游戏开发中,单个Scene解决所有问题似乎不可能,那么多个Scene之间的切换是必然存在。如果仅仅是切换,似乎什么都好说,但是在场景比较大的时候不想让玩家等待加载或者说场景与场景之间想通过一些画面、动画表现出一些让玩家期待的东西,大家就要去认真考虑。这篇文章主要介绍两种增加切换中如何播放画面或者动画等等,提高玩家的浸入感,当然你也可以做成无缝的场景。
1 | // 异步切换场景 |
重玩功能:可以通过切换到当前场景来实现,由于切换会把切之前的元素销毁掉,并重新建新的元素,因此相当于重玩
游戏暂停
设置Time.timeScale = 0 将会暂停所有和帧率有关的事情。这些主要是指所有的物理事件和依赖时间的函数、刚体力和速度等,而且FixedUpdate会受到影响,会被暂停(不是Update),即timeScale =0 时将不会调用FixedUpdate函数了。
(1)Time.timeScale = 0可以暂停游戏,Time.timeScale = 1恢复正常,但这是作用于整个游戏的设置,不单单是当前场景,记得在需要的时候重置回Time.timeScale = 1。当然也可以使用Time.timeScale来做游戏的1倍、2倍整体加速。
1 |
|
碰撞检测
碰撞体的编辑
点εEdit collider进行编辑…,规定可碰撞的范围和形状
常见的形状:
- 方形 Box Collider2D
- 圆形 Circle collider2D
- 不规则边缘 Edge Collider2D
- 胶囊形状 Capsule Collider2D
-
带有collider组件的对象脚本,将组件的IsTrigger属性勾选上
1
2
3
4
5
6
7
8
9
10
11
12
13
14// 开始接触
void OnTriggerEnter(Collider collider) {
Debug.Log("开始接触");
}
// 接触结束
void OnTriggerExit(Collider collider) {
Debug.Log("接触结束");
}
// 接触持续中
void OnTriggerStay(Collider collider) {
Debug.Log("接触持续中");
} -
带有collider组件的对象脚本,发生碰撞时会执行如下钩子函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15// 碰撞开始
void OnCollisionEnter(Collision collision) {
// 销毁当前游戏物体
Destroy(this.gameObject);
}
// 碰撞结束
void OnCollisionExit(Collision collision) {
}
// 碰撞持续中
void OnCollisionStay(Collision collision) {
}
两者的区别在于,将对象collider组件的isTriiger属性勾上后,游戏物体发生接触的时候就不会有碰撞的效果了,而是会直接穿过去,即碰撞逻辑需要我们自己手写了。
【值得注意的是,触发器回调的这三个方法的参数都是Collider类型,表示的就是被碰撞的游戏物体的触发器组件对象。】
1 | // 获得被碰撞物体的name |
Resources.Load动态加载资源
使用这种方式加载资源,首先需要下Asset目录下创建一个名为Resources的文件夹,这个命名是U3D规定的方式,然后把资源文件放进去,Cube放在Resource中的Prebs中,而Sphere放在Resources跟目录下
1 | private string cubePath = "Prebs/MyCubePreb"; |
DontDestroyOnLoad
新场景的负载会破坏所有当前场景对象。调用Object.DontDestroyOnLoad在级别加载期间保存对象。如果目标对象是组件或游戏对象,Unity还将保留Transform的所有子对象。对象.DontDestroyOnLoad不返回值。使用typeof操作符更改参数类型。
建议把需要DontDestroyOnLoad的游戏对象放到一个在游戏逻辑中不会返回的一个场景,比如说放到登录时加载的那个场景,,,或者代码使用一个静态变量做标志,(static bool isHave )是否DontDestroyOnLoad过,若DontDestroyOnLoad就将其赋值为True,
想要找到这个游戏物体的话,搜索Find 是可以找到的,或者使用标签的形式FindGameObjectWithTag
1 | // 登陆页面的Canvas挂载的必启动文件 |
问题:
-
Unity:You must exit play mode to save the scene
A: 出现上述错误时,通常是处于游戏模式也就是play mode的状态下进行保存操作,此时无法完成保存指令。
点击运行后,需要等待几秒才能正式进入Play Mode,进入后可以看到Run按钮变蓝,要退出的话不是点击Pause,而是再次点击变蓝的Run按钮(Pause是暂停)
- 可以加深Play Mode的观感——Unity小技巧——编辑模式Play Mode指定颜色,我是选择了加深灰色,使得有沉浸感的体验。
-
Visual Studio没有Unity的代码提示——unity脚本在vs2019中打开没有智能提示完美解决方案,将VS加上“使用Unity游戏开发”的选项即可。
渲染顺序:
简单总结一下,
-
决定Sprite render的渲染关系的层级顺序是:
- Camera: 不同的Camera的Depth
- sorting layer: 相同Camera下的不同SortingLayer
- sortingorder: 相同SortingLayer下的不同Z轴/Order in Layer
-
改变控件之间的层级关系
(1)同一canvas下:
改变控件transform的SiblingIndex,
transform.GetSiblingIndex();
transform.SetSiblingIndex(int index); //index值越大,越后渲染,层级越大,越显示在前面
(2)不同Canvas下:
设置Canvas下的Sort Order //Sort Order值越大,越后渲染,层级越大,越显示在前面
学习参考视频:
- B站,Unity2021入门教程_游戏开发100集课程(含建模)——间接明了的demo展示,内含飞机大战
- 案例学习网站-sikiedu:
- 基础案例——小球发射
- Unity初级案例 - 愤怒的小鸟
- Unity初级案例 - 炸弹人
- Unreal初级案例 - 3D吃豆人
- Unity初级案例 - 贪吃蛇(Unity2017.2.0)
- 【游戏开发】unity项目案例《黄金矿工》
- 绳子的state通过gameManager来控制
- 绳子自己没有trigger,而是写在ore上了,当碰撞时设置ore的parent为rope
官方API文档
免费的素材网站
Author: Mrli
Link: https://nymrli.top/2021/12/16/Unity游戏开发学习/
Copyright: All articles in this blog are licensed under CC BY-NC-SA 3.0 unless stating additionally.