GamePlay First

----


  • 首页

  • 关于

  • 归档

  • programming

状态同步的预表现和确认机制

发表于 2018-01-06

C/S架构下的同步

C/S(Client-Server)架构下,服务器和客户端需要保持一致的状态,且服务器权威。客户端的指令引发服务器世界状态的变化,服务器下发的快照(SnapShot)数据改变客户端游戏世界的状态。出于游戏逻辑的需要,客户端和服务器都需要感知彼此在当前时刻出于何种状态。

如何保证一致性?

  • 精确对时
  • 服务器和客户端选择合适的频率
    • 理论上频率越快越精确,但是出于性能和带宽的考虑,选择合适的即可
    • 计算频率
    • 同步频率

同步的数据

客户端和服务器传递数据,更改状态。

  • 上行:
    • 客户端发送指令(指令的内容和粒度跟游戏业务逻辑相关)
      • Send Commond
  • 下行:
    • 服务器发消息
      • Remote procedure calls (RPC)
    • 同步数据:封装成常用变量、数组、机构体等等
      • UnityNet:SyncVar
      • Unreal:Replication

RPC在游戏逻辑中通常用作不重要的逻辑调用(经验之谈),比如开枪后服务器回调客户端播放声音、枪火特效等。
数据的同步则常用来表示逻辑状态的变更。

状态预测与确认的方法

一些术语

  • rollback:回滚。当客户端和服务器状态不一致时,客户端将当前状态回退到服务器状态
  • rollforth:‘前滚’。因为回滚所依赖的数据必定是旧的数据,所以客户端回退状态以后,根据缓存的指令再次预表现到自认为正确的状态,以期达到客户端和服务器在时空上的一致。

上行的粒度选择

发送操作级别的指令

  • 逐Tick发送
    • 采用不可靠通道
    • 采用可靠通道
  • 倾向前者,需要服务器逻辑做一定的容错。后者基本违背了使用不可靠通道的初衷。

发送状态变化级别的指令

  • 状态变更时发送
  • 必须可靠通道

对比

优点 缺点
同步操作指令 粒度细、占用更多流量
方便做状态rollforth,可跨状态
服务器要有一定的容错逻辑
客户端计算开销更大
同步状态变化 粒度粗、比前者省流量
只能做单一状态内的rollforth
客户端和服务器对齐上会有偏差
客户端计算开销小

下行的状态确认

  • 理想状态:当客户端预表现状态A->B->C,并发送相应指令后,服务器若没有发生异常,会同步A->B->C。
  • 实际状态
    • A->B->C 的迁移非常迅速(一帧内),B没必要也通常不会下发
    • 下行通常采用‘不可靠’通道,只保证最终状态的重发。即中间状态丢了不会重发

基于Pattern

  • 完备的前提:理想状态
  • 在不完备,即实际状态下,有两种方式

前向确认

  • 预表现状态存在Queue或者RingBuffer中。服务器数据下发后,预表现队列队头出列,匹配成功静默不处理,失败则清空队列,客户端回滚到服务器状态。
  • 当发生循环时,会有以下几种出错的可能性
    • 服务器丢状态,导致预表现队列清空。后续状态会连续信赖服务器而回退,如
      • 客户端 A->B->C->A->B->C,服务器下发A->C->A->B->C。则A->B->C都会多执行一次(预表现+信任服务器)
    • 服务器在快速执行的过程中省略中间过程,会导致客户端预表现状态残留
      • 通常情况下,客户端的操作不希望进行无限制预表现。所以某些关键操作会检查预表现队列,如果有残余则禁止预表现。客户端 A->B->A->B,服务器忽略中间过程,同步起始A和最终B。预表现队列残留A->B,则在服务器下一个状态下发前,客户端无法进行关键动作预表现。

后向确认

  • 预表现状态存在栈中,总是从最新状态开始匹配。适用于不存在循环的情况,万一出现循环,则最后几个状态会被服务器拉车

