在现代复杂游戏中实现成就系统

发布于 2024-08-23 02:30:16 字数 594 浏览 8 评论 0 原文

如今创建的许多游戏都带有自己的成就系统,奖励玩家/用户完成某些任务。 stackoverflow 上的徽章系统是完全相同的。

但有一些问题我无法找到好的解决方案。

成就系统必须始终留意某些事件,想想一款提供 20 到 30 个成就的游戏,例如:战斗。服务器必须检查这些事件(例如:玩家在这场战斗中避免了对手的x次攻击或者玩家走了x英里)一直< /em>.

  • 服务器如何处理如此大量的操作而不减慢速度甚至崩溃?

成就系统通常需要仅在游戏核心引擎中使用的数据,如果没有那些令人讨厌的成就,则无论如何都不需要这些数据(例如:玩家在每次战斗中跳跃的频率,你不知道)不想将所有这些信息存储在数据库中。)。我的意思是,在某些情况下,添加成就的唯一方法是将检查其当前状态的代码添加到游戏核心,这通常是一个非常糟糕的主意。

  • 成就系统如何与保存后续不必要信息的游戏核心进行交互? (参见上面的示例)

  • 它们如何与游戏的核心分离?

我的例子可能看起来“无害”,但想想目前《魔兽世界》中的 1000 多个成就以及同时在线的许许多多玩家。

Many games that are created these days come with their own achievement system that rewards players/users for accomplishing certain tasks. The badges system here on stackoverflow is exactly the same.

There are some problems though for which I couldn't figure out good solutions.

Achievement systems have to watch out for certain events all the time, think of a game that offers 20 to 30 achievements for e.g.: combat. The server would have to check for these events (e.g.: the player avoided x attacks of the opponent in this battle or the player walked x miles) all time.

  • How can a server handle this large amount of operations without slowing down and maybe even crashing?

Achievement systems usually need data that is only used in the core engine of the game and wouldn't be needed out of there anyway if there weren't those nasty achievements (think of e.g.: how often the player jumped during each fight, you don't want to store all this information in a database.). What I mean is that in some cases the only way of adding an achievement would be adding the code that checks for its current state to the game core, and thats usually a very bad idea.

  • How do achievement systems interact with the core of the game that holds the later unnecessary information? (see examples above)

  • How are they separated from the core of the game?

My examples may seem "harmless" but think of the 1000+ achievements currently available in World of Warcraft and the many, many players online at the same time, for example.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

夜夜流光相皎洁 2024-08-30 02:30:16

成就系统实际上只是一种记录形式。对于这样的系统,发布/订阅是一个很好的方法。在这种情况下,玩家发布有关自己的信息,感兴趣的软件组件(处理个人成就)可以订阅。这使您可以使用专门的日志记录代码来观察公共值,而不会影响任何核心游戏逻辑。

以“玩家走了 x 英里”为例。我会将步行距离实现为玩家对象中的一个字段,因为这是一个简单的增量值,并且不需要随着时间的推移增加空间。奖励步行 10 英里的玩家的成就则成为该领域的订阅者。如果有很多玩家,那么将这一价值与一个或多个中间经纪人级别相加是有意义的。例如,如果游戏中存在 100 万玩家,那么您可以将值与 1000 个经纪人进行聚合,每个经纪人负责跟踪 1000 名个人玩家。然后,成就将订阅给这些经纪人,而不是直接订阅给所有玩家。当然,最佳层次结构和订户数量是特定于实现的。

在您的战斗示例中,玩家可以以完全相同的方式发布他们上次战斗的详细信息。监视战斗中跳跃的成就将订阅此信息,并检查跳跃次数。由于不需要历史状态,因此它也不会随着时间的推移而增长。再次强调,无需修改核心代码;您只需要能够访问一些值。

另请注意,大多数奖励不需要是即时的。这让您在管理流量方面有一定的余地。在前面的示例中,您可能不会更新经纪人发布的行驶距离,直到玩家总共又走了一英里,或者自上次更新以来已经过去了一天(直到那时在内部递增)。这实际上只是一种缓存形式;确切的参数取决于您的问题。

Achievement systems are really just a form of logging. For a system like this, publish/subscribe is a good approach. In this case, players publish information about themselves, and interested software components (that handle individual achievements) can subscribe. This allows you to watch public values with specialised logging code, without affecting any core game logic.

Take your 'player walked x miles' example. I would implement the distance walked as a field in the player object, since this is a simple value to increment and does not require increasing space over time. An achievement that rewards players that walk 10 miles is then a subscriber of that field. If there were many players then it would make sense to aggregate this value with one or more intermediate broker levels. For example, if 1 million players exist in the game, then you might aggregate the values with 1000 brokers, each responsible for tracking 1000 individual players. The achievement then subscribes to these brokers, rather than to all the players directly. Of course, the optimal hierarchy and number of subscribers is implementation-specific.

In the case of your fight example, players could publish details of their last fight in exactly the same way. An achievement that monitors jumping in fights would subscribe to this info, and check the number of jumps. Since no historical state is required, this does not grow with time either. Again, no core code need be modified; you only need to be able to access some values.

Note also that most rewards do not need to be instantaneous. This allows you some leeway in managing your traffic. In the previous example, you might not update the broker's published distance travelled until a player has walked a total of one more mile, or a day has passed since last update (incrementing internally until then). This is really just a form of caching; the exact parameters will depend on your problem.

丑丑阿 2024-08-30 02:30:16

如果您无法访问源代码(例如在视频游戏模拟器中),您甚至可以执行此操作。例如,可以编写一个简单的内存扫描工具来查找显示的分数。一旦你有了这个,你的成就系统就像每帧轮询该内存位置并查看他们当前的“分数”或其他什么是否高于他们的最高分数一样简单。视频游戏模拟器的一个很酷的事情是内存位置是确定的(没有操作系统)。

You can even do this if you don't have access to source, for example in videogame emulators. A simple memory-scan tool can be written to find the displayed score for example. Once you have that your achievement system is as easy as polling that memory location every frame and seeing if their current "score" or whatever is higher than their highest score. The cool thing about videogame emulators is that memory locations are deterministic (no operating system).

要走就滚别墨迹 2024-08-30 02:30:16

在普通游戏中有两种方法可以实现这一点。

  1. 离线游戏:没有什么像发布/订阅那么复杂 - 这是巨大的杀伤力。相反,您只需使用大地图/字典,并记录名为“事件”的日志。然后每隔 X 帧或 Y 秒(或者通常是:“每次有东西死亡,并且在关卡结束时 1x”),您会迭代成就并进行快速检查。当设计人员想要记录新事件时,程序员只需添加一行代码来记录它即可。

注意:pub/sub 不太适合这个 IME,因为设计者从来不希望“当player.distance = 50 时”。他们真正想要的是“当观看屏幕的人感知到的玩家距离似乎已经经过第一个村庄,或者向右至少 4 个屏幕宽度时”——即比简单的计数器更加模糊和抽象。

在实践中,这意味着逻辑发生在更改发生的地方(甚至在事件发布之前),这是使用发布/订阅的糟糕方法。有一些游戏引擎可以更轻松地执行“逻辑在接收点进行”(“子”部分),但它们并不是大多数,IME。

  1. 在线游戏:几乎相同,除了存储“计数器”(上升的整数),通常还存储:“增量”(帧与帧之间发生的情况的循环缓冲区),以及:“事件”(游戏中发生的复杂事情)可以硬编码为单个 ID 加上固定大小的参数数组)。然后,这些信息通过 SNMP 等方式公开,供其他服务器以较低的 CPU 成本异步方式收集,

