美文网首页游戏程序员
深入剖析Unity FPS Sample (二) 模块结构篇

深入剖析Unity FPS Sample (二) 模块结构篇

作者: windknife | 来源:发表于2018-12-20 20:06 被阅读3次

    Fps Sample的源码规模比较庞大,我们先从宏观层面来剖析一下,下一篇会结合源码整个游戏的流程控制做一个讨论,同时未来还会对我认为这个Sample最具价值的部分————网络消息传输,客户端预测以及服务端的延迟补偿进行深入的探讨。

    一、Game

    Game类(game.cs)是运行时第一个被初始化的类,我们可以认为是整个游戏的入口类,因为FPS Sample中所有其他的代码,都是被Game.Update驱动起来运行的。(这个有点像用C++写游戏时的main.h/main.cpp)

    Game类中创建了多个子系统的,例如Audio、Input、LevelManager等。

    Game对象内部的IGameLoop接口,用于提供统一的初始化、销毁,以及更新。

    目前实现了IGameLoop的接口的类型有ServerGameLoop,ClientGameLoop以及PreviewGameLoop。

    • ServerGameLoop

    ServerGameLoop(ServerGameLoop.cs)用于处理客户端的连接,以及更新所有的服务端系统

    • ClientGameLoop

    ClientGameLoop(ClientGameLoop.cs)用于处理客户端到服务器之间的连接,以及更新所有的客户端系统

    • PreviewGameLoop

    PreviewGameLoop(PreviewGameLoop.cs)把客户端和服务端合并在一起,用于在预览游戏的时候,不用单独构建游戏包,或者单独启动服务端或者客户端。
    当我们在编辑器中进入Play模式,在场景加载完成之后,Preview会作为gameloop来驱动游戏运行。

    二、主要模块

    为了让代码的组织更合理,FpsSample把服务于同样功能的源码,组织到了一起,也就是模块化。
    FpsSample中的所有游戏模块的源码包含在:<u>Assets/Scripts/Game/Modules</u>文件夹下。
    模块中包含了大量的组件,这些组件由对应的System去负责进行更新。

    Player模块

    客户端的Player模块处理由服务端广播下来的消息,维护客户端用户的输入指令,以及对于本地操控角色的更新等处理。

    服务端的Player模块为新连接到服务器的玩家构建一个Player Entity(玩家实体)。Player Entity包含诸如玩家的ID和名字、控制状态等数据。

    每一个客户端程序均包含一个LocalPlayer实例(特别说明,这里的LocalPlayer是指有本地玩家控制的Player实例,而不是代码目录中的Locallayer.cs这个类),LocalPlayer里面拥有本地表现用的组件(例如摄像机控制和界面相关)。例如在CharacterModule中的LocalPlayerCharacterController组件添加到LocalPlayer后,LocalPlayer实例就具备了控制Character的能力。总之,对于一个Entity而言,附加了什么样的组件,就会具备对应的能力,这就是组件的魅力

    ReplicatedEntity 模块

    ReplicatedEntity处理GameObject和ECS实体的复制。

    对于GameObejct而言,只有附加了ReplicatedEntity组件的Prefab才能被复制,这个约束是为了确保被复制的Prefab注册进RelicatedEntityRegistry的。

    对于Entity而言,通过创建一个继承自ReplicatedEntityFactory的ScriptableObjct来复制,这个类也有注册进ReplicatedEntityRegistry。

    Character模块

    Character模块服务于角色属性,动画以及UI表现。
    FPS Sample中的Character通过Prefab来定义的(所有的CharacterPrefab都在Assets>Prefab>Characters下面).
    FPS Sample有3个Character类,分别呢是Character、Character1P。其中Character是在服务端和客户端的第三方玩家显示,Character1P用于第一人称相机模式下。

    Item 模块

    Item模块处理角色的道具。

    当道具执行Update时,读取相关属性的状态,用于触发相关的特效。

    Effect 模块
    • Effect模块控制客户端特效(图形特效和声音特效)的播放。
    • 游戏启动后,在一个静态的特效池内创建特效。
    • Effect当前支持HitScanEfect和SpatialEffect两种特效。
    • 特效属性的通过ScriptableObject来配置。(例如SpatialEffectTypeDefine定义了特效使用的Prefab和特效缓存池的大小。)
    • 特效的播放目前是在代码中调用的,通过特效的Request类(例如SpatialEffectRequest)来创建特效的实体。
    HitCollision 模块

    HitCollision用于处理所有对象的碰撞检测,进行游戏内部的伤害处理。

    服务端存储了碰撞体的一些位置和旋转信息,来支持把碰撞体的信息回滚到某一个ServerTick再进行碰撞检测。这个方法用于服务端的延迟补偿

    Projectile 模块

    这个模块处理自动推进的武器在服务端的模拟,以及在客户端的视觉表现(例如RPG的发射出火箭炮)。

    在FpsSample中,Projectile模块也使用了客户端本地预测的功能,具体未来讨论到。

    Ragdoll 模块

    Ragdoll即所谓的布娃娃系统,这个模块用于更新游戏中已激活的布娃娃的状态。

    SpectatorCam 模块

    SpectatorCam模块用于测试控制一个非玩家角色。

    三、关于ECS

    FPSSample中几乎所有的游戏逻辑都是基于ECS模式来实现的,但是是和原来的GameObject和MonoBehavior现在结合还不太好,例如例如纯ECS创建的实体不能在Hierarchy视图里面查看。因此FPSSample并没有使用纯粹的ECS模式,未来随着ECS模块的成熟,FPSSample团队会把更多的源码基于纯ECS实现。

    四、写在最后

    接下来,我会花些时间把客户端预测和延迟补偿这部分代码给消化掉,然后分享给大家。

    受限于笔者的技术能力有限和英文水平有限,难免有偏颇之处,希望朋友们雅正、谅解!

    相关文章

      网友评论

        本文标题:深入剖析Unity FPS Sample (二) 模块结构篇

        本文链接:https://www.haomeiwen.com/subject/qpuukqtx.html