Unity-实现功能
游戏全局
进入游戏
进入游戏的第一个界面,应该放置多个按钮,以供玩家选择是否开始游戏、退出游戏。
GameManager - 游戏管理器
用来控制游戏的整体进程,以及界面文本、按钮的功能实现。 也常用于记录各种需要在整个游戏过程中持久化的数据。
GameManager 的用处:
- 整个游戏过程中有且仅有一个 GameManager,且位于场景的根目录
- 在 GameManager 里会有一个叫 Value 的整型变量,记录当前场景。
- 切换游戏场景的时候 GameManager 不能被销毁
- 每一个场景中都会有一个按钮,点击后会跳转到另一场景,并且对 GameManager.Value 进行 +/- 1 操作
使用 DontDestroyOnLoad() 方法让 GameManager
在切换游戏场景的时候不会被销毁,且只会存在一个GameManager:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20public class GameManager : MonoBehaviour
{
public static GameManager Instance { get; private set; }
public int Value { get; set; } = 0;
private void Awake()
{
// 单例模式核心,↓↓↓
if (Instance == null)
{
Instance = this;
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
}
// ↑↑↑
}
}
开始游戏
1 | using UnityEngine; |
退出游戏
分为两种情况:
- 使用Unity调试时
UnityEditor.EditorApplication.isPlaying = false;
- 打包发布后
Application.Quit();
## 数据保存 ### JsonUtility1
2
3
4
5
6
7
8
9
10
11
12using UnityEngine;
public class GameMenu : MonoBehaviour {
public void OnExitGame()
{
UnityEditor.EditorApplication.isPlaying = false;
Application.Quit();
}
}#### JsonUtility.ToJson - 生成 JSON 格式的对象数据 public static string ToJson (object obj); public static string ToJson (object obj, bool prettyPrint);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36/// <summary>
/// 需要保存的JSON数据表
/// </summary>
[ ]
class SaveData
{
public int score;
}
/// <summary>
/// 保存数据,使用JSON格式保存
/// </summary>
public void SaveScore()
{
SaveData data = new SaveData();
data.score = BestScore;
string json = JsonUtility.ToJson(data);
File.WriteAllText(Application.persistentDataPath + "/savefile.json", json);
}
/// <summary>
/// 读取数据,读取JSON文件的内容
/// </summary>
public void LoadScore()
{
string path = Application.persistentDataPath + "/savefile.json";
if (File.Exists(path))
{
string json = File.ReadAllText(path);
SaveData data = JsonUtility.FromJson<SaveData>(json);
BestScore = data.score;
}
}
obj | 要转换为 JSON 形式的对象。 |
---|---|
prettyPrint | 如果为 true,则格式化输出以实现可读性。如果为 false,则格式化输出以实现最小大小。默认为 false。 |
返回值:string JSON 格式的对象数据。 描述:生成 对象的公共字段 的 JSON 表示形式。 #### JsonUtility.FromJson - 以JSON 格式的数据创建对象 public static T FromJson (string json);
json | 对象的 JSON 表示形式。 |
---|
返回值:T 对象的实例。 描述:通过 JSON 表示形式创建对象。(对象的数据格式应与源数据格式一致,即转换成 JSON 表示形式之前的对象数据格式) #### JsonUtility.FromJsonOverwrite - 以JSON 数据形式覆盖对象数据 public static void FromJsonOverwrite (string json, object objectToOverwrite);
json | 对象的 JSON 表示形式。 |
---|---|
objectToOverwrite | 应覆盖的对象。 |
描述:通过读取对象的 JSON 表示形式覆盖其数据。 此方法非常类似于 JsonUtility.FromJson,只是它将 JSON 数据加载到现有对象中,而不是创建新对象并将 JSON 数据加载到其中。这样,无需进行任何分配即可更新存储在类或对象中的值。 ### 数据保存目录 #### Application.persistentDataPath - 持久性数据目录路径 此值是一个目录路径,您可以在其中存储要在运行之间保留的数据。在 iOS 和 Android 上发布时,persistentDataPath 指向设备上的公共目录。应用更新不会擦除此位置中的文件。用户仍然可以直接删除这些文件。
构建 Unity 应用程序时,将生成一个基于捆绑标识符的 GUID。此 GUID 是
persistentDataPath
的一部分。如果在将来的版本中保留相同的捆绑标识符,则应用程序在每次更新时都会继续访问相同的位置。
1
string persistentUrl = $"{Application.persistentDataPath}/{this.localInfoName}"; //持久化地址
Windows Store Apps: Application.persistentDataPath 指向 %userprofile%<productname>。
Windows Editor 和 Standalone Player: Application.persistentDataPath 通常指向 %userprofile%<companyname><productname>。如果前者不可用,则由带有 FOLDERID_LocalAppDataLow 的 SHGetKnownFolderPath 或带有 CSIDL_LOCAL_APPDATA 的 SHGetFolderPathW 解决。
WebGL: Application.persistentDataPath
指向 /idbfs/
Linux: Application.persistentDataPath 指向 $XDG_CONFIG_HOME/unity3d 或 $HOME/.config/unity3d。
iOS: Application.persistentDataPath
指向 /var/mobile/Containers/Data/Application/
tvOS: 不支持 Application.persistentDataPath 并返回空字符串。
Android: Application.persistentDataPath
在大多数设备上指向
/storage/emulated/0/Android/data/
Mac: Application.persistentDataPath 指向用户库文件夹(这个文件夹通常是隐藏的)。在最近的 Unity 版本中,用户数据被写入 ~/Library/Application Support/company name/product name。旧版本的 Unity 写入 ~/Library/Caches ,或 ~/Library/Application Support/unity.company name.product name. 这些文件夹都是 Unity 搜索的。该应用程序会查找并使用系统上包含所需数据的最旧文件夹。
角色控制
- Rigidbody.velocity 直接给物体设定速度,适合物理类移动
- transform.Translate 适合非物理的移动,难以控制边界限制问题,俗称“卡墙里”。
- Rigidbody.Force 给物体施加力的作用,适合物理类移动
- 角色控制器
- Rigidbody.MovePosition 直接改变物体的位置,适配了物理碰撞
- transform.Position 直接改变物体的位置,适合非物理碰撞的移动
移动
跳跃
游戏细节
基于轴心的排序图层渲染顺序
物理系统 - 刚体与碰撞体之间的关系
案例 不需要移动的物体,可以只加碰撞体,用于处理交互; 需要移动的物体,则需要刚体支持。
瓦片地图碰撞和复合器
添加瓦片地图碰撞
## 角色受伤后的无敌时间 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float timeInvincible = 2.0f;
bool isInvincible;
float invincibleTimer;
void Update()
{
if (isInvincible)
{
invincibleTimer -= Time.deltaTime;
if (invincibleTimer < 0)
isInvincible = false;
}
}
public void ChangeHealth(int amount)
{
if (amount < 0)
{
if (isInvincible)
return;
isInvincible = true;
invincibleTimer = timeInvincible;
}
currentHealth = Mathf.Clamp(currentHealth + amount, 0, maxHealth);
}
}
Update 函数 在 Update 函数中,如果 玩家 处于无敌状态,则从计时器减去 deltaTime。这实际上是在倒计时。当该时间小于或等于零时,计时器结束,玩家 的无敌状态也结束,因此通过将 bool 重置为 false 来消除她的无敌状态。这样,下次调用 ChangeHealth 来伤害 玩家 时,你就不会提前退出并再次伤害她、重置她的无敌状态等等。
使UI绑定到某个对象上,而不是屏幕上
案例 - 附加在对象上的Canvas - Ruby's Adventure 2D 比如:你需要让对话框显示在一个角色上方的一个小框中。这意味着画布将存在于世界(world space)中,位于头顶上方,而不是始终叠加在屏幕固定位置上。 ## 2D游戏中的各种平台 基础平台、单向可穿越平台、移动平台等;并且可相互组合。
可使用 2D 平台效应器 (Platform Effector 2D)来实现某些平台的功能。