结论

  • 基于Pattern的状态确认只有在‘理想状态’下才能完全生效

基于Tick or Sequence

  • 客户端状态变化时记录变化的Tick,服务器返回的状态也附带Tick,直接根据Tick比对。简单直接。
  • 适用于同步指令操作的方式

混合Pattern和Tick

  • 同步状态变化的方式下,Tick有可能有偏差。结合Pattern和Tick一起比对。

参考和实践

Overwatch参考

  • [GDC2017:Overwatch Gameplay Architecture and Netcode]的Netcode部分

关于确定性

在守望先锋中,保持一致性的术语其称之为确定性(determinism)。这里的确定性和LockStep的确定性不是一个意思,后者指的是统一的输入永远得到统一的输出,主要解决的是浮点数的不确定性问题。

保持确定性的方法的本质是使用一致的逻辑(游戏逻辑、物理逻辑),在相同的时刻以相同的频率进行模拟计算,也就是其列出的几个手段:

  • synchronized clock:对时来确保客户端和服务器逻辑触发时机的一致。
  • fixed update:固定频率更新以确保客户端和服务器计算频率一致
  • quantization:设置频率来提高或者降低计算的精度。

基于Tick的确认

属于

  • ‘饥饿’:服务器没有指令

客户端

  • 同步指令,同时缓存CommandQueue作为RollForth的依据
  • 状态不一致的时候回滚,并读取CommandQueue中剩余帧的操作进行RollForth
  • 当网络状况变糟糕时,加快发送指令的频率,期待服务器减少‘饥饿’状态,尽量‘内插’

    服务器

  • 根据客户端指令更改状态。在‘饥饿’状态时候复制上一帧的指令,类似‘外插’。

实际的运用和思考

(填坑中)

声明

  • 本文固定链接: https://atlasz.github.io/2018/01/06/states-synchronization/
  • 转载请注明: AtlasZ 2018年1月6日 于 GamePlay First 发表

多人FPS游戏的网络架构

发表于 2018-01-01 | 分类于 programming

Multiplayer-FPS游戏的网络架构

先列出骨架,慢慢填坑

游戏趋势

  • 游戏角色GamePlay逻辑日益复杂
    • TitanFall:载具
    • Overwatch、枪火游侠:技能
  • 游戏模式玩法多变、规模变大
    • Killzone的玩法模式
    • 吃鸡的大规模大逃杀

游戏需求

  • 应对复杂的GamePlay
  • 世界状态的切换
    • Killcam
    • 精彩时刻

重点问题

  • 响应性:Responsive
  • 服务器权威:Server Authority

同步方案的选择

  • LockStep的指令同步
  • Client-Server的状态同步

Lowlevel的Network

  • RUDP的实现

HighLevel的Network

  • 类似UNet和Unreal的接口封装
    • RPC
    • SyncVar
  • ECS(服务但不仅限于网络架构)

LocalPlayer的状态预测和确认

  • 可靠通道
    • 基于Pattern
    • 基于Sequence或者Tick
    • 两者结合
  • 不可靠通道
    • Unreal(还未研究)

移动同步

LocalPlayer

  • 目的:响应及时,少拉扯
  • prediction
  • reconciliation

RemotePlayer

  • 目的:平滑、少闪现
  • Dead Reckoning
  • Entity Interpolation
    • 引入Interpolation Delay(IND)

HitReg

  • 由于引入IND的延迟补偿
  • Rewind机制

目标

  • 不断填充Network架构的内容
  • 不断细化每个内容
  • 讨论并实现每个细节

game_ai_introduction

发表于 2017-10-24 | 分类于 programming

格姆艾尔是一头大象

