在 Sprite Kit 中将数据存储在 plist 中与在场景编辑器中设置数据有什么区别?
What is the difference between storing data in plist vs setting up data in scene editor in Sprite Kit?
问这个问题似乎不是一个明智的问题,但我心中有些困惑,我想澄清一下。在Apple的2d游戏框架Sprite kit中,通常建议将节点相关的数据存储在Plist中,然后在代码中需要时检索。我没有得到的是,在使用 .sks 场景编辑器时,您有机会在属性 inspector.Or 中设置和存储与节点相关的数据,我误解了吗?通过属性检查器使用 .sks 场景编辑器,这两种方法或设置与节点相关的数据有什么区别不会存储在任何地方,只能动态访问。如果有人能说明这两种方法之间的明显区别,我将不胜感激。我试图寻找它,但没有得到任何帮助。
我最近开始在游戏的各个方面使用场景编辑器。不仅是场景,还有创建复杂的 SKSPriteNode 对象、模块化弹出窗口等。它大部分都很棒,而且比尝试在代码中布局对象要快得多。
所以如果我能将所有数据保存在 sks 文件中就更好了。
是的,你是对的,你可以在场景编辑器中设置和存储与节点相关的数据。它位于用户数据下的属性检查器中。
您还可以将该信息存储在 Plist 文件中。然而,这两种方法之间的一个很大区别是,如果将数据存储在 Plist 文件中,则必须对数据进行排序并找到相关数据并将其绑定到节点。使用用户数据时,数据已经绑定到节点并随它一起使用,因此您以后不必再找到它来关联它。
来自 Apple.
You use this property to store your own data in a node. For example,
you might store game-specific data about each node to use inside your
game logic. This can be a useful alternative to creating your own node
subclasses to hold game data. SpriteKit does not do anything with the
data stored in the node. However, the data is archived when the node
is archived.
这是一个示例,说明访问从 sks 文件存储的用户数据是多么容易
if let userData = redVillian.userData {
if let hitPoints = userData.object(forKey: "hitPoints") as? Int {
redVillain.hitPoints = hitPoints
}
if let name = userData.object(forKey: "name") as? String {
redVillian.name = name
}
}
您也可以在代码中设置用户数据
redVillian.userData = ["hitPoints": 5, "name" : "Herbert"]
或在代码中修改
redVillian.userData?.setValue("Eleanor", forKey: "name")
我认为你应该在这件事上简单一点。 PList 非常适合存储更通用的数据。比如游戏设置等。如果需要存储与节点直接相关的数据,则使用节点的用户数据。
重要的是要了解,在游戏中,比方说,生成敌人,您could/should将关于不同敌人类型的信息存储在一个列表。
当生成敌人时,它们将具有不同的属性,这将使它们独一无二,即使它们是同一类型的。它可以是颜色、生命值、级别等。如果您需要序列化并保存数据供以后使用,它应该放在用户数据中。
根据我刚才所说的,我不知道,在性能方面,当涉及到变化很大的数据(例如健康点数)时,用户数据是否非常有效。我觉得在那种情况下,使用自定义 class 并添加属性来存储该数据可能会使事情变得更快,但在这种情况下,如果您需要序列化数据,则必须实施 NSCoding 协议。
编辑
根据您的评论,这里有一些说明:
如果您只在 xCode 的场景编辑器中处理您的场景,那么您可能看不到用户数据和使用 plist 之间的真正区别。如果您从不通过代码创建精灵,那么它并不明显。
为什么要 plists?
如果您通过代码创建角色,那么使用 plist 来存储 "model information" 可能会很有趣。正如您提到的,Apple 制作的关于 SpriteKit 最佳实践的视频演示正在谈论在 plist 中存储锚点、位置、比例等信息。例如,如果您正在制作 space 飞船游戏,您可能希望拥有不同的 space 飞船模型。它们可能具有非常不同的形状,因此您可能不希望它们围绕同一点旋转以使其看起来不错。它们还将具有不同的材质和不同的统计数据(最大生命值、最大护盾等)。然后在 plist 中你可以存储这样的东西:
- 舰模1
- 质地:ship1.png
- 锚点:(0.5, 0.5)
- 最大健康:100
- 最大护盾:100
- ...
- 舰模2
- 质地:ship2.png
- 锚点:(0.2, 0.5)
- 最大健康:150
- 最大护盾:200
- ...
- ...
如果您与绘图师一起工作,他可以很容易地编辑 plist 而无需参与 xCode。所以当他的图形准备好后,他可以自己填写关于纹理和锚点(例如)的信息,让游戏设计师添加其他统计数据等
然后,如果您在代码中创建一艘船,只需从 plist 中检索信息即可创建具有所有正确设置的新船。
随着时间的推移,图形师可以更新 plist 中的图形和相关信息,您甚至不需要重新编译来测试新内容。您甚至可以在获得图形之前使用通用图片(或在未提供图片时使用纯色)来开发功能 material.
为什么要使用 UserData?
您的 space 飞船已创建,您正在为自己的生命而战。在某些时候,有人会受伤,你需要跟踪它。您可以使用变量轻松完成此操作,但是如果您想使用 NSCoder 来保存您的游戏状态,则必须手动完成。
如果您存储有关精灵的特定信息,则 UserData 是关键。它仅特定于 THAT 节点。当您使用 NSCoder 保存您的游戏状态时,它也会与所有其他内容一起保存。
这是准时的数据。在游戏过程中,生命值会发生很大变化,但是当您加载上次保存时,您希望与您战斗的老板像您保存时一样受到伤害。所以它是准时的,但坚持不懈。它只与那个节点有关。因此将其存储在节点本身中是有意义的。
表演
与您可能担心性能的任何事情一样。如果你有数百个精灵不停地受伤和治疗,如果你一直更新用户数据,它可能会出现瓶颈。如果你到了那个地步,你可能会考虑从 SKSpriteNode subclassing,添加一个变量来跟踪健康等,而不是直接处理 NSCoder 的东西,只需提交你的变量的内容当你需要保存它时到 userData。
问这个问题似乎不是一个明智的问题,但我心中有些困惑,我想澄清一下。在Apple的2d游戏框架Sprite kit中,通常建议将节点相关的数据存储在Plist中,然后在代码中需要时检索。我没有得到的是,在使用 .sks 场景编辑器时,您有机会在属性 inspector.Or 中设置和存储与节点相关的数据,我误解了吗?通过属性检查器使用 .sks 场景编辑器,这两种方法或设置与节点相关的数据有什么区别不会存储在任何地方,只能动态访问。如果有人能说明这两种方法之间的明显区别,我将不胜感激。我试图寻找它,但没有得到任何帮助。
我最近开始在游戏的各个方面使用场景编辑器。不仅是场景,还有创建复杂的 SKSPriteNode 对象、模块化弹出窗口等。它大部分都很棒,而且比尝试在代码中布局对象要快得多。
所以如果我能将所有数据保存在 sks 文件中就更好了。
是的,你是对的,你可以在场景编辑器中设置和存储与节点相关的数据。它位于用户数据下的属性检查器中。
您还可以将该信息存储在 Plist 文件中。然而,这两种方法之间的一个很大区别是,如果将数据存储在 Plist 文件中,则必须对数据进行排序并找到相关数据并将其绑定到节点。使用用户数据时,数据已经绑定到节点并随它一起使用,因此您以后不必再找到它来关联它。
来自 Apple.
You use this property to store your own data in a node. For example, you might store game-specific data about each node to use inside your game logic. This can be a useful alternative to creating your own node subclasses to hold game data. SpriteKit does not do anything with the data stored in the node. However, the data is archived when the node is archived.
这是一个示例,说明访问从 sks 文件存储的用户数据是多么容易
if let userData = redVillian.userData {
if let hitPoints = userData.object(forKey: "hitPoints") as? Int {
redVillain.hitPoints = hitPoints
}
if let name = userData.object(forKey: "name") as? String {
redVillian.name = name
}
}
您也可以在代码中设置用户数据
redVillian.userData = ["hitPoints": 5, "name" : "Herbert"]
或在代码中修改
redVillian.userData?.setValue("Eleanor", forKey: "name")
我认为你应该在这件事上简单一点。 PList 非常适合存储更通用的数据。比如游戏设置等。如果需要存储与节点直接相关的数据,则使用节点的用户数据。
重要的是要了解,在游戏中,比方说,生成敌人,您could/should将关于不同敌人类型的信息存储在一个列表。 当生成敌人时,它们将具有不同的属性,这将使它们独一无二,即使它们是同一类型的。它可以是颜色、生命值、级别等。如果您需要序列化并保存数据供以后使用,它应该放在用户数据中。
根据我刚才所说的,我不知道,在性能方面,当涉及到变化很大的数据(例如健康点数)时,用户数据是否非常有效。我觉得在那种情况下,使用自定义 class 并添加属性来存储该数据可能会使事情变得更快,但在这种情况下,如果您需要序列化数据,则必须实施 NSCoding 协议。
编辑
根据您的评论,这里有一些说明:
如果您只在 xCode 的场景编辑器中处理您的场景,那么您可能看不到用户数据和使用 plist 之间的真正区别。如果您从不通过代码创建精灵,那么它并不明显。
为什么要 plists?
如果您通过代码创建角色,那么使用 plist 来存储 "model information" 可能会很有趣。正如您提到的,Apple 制作的关于 SpriteKit 最佳实践的视频演示正在谈论在 plist 中存储锚点、位置、比例等信息。例如,如果您正在制作 space 飞船游戏,您可能希望拥有不同的 space 飞船模型。它们可能具有非常不同的形状,因此您可能不希望它们围绕同一点旋转以使其看起来不错。它们还将具有不同的材质和不同的统计数据(最大生命值、最大护盾等)。然后在 plist 中你可以存储这样的东西:
- 舰模1
- 质地:ship1.png
- 锚点:(0.5, 0.5)
- 最大健康:100
- 最大护盾:100
- ...
- 舰模2
- 质地:ship2.png
- 锚点:(0.2, 0.5)
- 最大健康:150
- 最大护盾:200
- ...
- ...
如果您与绘图师一起工作,他可以很容易地编辑 plist 而无需参与 xCode。所以当他的图形准备好后,他可以自己填写关于纹理和锚点(例如)的信息,让游戏设计师添加其他统计数据等
然后,如果您在代码中创建一艘船,只需从 plist 中检索信息即可创建具有所有正确设置的新船。
随着时间的推移,图形师可以更新 plist 中的图形和相关信息,您甚至不需要重新编译来测试新内容。您甚至可以在获得图形之前使用通用图片(或在未提供图片时使用纯色)来开发功能 material.
为什么要使用 UserData?
您的 space 飞船已创建,您正在为自己的生命而战。在某些时候,有人会受伤,你需要跟踪它。您可以使用变量轻松完成此操作,但是如果您想使用 NSCoder 来保存您的游戏状态,则必须手动完成。 如果您存储有关精灵的特定信息,则 UserData 是关键。它仅特定于 THAT 节点。当您使用 NSCoder 保存您的游戏状态时,它也会与所有其他内容一起保存。 这是准时的数据。在游戏过程中,生命值会发生很大变化,但是当您加载上次保存时,您希望与您战斗的老板像您保存时一样受到伤害。所以它是准时的,但坚持不懈。它只与那个节点有关。因此将其存储在节点本身中是有意义的。
表演
与您可能担心性能的任何事情一样。如果你有数百个精灵不停地受伤和治疗,如果你一直更新用户数据,它可能会出现瓶颈。如果你到了那个地步,你可能会考虑从 SKSpriteNode subclassing,添加一个变量来跟踪健康等,而不是直接处理 NSCoder 的东西,只需提交你的变量的内容当你需要保存它时到 userData。