GameSaveLoadScript
来源:互联网 发布:js获取json数组长度 编辑:程序博客网 时间:2024/06/04 00:42
原文链接:如何在Unity中保存并加载玩家的进度
http://www.manew.com/thread-98780-1-1.html
在本教程中,你会了解怎么实现简单的系统,一个创建和管理游戏的系统。我们会创建Final Fantasy般的主菜单框架,能够使玩家创建一个新的,独一无二的保存文件以及加载已经存在的。一些原则表明将允许你将他们扩展到任何需要你的游戏。
在本教程的最后,我们会学到这些:
Unity3D使用序列化来保存并加载游戏数据
在整个场景的变化过程中使用静态变量保存数据
注:在所有平台上除了网络播放器都使用这种方法保存和加载游戏数据。web播放器保存游戏数据的信息,可以看看官方文档and browser communication。
Let's Get Serial
我们将要做的第一件事就是创建一些代码,能够允许我们序列化游戏数据,将它转换一个格式,使其能够被保存后再恢复。为此,让我们创建一个C #脚本并命名为SaveLoad。这个脚本将处理所有的保存和加载功能。
我们会从其他脚本中引用这个脚本,所以让我们通过在public和class之间添加static,把它变成一个静态的类。让我们也删除:MonoBehaviour的一部分,因为我们不需要将它附加到一个游戏对象。因为它不再继承MonoBehaviour,让我们删除启动和更新功能。
最后的代码应该看起来像这样:
[AppleScript] 纯文本查看 复制代码
1
2
3
4
5
usingUnityEngine;
usingSystem.Collections;
publicstaticclassSaveLoad
{
}
现在,我们想要在这个脚本中添加一些新的函数,所以在usingSystem.Collections下面添加以下这些:
[AppleScript] 纯文本查看 复制代码
1
2
usingSystem.Collections.Generic;
usingSystem.Runtime.Serialization.Formatters.Binary;
usingSystem.IO;
第一行允许我们使用C #创建的动态列表,但这是不必要的序列化。第二行我们能够使用脚本中的操作系统的序列化功能。在第三行中,IO代表输入/输出,并允许我们从计算机或移动设备上写和读。换句话说,这条线允许我们创建独特的文件,然后从这些文件中读取。
现在我们准备序列化一些数据。
Making SerializableClasses 创建序列化类
现在我们脚本已经有序列化的能力,我们要创建一些被序列化的类。如果考虑简单的RPG游戏,例如最终幻想,它为玩家提供了创建和加载不同的游戏保存方式。因此,创建一个新的C #脚本并命名为Game,给它一些变量来保存三个对象:一个knight,一个rogue,和一个wizard。改变脚本的代码,最后使其看起来像这样:
[AppleScript] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
usingUnityEngine;
usingSystem.Collections;
[System.Serializable]
publicclassGame
{
publicstaticGame current;
publicCharacter knight;
publicCharacter rogue;
publicCharacter wizard;
publicGame
(
)
{
knight
=
newCharacter
(
)
;
rogue
=
newCharacter
(
)
;
wizard
=
newCharacter
(
)
;
}
}
[System.Serializable]这行告诉Unity脚本可以被序列化,换句话说,我们在这个脚本可以保存所有的变量。根据官方文档,Unity可以序列化以下类型:
- 所有简单的数据类型
- 一些内建类型(包括Vector2, Vector3, Vector4, Quaternion, Matrix4x4, Color, Rect,以及LayerMask)
- 继承于UnityEngine.Object的所有类 (包括GameObject, Component, MonoBehavior, Texture2D, 以及 AnimationClip )。
- Enums. 枚举
- Arrays and lists of a serializable type. 数组以及序列类型的清单
第一个变量,current是对Game实例的静态引用。当我们创建或者加载一个游戏,我们将把静态变量设置为独有的游戏实例,以便于我们从工程的任何地方引用这个变量。通过使用静态变量和函数,我们不必要使用一个gameObject的GetComponent()函数。
Notice that it'sreferencing something called a Character? Wedon't have that yet, so let's create a new script to house this class, and callit Character:
注意它引用的是一个被称为Character的事物?我们还没有它,让我们创建一个新的脚本来管理这个类,并命名为Character:
[AppleScript] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
usingUnityEngine;
usingSystem.Collections;
[System.Serializable]
publicclassCharacter
{
publicstringname;
publicCharacter
(
)
{
this.
name
=
""
;
}
}
你可能会想知道,如果我们只是存储一个字符串变量,为什么需要一个全新的类。事实上,我们可以取代在Game 脚本中使用string代替character。但我想告诉你,这个方法能怎么用:你可以引用其他类来保存和加载类,等等,只要各个类已经序列化。
现在,我们的类设置为可以保存和加载的,让我们跳回到我们的SaveLoad 脚本并添加保存游戏的能力。
Saving a Game's State保存一种游戏状态
一个"Load Game"菜单通常会展示保存好的游戏清单,所以让我们创建一个列表类型的游戏并命名为savedGames。使它成为static List类型,这样我们的项目中只有一个保存的游戏列表。代码应该看起来像这样:
[AppleScript] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
usingUnityEngine;
usingSystem.Collections;
usingSystem.Collections.Generic;
usingSystem.Runtime.Serialization.Formatters.Binary;
usingSystem.IO;
publicstaticclassSaveLoad
{
publicstaticList
<
Game
>
savedGames
=
newList
<
Game
>
(
)
;
}
接下来,让我们创建一个新的静态函数来保存游戏:
[AppleScript] 纯文本查看 复制代码
1
2
3
4
5
6
publicstaticvoidSave
(
)
{
savedGames.Add
(
Game.current
)
;
BinaryFormatter bf
=
newBinaryFormatter
(
)
;
FileStream
file
=
File.Create
(
Application.persistentDataPath
+
"/savedGames.gd"
)
;
bf.Serialize
(
file
,
SaveLoad.savedGames
)
;
file
.Close
(
)
;
}
第2行将我们当前的游戏添加到保存的游戏列表中。这个名单是我们要序列化的。为此,我们首先需要创建一个新的BinaryFormatter,它将处理序列化工作。这是第3行做的。
第四行,我们正在创建一个FileStream,它本质上是一个新文件的路径,我们可以发送数据 ,就像鱼在河下游泳。我们使用File.Create()来创建一个新文件,它的位置作为我们传过去的参数。 Unity有一个内置的location来存储我们的游戏文件(即基于游戏平台自动更新),我们可以参考使用Application.persistentdatapath。
由于我们正在创建一个新文件,但是,我们不能仅仅只说文件在哪里,我们也必须用实际文件本身的名称来关闭这个路径。这个文件有两个部分:
- 文件名字
- 文件类型
我们将使用savedgames作为文件名,我们会使用自定义数据类型gd(“游戏数据”)作为文件类型。我们的结果在设定位置application.persistentdatapath的游戏文件savedgames.gd中。(将来,你可以使用这个数据类型保存其他类型的东西;例如,你可以将用户选项设置保存为options.gd。)
注意:你可以使用任何你想要的文件类型。例如,the Elder Scrolls系列使用.esm作为文件类型。你也可以简单的保存为savedgames.baconandgravy。
第5行中,我们调用BinaryFormatter函数的Serialize功能将savedGames列表保存到我们的新文件中。之后,在第6行关闭创建的文件。
我们的游戏保存好了。
Loading a Game's State加载一种游戏状态
在Save函数,我们在一个特定的位置序列化已保存的游戏列表。相反,加载游戏的代码应该是这样的:
[AppleScript] 纯文本查看 复制代码
1
2
3
4
5
6
7
publicstaticvoidLoad
(
)
{
if
(
File.Exists
(
Application.persistentDataPath
+
"/savedGames.gd"
)
)
{
BinaryFormatter bf
=
newBinaryFormatter
(
)
;
FileStream
file
=
File.Open
(
Application.persistentDataPath
+
"/savedGames.gd"
,
FileMode.Open
)
;
SaveLoad.savedGames
=
(
List
<
Game
>
)
bf.Deserialize
(
file
)
;
file
.Close
(
)
;
}
}
在第2行中,我们检查保存的游戏文件是否存在.。(如果没有,很明显没有东西可以加载。)在3行,使用处理Save函数的相同方式来创建一个BinaryFormatter。第4行中,我们创建一个FileStream,但是这一次,我们目标从文件流相反方向移动。因此,我们使用file.Open,并表明savedgames.gd存在的地方使用相同的application.persistentdatapath字符串。
第五行有点多,所以让我们展开他
- bf.Deserialize(文件)回调在我们上面指定位置找到文件并反序列化它。
- 我们不能只是在Unity中指望二进制并期望它工作,但是,(将我们反序列化文件转换(计算)成我们想要的数据类型,在这种情况下它是一个列表的类型
- 然后将列设置为我保存的游戏列表。
最后,在第六行,和在Save函数里做过得一样,以同种方式关闭文件。
注:你转换反序列化的数据类型可以根据你的需要改变。例如,Player.lives = (int)bf.Deserialize(file)。
Conclusion 结论
我们的SaveLoad脚本已经完成,应该像这样:
这是保存和加载Unity的基础知识.。在the attachedproject file中,你会发现一些其他脚本,展示我如何处理调用这些函数,以及如何使用Unity的GUI来显示数据.。
如果你需要让你你的游戏开发有一些优势,可在Envato市场尝试Unity3D templates。
0 0