appid:afztA5Vo3mtbEpjFrp0V588v-gzGzoHsz
sdk版本号:unity最新版本v0.5.0-alpha.6
client.Room.SetCustomProperties(new PlayObject{{"gold",1}})设置自定义属性可以成功,但马上会触发client.OnDisconnected,不调用这个函数或者传一个空如client.Room.SetCustomProperties(new PlayObject{})也不会断开

官方有人吗,我看unity已经很长时间没有维护了,如果是不维护了,烦请说一声好吗,谢谢!

请问在断开之前有什么错误日志吗?

我测试了一下,每 3s 修改一下房间属性,并在小米 Max 手机上运行了,并没有出现你描述的情况。
下面是我的测试代码:

// Start is called before the first frame update
    async void Start()
    {
        // 设置 SDK 日志委托
        LeanCloud.Common.Logger.LogDelegate = (level, log) => {
            if (level == LeanCloud.Common.LogLevel.Debug) {
                Debug.LogFormat("[DEBUG] {0}", log);
            } else if (level == LeanCloud.Common.LogLevel.Warn) {
                Debug.LogFormat("[WARN] {0}", log);
            } else if (level == LeanCloud.Common.LogLevel.Error) {
                Debug.LogFormat("[ERROR] {0}", log);
            }
        };

        // App Id
    var APP_ID = "xxxx";
    // App Key
    var APP_KEY = "yyyy";
    // 域名
    var playServer = "https://g2b0x6om.lc-cn-n1-shared.com";
    // 这里使用随机数作为 userId
    var random = new System.Random();
    var randId = string.Format("{0}", random.Next(10000000));

    // 初始化
    client = new Client(APP_ID, APP_KEY, randId, playServer: playServer);
    await client.Connect();
    Debug.Log("connected");
    // 根据当前时间(时,分)生成房间名称
    var now = System.DateTime.Now;
    var roomName = string.Format("{0}_{1}", now.Hour, now.Minute);
    await client.JoinOrCreateRoom(roomName);
    Debug.Log("joined room");

    StartCoroutine(ChangeProperty());
}

IEnumerator ChangeProperty() {
    int i = 0;
    while (i < 10) {
        client.Room.SetCustomProperties(new PlayObject {
            { "gold", i }
        });
        yield return new WaitForSeconds(3);
        i++;
    }
}

下图是每次更新房间属性的消息日志:

如果你那边还没有解决,可以提供一个可复现的 demo 工程给我。

PS:这个仓库是一直维护的。

不好意思,我排查到问题了,是因为设置属性成功后我前端有一个异常,导致连接断开,unity没有打印出错误,所以误以为是这个接口bug,谢谢!另外有两个问题,
1,现在房间是没有接口主动销毁到吗,比如我是房主,我退出就相当于解散房间
2,unity现在avobject子类化使用起来不太方便,因为一般是player用户数据,很多用户属性,每一个属性都要加标签和重复到getset,要么你们把SubclassingController.GetPropertyMappings开放自定义,要么用cecil自动注入setget代码,这样方便开发者,多谢!

1,现在房间是没有接口主动销毁到吗,比如我是房主,我退出就相当于解散房间

目前房间销毁策略是「房间里没有人」的情况下,由服务端销毁。客户端只能选择创建,加入,离开,并没有主动销毁的接口。

2,unity现在avobject子类化使用起来不太方便,因为一般是player用户数据,很多用户属性,每一个属性都要加标签和重复到getset,要么你们把SubclassingController.GetPropertyMappings开放自定义,要么用cecil自动注入setget代码

这部分算是存储 SDK 做的工作,我目前正在重构。
关于子类化这部分,我这边的初步考虑的方案是:只设置类名 / 构造方法,然后根据 C# 的 Getter/Setter 映射到数据表的字段,减少目前 Attribute 的使用。