广场上运来了一头大象,猎奇心起的居民们纷纷前去围观。大家窃窃私语,“这头大象叫格姆·阿提费什尔·英特李琼斯,真是个大家伙!”“据说它小名叫格姆艾尔,是格姆普勒地区的三大神宠之一,今天可算大饱眼福了。”几个盲人,从来没有见过大象,不知道大象长什么样子,他们决定上前摸摸大象。“我摸到大象了!”一个微胖的盲人拽着格姆艾尔的尾巴说,“它长得很像一颗行为树。”“不对!”一个秃顶的盲人打断道,“大象怎么会是一棵树?他明明像一只状态鸡。”队伍中最高大的盲人自言自语,“好神奇的格姆艾尔,它的四肢粗壮,仿佛一头薰鹿。”侏儒盲人尖声惊叫,“他简直就是一头艾猩!”“小伙子们,老头子我年轻时候还没瞎,见过很多动物。”一个学者装束的老盲人慢条斯理地说,“格姆艾尔最像一种叫做阿尔法狗的生物。”争吵还在继续……

游戏开发中的人工智能

每一个游戏开发者在开发进行到某个阶段时,一定绕不开如何设计AI。

在人工智能中,智能体(intelligent agent,简称IA)是一种实体,它自主观察感知外部环境,自行决策并选择最佳行为,以此完成自己的目标。设计游戏AI,目的就是设计能让玩家愉悦的IA,提升Gameplay的体验。

为了语义清晰且不造成歧义,IA在下文中用Agent表示

从AI Robotics开始

robotics

学习新知识,如果害怕自己获取的信息过于片面,可以先从找一本该学科对应的导论入门开始。不幸的是我并未找到一本类似游戏AI导论的书籍,而人工智能导论概述的内容又超出游戏AI本身太多。因此,AI机器人学这个范畴刚好。无论是三种机器人范式(Robot paradigm)还是支撑范式的几个基元(Robot paradigm primitives),都可以直接映射到游戏AI中。

独孤九剑与机器人范式

风清扬传授令狐冲的独孤九剑,虽有破剑、破刀、破掌、破气诸式,但以总决式纲领整套剑法,衍生三百六十种变化。姑且以机器人范式与之对应,总览游戏AI中涉及的各种技术,以期“一招鲜,吃遍天”。

范式

范式是一种哲理或者界定一类问题的一组假设或技术,它是一种看待世界的方式,也包含了一系列解决问题的工具,它具有以下特点:

  • 范式在一定程度内具有公认性
  • 范式是一个由基本定律、理论、应用以及相关的仪器设备等构成的一个整体,它的存在给科学家提供了一个研究纲领;
  • 范式还为科学研究提供了可模仿的成功的先例

用来描述机器人范式的原子结构,我们称之为基元(为了释义准确,我不得不接受了基元这个拗口的称呼)。机器人学中有三大被普遍认可的基元,即一个机器人的主要功能可以分为三类: 感知(SENSE)、规划(PLAN)和执行(ACT)。(还有一种流派认为有第四种基元(LEARN))

以寻路为例,地图发生动态变化,寻路组件重新生成导航网格的过程归类于SENSE;从起点到终点,通过A*算法搜索并生成路点集合的过程归类于PLAN;按照生成的路点进行寻路的过程归类于ACT。

范式1 分级/慎思范式(Hierarchical/deliberative paradigm)

范式1

分级范式出现于1967年第一个人工智能机器人Shakey。这里的分级是执行顺序的划分,并没有父子或者优先级的区别。在该范式中,机器人以自顶向下的方式思考,着重于规划,因此也叫慎思范式。“全局性”是分级范式的最大特点。

思考步骤为:

  • 机器人感知外部环境、建立全局环境图。
  • 感知部分停止工作,规划出所有到达目标所需的指令
  • 从第一条指令顺序执行所有指令

寻路的过程就是这种范式的典型代表。依赖G.O.A.P或者HTN(这几种Game AI Planning的方法会在后续的文章中详细介绍)做决策的游戏AI也归属于这个范式。

范式2 反应范式(The reactive paradigm)

范式2

或许由于记忆原件的成本问题,或者出于模拟动物条件反射等生物现象的目的。80年代,研究者们设计了反应范式。该范式剔除了PLAN基元,由一组多个SENSE-ACT(S-A)结构组织而成。

