[开发者心得] 【RPC和Replicated】——Replicated介绍

[复制链接]
1658 |0
空伊伊 发表于 2023-3-21 11:04:26 | 显示全部楼层 |阅读模式
本帖最后由 空伊伊 于 2023-10-10 13:04 编辑

RPC和Replicated
所使用编辑器版本:Online_v0.27

目录


Replicated介绍
1.Replicated是什么
传统的网络游戏网络数据结构设计中,要在客户端让一个值或对象同步服务端的修改,需要定义一个数据结构,通过网络链接(TCP/UDP)来传递这个数据结构, 要自编码来解包和封包这个数据结构。同时在传输完成后要调用客户端对应的回调来修改数据并回调数据改变的方法,而且需要考虑数据传输的可靠性和完整性,以及综合考虑网络流量带来的性能问题,让某些非关键数据不影响关键数据的传输。中间涉及到大量的重复以及容易带来性能风险的部分,还有客户端代码结构和服务端代码结构不同所带来的逻辑混乱问题。

Dedicated Server,也就是DS服务器,针对这种需要做属性同步的场景做了专门的性能和使用优化,我们可以通过给属性添加装饰器 @Property({ replicated: true}) ,加了装饰器的属性会被标记,这样在服务端修改这个属性后,所有客户端的该属性值就能同步改变,DS层专门对属性同步做了性能优化,通过合并同步请求减轻了网络压力。

2.Replicated的使用方法
大前提
Replicated只在双端脚本生效
因为Replicated只接受在双端的脚本中使用,因为修改Replicated的值必须在主控端(服务端)进行,而Replicated值修改的回调必须在客户端调用,故单端脚本作为Replicated的生命周期不完整,不能使用。

步骤一:声明属性值为replicated   
装饰器:@Property({ replicated: true})
给属性加上这个装饰器后,在服务端修改这个值,它将会自动同步到客户端
export class RepScript extends Script {
    @Property({ replicated: true })
    public myID: number;

}

步骤二:赋值初始化属性
对于replicated属性,我们必须要有一个初始化属性用来在编辑器的面板中展示,如果不赋予初始化属性,那么replicated的值将不会生成成功。
一个完整的初始化replicated属性如下,下例中的myID赋值为0的数字类型初始值,这样当脚本属性为非0的时候,就表示myID已经改变了,数据就将会自动同步给客户端
export class RepScript extends Script {
    @Property({ replicated: true })
    public myID: number = 0;

}

步骤三:添加属性修改回调
当属性改变时,会在客户端执行onMyIDChanged方法,当这个方法被执行,就表示这个属性确实的被更新到了。客户端可以直接在onMyIDChanged方法里使用this.myID获取最新的属性值。
export class RepScript extends Script {
    @Property({ replicated: true, onChanged: "onMyIDChanged" })
    public myID: number = 0;

    private onMyIDChanged() {
        //dosomething
    }
}

补充:自定义replicated属性
有些时候,我们同步的属性用简单的元数据类型没办法定义,需要用自定义的结构体来做,这个时候我们可以用@Serializable装饰器来自定义属性类型
@Serializable
class bagData {
    @Property({ replicated: true, onChanged: "onIdChanged" })
    public id: number = 0

    @Property({ replicated: true, onChanged: "onNumChanged" })
    public num: number = 0

    onIdChanged(): void {
        console.log("bagData id = " + this.id)
    }

    onNumChanged(): void {
        console.log("bagData num = " + this.num)
    }
}

export class NewScript extends Script {
    @Property({ replicated: true })
    public bag: bagData = new bagData();

    changeBagData() {
        if (SystemUtil.isServer()) {
            this.bag.num += 5
        }
    }
}


3.Replicated注意事项
- 单个属性支持类型:String Boolean Number null undefined Vector2 Vector Vector4 LinearColor Rotation Transform GameObject 和 符合Serializable规范的自定义类型 以及这些类型的一维数组,确定不会支持的类型有多维数组和Set&Map类型


4.使用案例:使用Replicated制作一个排行榜

回复

使用道具 举报

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