来自Minecraft Wiki
跳转到导航 跳转到搜索
  Tick”重定向至此。关于命令,请见“命令/tick”。
  gt”重定向至此。关于gametest命令,请见“命令/gametest”。

几乎所有的游戏(包括Minecraft)都由一个大的程序循环驱动,游戏内的计算遵照循环执行,按照固定的顺序依次被调用。当程序执行了一次循环,这个程序就进行了一次滴答(Tick),而计量滴答次数的单位就是刻(Tick)。在大多数情况下,刻不仅可以代表滴答的次数,也可以代表滴答本身。

游戏刻与计算速率[编辑 | 编辑源代码]

Minecraft的绝大多数计算逻辑都在一个游戏循环内执行,执行一次这个循环就被称为执行了一次游戏刻(Game Tick),作为单位时缩写为gt

由于游戏不能时刻都在计算而消耗资源,所以游戏刻执行一次后线程会进行休眠,等待下一次执行,从而维持一秒内游戏刻的执行次数相等且均匀。通常每秒最多运行20次游戏刻,即从这一游戏刻开始执行到下一游戏刻执行的时间间隔为0.05秒。如果这次游戏刻计算时间小于两个游戏刻的时间间隔,则会进行休眠直到下一游戏刻的执行。在Java版中,每秒最多运行游戏刻的次数可用/tick rate修改,从而缩短或延长两个游戏刻开始执行的时间间隔。

在实际运行中,游戏刻计算的平均时间被称为每刻毫秒数(Milliseconds per Tick,MSPT),用于衡量游戏计算的负载。每秒具体执行了多少次游戏刻被称为每秒刻数(Ticks per Second,TPS),用于衡量游戏运行的真正速率。同时,每秒最多运行多少次游戏刻也被称为最大TPS。在未使用/tick rate修改时,游戏的正常TPS为20,MSPT不超过50。

当MSPT小于或等于游戏刻时间间隔时,游戏能够以最大TPS速率运行。但当游戏刻内计算量太大时,MSPT上升导致超过游戏刻时间间隔,TPS就不能维持在最大TPS速率,而维持在1000mspt,此时游戏的运行速度就会减慢,又称掉刻。在Java版中,若一个游戏刻的执行时间超过了1秒,且距离上次警告已经超过10秒加100个游戏刻,服务端就会输出日志Can't keep up! Is the server overloaded? Running <执行时间>ms or <延迟游戏刻数> ticks behind警告计算发生了卡顿。

Java版中的单人模式或多人游戏主机的调试屏幕内,MSPT和游戏刻时间间隔位于左上区域,打开帧生成时间图表(F3 + 2)也可以查看当前的TPS。

游戏刻在客户端和服务端上都存在。服务端的游戏刻主要负责游戏的计算逻辑,而客户端游戏刻主要和渲染有关。

游戏刻流程[编辑 | 编辑源代码]

在每个游戏刻中,各个模块的计算都按照固定的顺序依次调用。下面的游戏刻流程中,只考虑服务端的游戏刻流程。

Java版[编辑 | 编辑源代码]

Java版中,服务端分为集成服务端和独立服务端。集成服务端内置在客户端内,会受到客户端的影响,而独立服务端的运行状态基本不会受到客户端连接的影响。

集成服务端的流程如下:

  • 检查游戏是否被暂停。当暂停时,游戏自动保存。
  • 当游戏暂停时,且集成服务端正以局域网联机服务器运行,则对所有玩家统计世界打开时间
  • 若游戏恢复运行,对所有玩家进行强制时间同步。
  • 执行服务端逻辑。
  • 更新客户端控制的渲染距离和模拟距离

集成服务端和独立服务端都拥有同样的服务端逻辑。下文中带有蓝色星号标记(*)的流程在服务端使用/tick freeze冻结时忽略执行。

  • 更新游戏刻计数器。游戏刻计数器与世界时间无关,用于记录服务器从启动到现在执行了多少游戏刻。
  • 若游戏被/tick freeze冻结,并使用/tick step步进时,计算剩余的步进次数
  • 关闭与客户端的网络自动发送队列的刷新。
  • *若游戏被重载,执行带有load标签的函数
  • *执行带有tick标签的函数
  • 遍历所有维度,进行每个维度的计算。默认处理顺序为主世界末地下界
    • 每经过20个游戏刻,与这个维度中的玩家同步这个维度的时间。
    • 执行维度游戏刻逻辑
      • 若维度游戏刻逻辑内产生异常,则立刻崩溃
  • 检查客户端连接,删除已经关闭的连接,刷新发送队列,解析来自玩家客户端的网络包(包括玩家的各种动作,但处理这些动作不在此阶段),计算网络使用情况。
    • 绝大多数玩家的实体计算任务在此阶段完成。
  • 每600游戏刻向所有玩家发送更新延迟网络包
  • 服务器GUI存在,更新服务器GUI。
  • 对所有玩家发送正在等待发送的区块网络包,并打开与玩家客户端的网络自动发送队列刷新。
  • 尝试自动保存。两次自动保存的时间不小于100游戏刻。当游戏正在快进时,两次自动保存间隔为300×TPS,否则两次自动保存间隔为300×最大TPS
  • 运行处理队列中的事件,包括来自玩家客户端的各种交互网络包。