反应范式具有”局部性”,由于个S-A结构可以自主决定机器人的行为,响应非常及时,所以很多游戏AI的文献中常常把响应及时和Reactive特性划等号。

在诸个S-A结构的上层,通常还有系统进行协调。比如包容结构中,机器人的模块是可以通过能力层次进行分组的。位于较高层次的模块可以覆盖或者包容相邻低层次模块的行为数据。

映射到游戏AI中,行为树(BehaviourTree)就是这种范式的代表。Parallel节点下面的每个分支可以各自分别处理自己的逻辑,但是设计者通常会在上层的逻辑对下层的行为进行某种程度的“干预”。但是,行为树中行为的执行是在各个叶子节点的Action中执行的,不会交由上层统一规划并执行。

范式3 慎思/反应混合范式(Hybrid deliberate/reactive paradigm)

范式3

顾名思义,该范式是一种企图融合前两种范式优点的产物。核心思想是PLAN根据当前外部环境决定激活哪一个或者哪一些S-A结构。

在游戏AI中,混合范式的应用场景不在少数。比如某个Agent拥有多个行为树,上层某个组件或者管理类通过当前环境来决定激活哪一个行为树实例。有的观点认为混合使用Reactive和Deliberate两种范式是合理且有必要的。

回归GAME AI

按照范式划分

借鉴AI Robotics导论的概念,接下来所有文章的讨论将会把游戏AI按照Sensor,Decision-Maker,Action三部分进行划分。

Sensor

sensor

Sensor指代的不仅仅是Agent的传感器应该如何设计实现,还包含在游戏开发中外部环境信息的定义,量化处理方法及一些工具化的思想。

  • 传感器设计方面:比如根据游戏特性,有的Agent采用视锥来搜集视野信息,有的则简单采用扇形和点来设计雷达;Unity官方教程Stealth中接触Navmesh的Corner来感知声音范围,是否在墙后等。
  • 外部环境信息的定义:
    • 静态数据:比如RecastNavigation(Unity使用的开源寻路组件)中Bake的Navmesh,不同行走Layer、OffMeshLink等扩展信息的标识;Killzone中Strategy Graph对于导航的影响。
    • 动态数据:比如势力图(Influence Map)的运用。
  • 信息的量化处理方法:比如使用模糊逻辑(FuzzyLogic)把多个外部条件量化到一个确定值;Utility Theory中如何设计一个Utility或者Score;很多基于Planner进行决策游戏中WorldState和WorldProerty的定义。

  • 工具化:比如依据玩家战斗信息的热度图来自动化生成Strategy Graph;根据Navmesh的信息来自动化生成掩体、障碍、狙击点等信息来帮助策划配置。

Decision-Maker

decisionmaker

Decision-Maker包含各种Reactivity、Deliberation或者混合范式的实现方式与利弊。比如Halo中的行为树,F.E.A.R中的G.O.A.P,Killzone中的HTN等等

Action

action

Action部分包含如何呈现和管理Agent具体Action行为的思路。比如借助线性或者非线性时间轴编辑器(比如Unity的Flux、鹅厂的AgeAction等)来实现怪物AI的ActionManager;比如F.E.A.R中的一个状态机三个状态管理Action等等。

其他划分

除了按照范式进行划分外,还会包含个体AI(Individual)与群体AI(Squad和Crowd)的划分;怪物BOSS、多人游戏机器人(Bot)等不同Case的划分。

内容播报

系列文章内容可能包含:

  1. 具体实现案例
  2. 工作的思考
  3. 如何提高开发效率

声明

  • 本文固定链接: https://atlasz.github.io/2017/10/24/game-ai-introduction/
  • 转载请注明: AtlasZ 2017年10月24日 于 GamePlay First 发表

AtlasZ

聊聊游戏,和人生

3 日志
1 分类
2 标签
© 2018 AtlasZ
由 Hexo 强力驱动
|
主题 — NexT.Muse v5.1.3