即几乎与上面的 1 相同,只是您要小心地做两件事:

  • 固定大小的内存使用量;如果“阅读”服务器离线一段时间,则需要重新赢得当时获得的成就(尽管您通常可以让客户支持人员手动检查主系统日志并计算出该成就“可能”) " 赢得了,并手动奖励它)
  • 非常低的开销; SNMP 是一个很好的标准,我认识的大多数团队最终都使用它

There are two ways this is done in normal games.

  1. Offline games: nothing as complex as pub/sub - that's massive overkill. Instead you just use a big map / dictionary, and log named "events". Then every X frames, or Y seconds (or, usually: "every time something dies, and 1x at end of level"), you iterate across achievements and do a quick check. When the designers want a new event logged, it's trivial for a programmer to add a line of code to record it.

NB: pub/sub is a poor fit for this IME because the designers never want "when player.distance = 50". What they actually want is "when player's distance as perceived by someone watching the screen seems to have travelled past the first village, or at least 4 screen widths to the right" -- i.e. far more vague and abstract than a simple counter.

In practice, that means that the logic goes at the point where the change happens (before the event is even published), which is a poor way to use pub/sub. There are some game engines that make it easier to do a "logic goes at the point of receipt" (the "sub" part), but they're not the majority, IME.

  1. Online games: almost identical, except you store "counters" (int that goes up), and usually also: "deltas" (circular buffers of what's-happened frame to frame), and: "events" (complex things that happened in game that can be hard-coded into a single ID plus a fixed-size array of parameters). These are then exposed via e.g SNMP for other servers to collect at low CPU cost and asynchronously

i.e. almost the same as 1 above, except that you're careful to do two things:

  • Fixed-size memory usage; and if the "reading" servers go offline for a while, achievements won in that time will need to be re-won (although you usually can have a customer support person manually go through the main system logs and work out that the achievement "probably" was won, and manually award it)
  • Very low overhead; SNMP is a good standard for this, and most teams I know end up using it
橪书 2024-08-30 02:30:16

如果您的游戏架构是事件驱动,那么您可以使用有限状态机。

If your game architecture is Event-driven, then you can implement achievements system using finite-state machines.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文