游戏刻 (Game Tick)

本文所有内容均基于Java版,基岩(BE)版不保证所有特性相同(部分已说明BE版的内容除外)!

游戏刻(Game Tick,简称gt ,所以真就先有gt后有天了Minecraft底层中用于计量时间的单位,常被用于衡量红石电路延迟、TNT爆炸时间等重要指标,是Minecraft中最小的完整时间循环单位,但是实质上,游戏刻是可以被再分的,但是再分后不再是一个完整的时间计量(打一个不太恰当的比方,就像是水分子H2O一样,一个水分子内含一个氢原子和二个氧原子,而通过某些手段,其可以被拆分为一个氢原子和二个氧原子,但是拆分后它不再是一个完整的水分子)同时也不能被视为一个完整的循环周期。在同一个游戏刻内发生的事件其实实际上依然是有先后顺序的,但是他们依然会被定义为“同时”,可以粗浅的理解为这本质上是将一组的同时发生的事件在一个循环内按某些顺序先后处理后打上一个“同时”的标签,这也就使得某些本来玩家期望要在同一个gt内按照某种特定顺序发生的事件因为顺序问题不得不更改顺序或将其置于另一个gt内进行(实际上这种特性在计算机的运行本身中也有一定的体现)。实际上,对于很多游戏都会有类似的设定,因为用离散的、逻辑性的、有先后顺序的计算机去模拟连续的、同时性的事件本就是一个难题,只是因为Minecraft是沙盒游戏的同时加入了红石系统,使得这个现象被特别突出了出来(而不是因为MOJANG不会做游戏SB BUGJUMP)。同时,Minecraft中的一切事件的时间长短都是基于游戏刻的,现实世界的一秒对应Minecraft的20gt,这意味着电脑必须在1/20=0.05,即在50毫秒,如果电脑的运算能力无法在这么短的时间内完成运算,那么一个游戏刻的时间会被延长,使得一秒执行的游戏刻会变少,即对于任意情况,我们都有每秒执行的游戏刻数量≤20;同时相应的,当一秒执行的游戏刻变少时,某些游戏内容也会相应的变慢,如熔炉烧制一个物品需要10秒即10*20=200gt,如果此时电脑的处理能力使得一秒仅能执行10个gt而非20个gt,那么烧制一个物品所需要的时间(现实时间)将会变为200/10=20秒。正因为游戏刻的种种特性,使得其变为深入研究Minecraft红石系统的玩家游玩中所不可或缺的一部分。

(注:如无深入了解打算可以仅阅读开头的“基础概念与部分属性”部分)


  • 基础概念与部分属性

Minecraft的循环程序是以每秒20周期的固定速度运行的,即TPS: 20.0。因此每刻发生在每0.05秒。在游戏中的一天将正好为24000刻,或20分钟。但是这个速率也不是完全固定的。如果电脑的性能不足以跟上这个速度,一个游戏刻的运行时间就被延长,每秒的游戏刻就会变少。由于游戏中的绝大多数动作都是以游戏刻而不是真实世界的时钟作为时间基准,这意味着在较慢的电脑上很多事情都要花更长的时间来完成。

每过去一刻,游戏的各方面都会更新:移动的实体位置会发生变化,生物会检查周围环境并更新自身的行为,玩家的生命值和饥饿值会根据玩家的处境发生变化,等等。这些游戏的方面是服务端的行为,和负责渲染游戏本身的客户端的更新速度没有关系。也就是说,游戏的帧率(FPS)不影响TPS,电脑的图形性能不会影响到游戏机制。

和每秒刻数(TPS)相关的一个单位是每刻毫秒数(MSPT),即服务器实际上用来计算一刻所需的时间。只有在MSPT不超过50时,TPS才可以达到20。以下的游戏机制比较消耗资源,容易导致服务端卡顿:

  1. 漏斗收集上方物品。可以通过在漏斗上添加容器方块防止这一行为发生。也可以直接换成吞吐量更大的水流运输。

  2. 红石电路更新。应该在时钟等线路上增加开关,以避免不必要的状态改变。另外红石造成的亮度更新也会造成卡顿,可以通过尽量减少空气空间避免。

  3. 生物AI。可以使用照明控制怪物的产生,并使用更高效的技术养殖家畜。

  4. 有些Mods可以优化或简化游戏逻辑。由于Mods是第三方产品,本Wiki不会特别声称其适用性。


  • 本质

游戏刻的本质其实是按照一个特定的执行顺序进行不同类型的更新与运算,并将执行结束后50毫秒内的剩余时间进行延迟。以此为基础作一个循环,最后达到做出所谓“时间”这个概念的目的,而对于这个循环的某一个周期本身,我们称之为游戏刻(Game Tick),同时,对于循环周期的次数(即时间量)则称之为游戏刻(Game Time)

  • 游戏刻的执行顺序

将游戏进行反编译并使用官方的混淆映射表(发布自己的混淆表......这种操作我这辈子还是第一次见......),进行反混淆后从源码进行解析不难看出Minecraft的游戏刻执行顺序,值得注意的是,获取Minecraft的源码本身就是不合理且不受法律保护的,虽然官方MOJANG默许甚至在一定程度上略微支持这种行为,而在没有获取官方允许授权的情况下对Minecraft的源码直接进行公布、抄袭还有用于商业行为是违法的,以下是Minecraft在一个游戏刻中执行的顺序(适用于1.13.2,但是事实上,这个时间顺序在1.14以下版本大部分(而不是全部)都适用,对于涉及到底层的执行方面官方很少会对此进行大修改)

  1. 成就命令相关

  2. 同步玩家客户端的时间

  3. 极限模式下难度锁困难判断

  4. 群系生成相关

  5. 玩家睡觉逻辑

  6. 生物、怪物刷新

  7. 区块卸载

  8. 天空光衰减计算

  9. 设置GameTime与DayTime(即世界时间相关)

  10. 计划刻(Scheduled tick或者Tile tick亦或者叫做Next Time Entry)

  11. 随机检查并更新玩家周围的亮度

  12. 天空光的计算与将新增的Tile      Entity储存至区块内;雷电;下雪与结冰;随机刻

  13. 玩家加载的区块列表更新,并发送客户端方块更新数据包

  14. 村庄运算

  15. 僵尸围城

  16. 地狱门缓存清空

  17. 方块事件(Block Event)

  18. 维度卸载判定相关

  19. 维度相关的运算(目前仅有末地的龙战相关逻辑)

  20. 天气相关实体运算

  21. 玩家实体运算

  22. 普通实体运算

  23. 方块实体运算

  24. 发送客户端实体更新数据包

  25. 网络玩家信息运算

  26. 自动保存

由于Minecraft的游戏延迟与时间更新不同步sbmojang,两个游戏刻之间的间隔的选择成了一个问题,参考前人的某些理论分析:作为一个离散的时间量,在游戏运算中一定存在某一个时刻,GameTime(游戏刻)这个时间量发生改变,这就是GameTime的分界线,这里前人将其划分为GameTime与GameTime+1,同时给出了游戏刻的确切定义:
GameTime为x的定义为:所有执行World.worldInfo.getGameTime()得到的返回值为x的时刻的集合。

同时,这样可以得到事件P发生于GameTime x的定义:

一个事件P发生于GameTick x的定义为:发生事件P时若执行World.worldInfo.getGameTime()得到的返回值为x。

这么定义的好处:

  1. 与计划刻元件的执行时间相对应,在GameTick为N时所触发的X gt延迟的计划刻元件会在GameTick为N+X时进行更新。

  2. 照应前人研究,鉴于以前红石理论多基于命令方块,而命令方块更新依赖Game Time,如此定义使一些较为远古的红石理论能与其兼容。

  3. 可以直观的在代码中调用World.worldInfo.getGameTime()来确定当前的GameTick。

  4. 不会调用代码的可以使用命令方块进行调试。

由此可得新的运算顺序:

  1. 设置GameTime与DayTime(即世界时间相关)

  2. 计划刻(Scheduled tick或者Tile tick亦或者叫做Next Time Entry)

  3. 随机检查并更新玩家周围的亮度

  4. 天空光的计算与将新增的Tile      Entity储存至区块内;雷电;下雪与结冰;随机刻

  5. 玩家加载的区块列表更新,并发送客户端方块更新数据包

  6. 村庄运算

  7. 僵尸围城

  8. 地狱门缓存清空

  9. 方块事件(Block Event)

  10. 维度卸载判定相关

  11. 维度相关的运算(目前仅有末地的龙战相关逻辑)

  12. 天气相关实体运算

  13. 玩家实体运算

  14. 普通实体运算

  15. 方块实体运算

  16. 发送客户端实体更新数据包

  17. 网络玩家信息运算

  18. 自动保存

  19. 成就命令相关

  20. 同步玩家客户端的时间

  21. 极限模式下难度锁困难判断

  22. 群系生成相关

  23. 玩家睡觉逻辑

  24. 生物、怪物刷新

  25. 区块卸载

  26. 天空光衰减计算

(其实就是把GameTime与DayTime前面的部分挪到了后面)

  • 简化版顺序

对于较为重要的修改服务端世界相关操作所在的阶段,可得简化版的顺序列表(这个简化表同时适用于两种不同的分界线……):

顺序
阶段
名称
缩写
顺序
阶段
名称
缩写
1
设置世界时间
World Time Updata
WTU
6
实体
Entity Updata
EU
2
计划刻
Scheduled Tick/Tile Tick/Next Time EntryST/TT/WTE
7
方块实体
Tile Entity
TE
3
随机刻与气候
RandomTick&Climate
RT&C(RTC)
8
玩家操作
Network Updata
NU
4
村庄相关
Village
V
9
刷怪
Spawning
S
5
方块事件
Block Event
BE
10
区块加载
Chunk Unload
EU
  • 一些容易误判顺序的更新顺序

引用前人理论研究:

1.活塞推出方块:
当活塞普通推出,即用时3gt的推出,此时被推出的方块到达目标位置时,更新顺序为Tile Entity。而当活塞收到短脉冲,即0gt,1gt或者2gt,此时被推出的方块到达目标位置的更新顺序为Block Event。如果是推出方块使红石线连接,更新顺序也为Block Event。
2.活塞破坏拌线:
这是在活塞推出瞬间完成的,拌线被替换为36号方块。所以更新顺序为Block Event。
3.树苗成熟:
自然成熟的树苗是由random tick完成,更新顺序为random tick。发射器骨粉催熟树苗,更新顺序是在发射器更新的NTE。玩家骨粉催熟的树苗,更新顺序是在玩家更新的Network Update。
4.命令输入:
命令方块执行命令的更新顺序为NTE,而玩家执行命令的更新顺序为Network Update。
5.红石灯:
红石灯是个很特殊的元件,它的点亮与熄灭更新顺序不同(P.S. sbmojang),点亮时瞬间点亮,与红石导线一样,没有任何延迟,而在熄灭时,有4gt的延迟,并且更新顺序为NTE。
6.重力方块:
MC中的沙子、沙砾等,其掉落前1gt延迟也是通过NTE实现,但它们在接收到NTE更新时,并不是立即更新周围方块,而是先创建掉落的沙子实体,等到实体更新时才将方块所在位置设成空气。所以,沙子掉落形成的更新顺序是Entity Update。

  • 活塞

活塞与粘性活塞的行为与更新顺序十分奇葩,但是此词条仅讨论游戏刻本身,所以此部分将会加入活塞粘性活塞的词条中。

参考资料(排名不分先后顺序):

  1. 《深度剖析Minecraft #1 游戏流程》——Fallen_Breath

  2. 《[理论分析] 红石更新延迟理论》——Gamepiaynmo

  3. 《【MC】想学0t?来这里就对了 最详细的0t原理讲解+干货讲解【第一讲之0t基础原理讲解+36号方块篇】》——Donocean

  4. 《【MC】XYZ §1.1 红石tick bug【Sancarn&Selulance】》——Sancarn&Selulance(搬运者为:红石科技搬运组)

  5. 《【MC】XYZ §1.2-6 红石tick bug【Sancarn&Selulance】》——Sancarn&Selulance(搬运者为:红石科技搬运组)

  6. 《游戏刻》——Minecraft wiki


侵删。

资料分类:游戏底层事件

短评加载中..