1,可以开放这个接口吗,因为大部分实际房间游戏还是有这个需求的,房主由创建人所有,房主不在,房间销毁,可以交给开发者自己定义,更灵活
2,这个方案是可以的,我之前的方案是继承子类只要是public属性(get,set非必要)的都会自动解析为保存字段,如果有些字段想不保存,再加标签ignore
3,既然您在重构,我顺便说说另外一个问题,就是序列化的设计https://leancloud.cn/docs/multiplayer-guide-csharp.html#hash23935662,初衷是好的,但是你们现在要序列化一个自定义类很麻烦,那个解析实例看起来都头大,我目前是用Newtonsoft.Json封了一层,解析的时候跟我存进去的类型一致,我认为类型一致性对开发者是更友好的,不然我存进去是sting[],读取的时候莫名其妙变成playarray,很奇怪,除非你们的playobject数据序列化反序列化跟Newtonsoft.Json一样支持保存为原始类型,这样多个选择,都能兼顾,而且代价不大

以上,诚心建议,不当之处,轻拍。。

这个实现的目的在于让开发者少关心一些细节,如果由开发者决定是否销毁,可能由于疏忽会导致很多资源浪费。开发者可以认为房间里没人了,这个房间便销毁了。

我理解您描述的使用方案更类似于我们之前的设计,使用 JsonObject/Dictionary 去表示复杂的类型。但是通过 key 获取 value 会导致编译期的错误不能及时发现,还会造成开发者侧代码各种类型转换,另外 json 造成的序列化开销也是很大的。
扩展一下,如果在 PlayObject 里只存放一个 string/byte[],开发者侧拿到 Raw data 之后,可以通过各种序列化工具(json/protobuf,thrift 等)解析,是不是可以省掉「头大的序列化代码」呢?

1,少关心细节是对的,如果是担心资源浪费,可以兼得,你们现在的机制保留,没人的时候自动销毁,有人的情况提供一个主动销毁的机制,其实会更节省。关键是这个需求是实际项目中必须要有的,因为只是房主退了,房间还有别人,方案设计上一般是会要销毁并告知其他玩家,房间已解散,往斟酌下。
2,我现在就是这么干的,自己new了一个playerobject["data"]=序列化对象,但仅仅用在sendevent上,在房间自定义属性和player自定义属性上没敢用,因为如果包一层data,那就是一个属性了,其中一个key变化,整个data都得变,会有浪费,而且data内部哪个属性变了也无从得知,所以目前是做了playerobject与dictionnary的相互遍历转换,作为一个中和方案

我不是很理解你们的需求,有人的情况下,为什么要销毁房间呢?

如果方便的话,可以把方案详细的记在我们仓库的 issue 里。
感谢关注!

1,比如一些聚会游戏,很多计算逻辑是在房主端进行,比如收集其他玩家信息,下发关键信息等,房主是这个房间的核心,房主不在,游戏是进行不下去的,即使切换房主,那这些数据转给新房主复杂度更大,所以一般采用房主不在,解散的模式,如果实在不方便,我只能绕道解决了,就是如果其他人收到房主离开,那leave,也能解决,就是别扭。
2,我说的方案跟你说的“如果在 PlayObject 里只存放一个 string/byte[],开发者侧拿到 Raw data ”是一回事,只不过这种方案用在房间自定义属性上不太合适,这些属性是要准确知道哪些key变化的
3,另外方便问一下你们重构的getset什么时候可以用呢,如果时间太晚,我就先自己注入代码

这个需求可以尝试我们的 Client Engine 服务,即房主运行在 LeanCloud 服务端,尽可能保证房主不掉线。
参考文档2

这个问题在这里我们不就不展开讨论了,您可以把您的方案记录在 issue 里,我们再做详细跟进分析。

我回复的子类化是指「存储 SDK」的子类化,存储功能下个月会开源发布,RTM 服务要晚一些。
Play 服务短时间不会对序列化再做什么开发。
您在这方面的问题或建议都可以提到对应的仓库里,我们共同讨论优化!
再次感谢关注!

ok,多谢多谢,我等你们等存储sdk的子类化,其他的我已经都实现了,再次感谢!

Client Engine如果是玩家掉线怎么办呢?我在使用rejoinroom时,一直提示4308,ROOM_MEMBERSHIP_REQUIRED,不知道Client Engine怎么做玩家掉线重连?请教一下。