每个维度执行游戏刻的流程如下:

  • *世界边界范围更新。
  • *计算天气循环,更新降雨和雷暴计时器。若降雨和雷暴的程度发生变化,向维度内的玩家发送世界事件网络包
  • 玩家睡眠逻辑。当维度内所有玩家入睡时,将时间调整到下一个日出,若在降雨则重置天气循环。
  • 更新内部光照等级乘数,与当前时间和降雨、雷暴有关。
  • *更新时间
  • *若为非调试维度,则执行计划刻逻辑。先执行方块计划刻,再执行流体计划刻,每个游戏刻最多处理65536个方块计划刻和65536个流体计划刻。
  • *更新维度内的袭击事件,清除已经结束的袭击事件。
  • 计算维度内的区块数据
    • *删除已经超时的计算标签,更新计算标签,计算当前所有已加载区块的计算等级。
    • 计算需要执行区块刻的区块,并打乱区块执行区块刻的顺序。
    • *计算生物上限等生成数据
    • *执行每个区块的区块刻
    • *执行计划周期生成
    • 更新各个玩家追踪的区块,并以网络包发送到玩家客户端。
    • 刷新区块的兴趣点数据卸载不需要的区块
  • *计算方块事件,并将方块事件数据发送到玩家客户端。
  • 若维度内有玩家或强制加载区块,则重置闲置超时
  • 若闲置超时小于300游戏刻,则执行实体和方块计算逻辑:
    • *计算末影龙战斗数据。
    • 遍历维度内的所有实体,进行实体计算。对于玩家骑乘的实体,/tick freeze对它们没有作用:
      • 遍历顺序由一个游戏内不可见的实体ID决定,实体按照ID从小到大进行遍历。从服务器启动开始,ID被初始化为0,每加载一个实体此ID自增1,即此ID代表了实体的加载顺序。对于同一个实体,若它未被卸载,那么实体ID不变,直到被卸载为止。
      • 删除已被标记清除的实体。
      • server.properties内的spawn-npcsfalse,删除所有村民流浪商人。如果spawn-animalsfalse,删除所有动物和水生动物。
      • *检查清除条件,清除满足条件的实体。
      • *对于强加载区块内的实体,检查骑乘情况并使失去坐骑的实体停止骑乘,并进行它们自身的实体计算。
        • 玩家的部分实体计算也会在此阶段被计算,如监守者生成数据。
    • *计算维度内的方块实体逻辑。
  • 加载区块内未加载的实体,卸载不需要的实体,更新各个玩家追踪的实体,并以网络包发送到玩家客户端。

基岩版[编辑 | 编辑源代码]

此段落暂无内容。

你可以帮助我们加入信息

区块刻[编辑 | 编辑源代码]

此章节仍需完善,你可以帮助我们扩充更多信息。
说明:基岩版相关内容并不全

在游戏刻计算流程中,游戏会以一个区块为单位进行一次游戏刻计算,而这次计算被称为区块刻。在Java版中,加载等级为实体计算等级的区块才可以执行区块刻,在游戏冻结时区块刻全部停止计算;在基岩版中,每个游戏刻内,所有加载的区块都得到区块刻处理。

Java版中,区块刻的执行顺序如下:

  1. 以随机顺序,遍历所有满足区块刻条件、加载等级为实体计算等级、且区块中心距离玩家128格(水平距离)以内的区块。
    1. 增加区块时间。
    2. 若当前为雷暴,且此区块为强加载区块,执行雷暴相关逻辑。
      • 每个区块刻,若游戏规则doMobSpawningtrue,每个区块都有1100000的概率产生闪电,并计算落点位置(受到避雷针影响),若落点没有降雨则闪电无法生成。
      • 在成功生成闪电的同时,若闪电没有落到避雷针上,则有区域难度×1%的概率生成骷髅陷阱
    3. 如果此区块位于世界边界内,执行周期生成
  2. 遍历所有满足区块刻条件的区块。
    1. 若正在降雨,执行雨雪相关逻辑。
      • 每个游戏刻,每个区块会尝试随机刻速率次雨雪逻辑,但只有148的概率可以执行。
      • 每次雨雪逻辑都会在区块内随机找到一个水平位置,并计算这个水平位置上的最高的阻止运动的方块(含水方块和流体也被视为阻止运动)。
        • 若该方块是,且满足结条件,将水替换为冰。
        • 计算此处是否降雪和是否能积雪,若满足条件积雪则增加一层
        • 若该方块是炼药锅,计算炼药锅收集水和细雪的逻辑。在降雨时炼药锅接收到区块刻有5%的概率使水位上升一级,在降雪时有10%的概率收集一层细雪。
    2. 当随机刻速率大于0时,执行每个子区块内的随机刻

