[开发者心得] Prefab和Replicated使用心得分享

[复制链接]
964 |0
派大星 发表于 2023-6-20 17:24:02 | 显示全部楼层 |阅读模式






    Prefab:







      Prefab的优势主要有

      • Prefab可以一对多的的统一修改做更新
      • Prefab可以方便的复用
      • Prefab可以加快场景的制作效率
      • Prefab可以结合绑定脚本触发交互逻辑,启动独立的预制体内部逻辑
      • Prefab动态创建时,可以方便的进入动态合批,降低dc



      制作prefab时需要注意


    • 要考虑一下预制体的使用范畴,是项目内用,还是可以项目外复用
    • 可以是场景里的组合物体,没有脚本交互能力,可以用于直接拖入场景中摆放,可以用代码根据Prefab的guid动态生成
    • 可以是具有简单脚本绑定的交互物体,简单自启动,不需要其它外部代码交互. 程序先提供可绑定的功能脚本(比如一个简单的用于物体缩放的脚本,提供一些可调整参数), 策划把该脚本绑定到一些物体上做成Prefab,当该Prefab放入场景后直接就会启动缩放效果了
    • 可以是需要有外部交互能力的物体,根据需要交互的需求,程序给出脚本用于制作绑定,同时提供外部代码交互接口,根据需要约定制作规则(比如命名,父子节点关系等)
    • 如果Prefab考虑多项目通用的,程序提供的脚本需要考虑内部依赖性,比如odin,公共模块,自己项目内其它代码。



       使用prefab时需要注意

    • 目前脚本无法clone,所以代码要生成带脚本的Prefab,不能使用clone,需要Spawn
    • 代码生成预制体,可以进行优先加载。 这样加载速度会变快。
    • Prefab所绑定的脚本,会随着制作而复制到对应的Prefab目录下的脚本目录里,要修改时得注意修改对应预制体目录下的脚本
    • Prefab如果比较大时,使用Spawn生成会比较消耗性时间,直接放场景clone会很快(注意脚本无法Clone,可以动态新挂载)。
    • Prefab需要注意双端情况,如果前端使用,仅勾客户端
    • 代码生成Prefab时如果有绑定脚本, 要等到物体创建后至少1帧后再去getScriptByName(“script.ts") 获取脚本来使用
    • 由于物体在前端不维护父子关系,Prefab无法方便的查找子/父物体.需要通过guid查找,而这些guid在物体(包含子物体)动态生成时都是会动态变化的,目前编辑器给出了一个方案,会提供一个在脚本对象面板进行吸附物体guid的操作。








      Replicated :
        Replicated是啥

      脚本里的字段,加上特定的标记后,在服务端更改该字段后会自动广播到所有客户端







           示例脚本,需要挂载到对象上面


          @MWCore.MWClassexport

          default class Rep_Monster extends MWCore.MWScript {   

          //同步血量变化      

          /**   

          * 当客户端收到hp变更信息时   

          */     

          private onHpChanged() {

                  oTrace("Rep_Monster,onHpChanged exceuted!!");

              }

             onStart(): void {

                   oTrace("Rep_Monster,OnStart!");

              }

               onDestroy(): void {

                  oTrace("Rep_Monster,OnDestroy!");

              }}


        Replicated的好处


        • 同步状态类信息非常方便,能提高开发效率
        • 非常方便的结合prefab使用
        • 断线重连时,属性会自动同步一次


          什么场景下适合使用Replicated




        • 服务器计算伤害后,对角色进行血量更新
        • 角色换装
        • 界面数据刷新都可以用



        Replicated一些周边细节


        • 从服务端向客户端 传递数据和信息的行为。注意是单向的,不会从客户端传递信息和数据到服务端
        • 服务端在固定周期(MW结论: 30帧)里收集需要同步的字段,然后合包通过网络进行发送,这些包每帧发送是有数量限制的,一定量的数据在当前帧发送后,没发送完的会累计到下一帧继续发送。
        • 同步出去的属性是基于udp的,是不靠的
        • 多条属性改动同步到前端时是不保证时序的   eg: ABC=Ship>XYZ




        Replicated和Rpc的对比

        • 属性复制是单向的(S->C),Rpc是双向可用的
        • 属性复制目前是针对所有client,无法指定。rpc可以指定同步端或者广播
        • Rpc 主要应用于过程性行为/事件。如果远端需要知道一个事情,但该事情是有过程性的,有复杂结构的,有时序性的,有关联的一套逻辑时,那么用Rpc是个直接选择。
        • 如果仅仅关心的的最终值,一个结果(状态),一个刷新量,无论你同步多少次我前端逻辑都不会出问题,那么使用Replicated。
        • Rpc是可靠的,消息有确认机制; Replicated 可能会丢,会乱序,不可靠。都是基于udp,但Rpelicated因为不需要确认。会比Rpc快
        • Replicated  是按照固定周期检测变化,并同步的。假如一个变量X,在固定周期类连续执行了几次++X,只会有最后一次变化被同步到客户端。但是Rpc没有这个问题
        • 属性复制在重连登陆或者新玩家加入时都会收到,Rpc则不会补发
        • 属性复制基本上会等包满再发车的,不具备实时性,Rpc则是立即发车,具有实时性。所以有些场合选择Rpc或者Replicated也得兼顾实时性的需求


        当前使用时的注意事项
        • 如果动态生成了物体并并挂载属性复制脚本后,需要至少延迟一帧去修改脚本属性变量才会生效
        • 同步的对象比较多时,新玩家加入或者断线重连会在odin启动之前就收到非常密集的同步消息,导致loading界面需要有比较长的一段黑屏时间后才加载出现,目前和编辑器对齐过,在910版本中修复,待测试
        • 属性脚本里的响应函数功能要考虑内部操作各数据的存在性,进行异步处理,特别是在重连或者新玩家加入时,比如GamePlay.GetPlayer(),在登陆时现在Odin都没有启动,业务逻辑还是空的
        • 属性脚本里的this.gameObject,需要在脚本挂载之后延后一帧之后才有效
        • 后续编辑器会开放一些Replicated可用的网络参数,比如基于玩家的网络裁剪距离,优先级
        • 任何Replicated的字段信息都要考虑消息丢失后的情况,比如换装,使用属性复制会很方便,但如果因为丢失了同步信息的话,有些客户端就换不了,如果是需要非常确定的场合,考虑走Rpc















回复

使用道具 举报

热门版块
快速回复 返回顶部 返回列表