随机刻[编辑 | 编辑源代码]

随机刻的范围,以草在泥土上的生长传播所示。草是服从区块边界分布,说明随机刻按子区块为单位计算。中间的红色和蓝色箭头分别标记+X和+Z方向。玩家位于区块的(7,7)位置,略微面朝区块的西北角,这意味着-X和-Z方向边缘上两个区块的中心纳入了128方块的半径内,从而得到区块刻处理。正北方和正西方边缘的两个一区块面积的草突出证实了这一点。(以上为北)

在区块刻的执行过程中,区块会在其中选取几个方块进行计算,这种计算被称为随机刻(Random Tick)。随机刻由随机刻速率,即游戏规则randomTickSpeed控制。

Java版中,随机刻在每个子区块内进行,每个子区块随机选取随机刻速率个方块执行随机刻。默认情况下,随机刻速率为3,即每个子区块在其中选取3个方块执行随机刻。由于随机刻为随机选取,每个方块被选中执行随机刻的时间间隔随机。两次随机刻时间间隔的中位数为47.30秒(946.03游戏刻),平均数为68.27秒(1365.33游戏刻)。也就是说时间间隔有50%的概率短于47.30秒,有50%的概率长于47.30秒。不过,有时候这个时间间隔会长得多或短得多:比如,时间间隔有1.38%的概率会比一秒还短,且有1.23%的概率比五分钟还长。

基岩版中,随机刻在每个区块内进行,每个区块随机选取2.5×子区块数量×随机刻速率个方块执行随机刻。默认情况下,随机刻速率为1。

一次随机刻中方块可被选取多次,从而在方块上同时产生多次随机刻。

绝大多数方块不会响应随机刻,响应随机刻的方块使用随机刻计算下列事件:

计划刻[编辑 | 编辑源代码]

一些方块的行为可能不会在本游戏刻立刻执行,而是延后到之后的游戏刻执行。这种情况下,方块向游戏请求一个计划在指定游戏刻后执行的任务,而规划请求的这项计划任务被称为计划刻(Scheduled Tick)

Java版中,计划刻分为两种,分别为方块计划刻和流体计划刻。计划刻的执行顺序取决于它的优先级,优先值越小,它的执行时间在一个游戏刻中越靠前。通常的计划刻优先级为0,对于红石比较器红石中继器,其状态切换时的优先级更高。当中继器状态切换时指向其他比较器或中继器的侧面或后面(即输入端),则具有最高优先级-3;当中继器本身正在熄灭时,优先级为-2;当中继器正在亮起,或比较器状态切换且指向其他比较器或中继器的侧面或后面时,优先级为-1。

Java版中,每个游戏刻内至多处理65536个计划刻。在基岩版中,每个游戏刻内,每一个区块至多处理100个计划刻。

若一个游戏刻内的计划刻数量超过了最大处理计划刻数,那么超出的计划刻将延后至下一游戏刻处理(即“计划刻堆积”[需要更多信息])。

红石刻[编辑 | 编辑源代码]

红石刻(Redstone Tick),常缩写为rt,是红石系统的时间单位,它代表两个游戏刻。

Java版中,红石刻并不存在于真正的游戏流程中,因为红石系统本质是方块更新和计划刻计算。定义红石刻的目的是为了更好解释红石系统的运行和便于交流,因为绝大多数红石元件都以两个游戏刻作为基础时间单位,有时也并不需要精准到游戏刻级别的时序分析。

基岩版中,红石刻真实存在于游戏中,红石系统每2游戏刻启动一次,计算并更新红石系统。如增删红石元件、依赖变动(如可能被充能的红石导体,被比较器检测的容器)和红石信号在元件间的流动等。有时通过将并发线程启动的那1游戏刻称为“红石刻”,反之称为“非红石刻”来区分并发线程是否启动的游戏刻。

  • 游戏源码中,红石系统的工作频率(以游戏刻为基准单位)被硬编码为2。但实际上可以通过特殊手段强制改动,以此来调整红石刻的工作频率。

历史[编辑 | 编辑源代码]

Java版
1.20.223w31a现在区块刻处理时露天方块检查天气更新的频率受游戏规则randomTickSpeed影响。
1.21.525w06a现在区块刻不再要求距离玩家128格以内,并修改了区块刻的执行顺序与逻辑。
25w09a现在区块刻要求区块加载等级为实体计算等级而非方块计算等级。

导航[编辑 | 编辑源代码]