找回密码
 立即注册
查看: 1061|回复: 12

[笔记] unity如何写出前后端通用的代码?

[复制链接]
发表于 2020-12-12 11:40 | 显示全部楼层 |阅读模式
unity如何写出前后端通用的代码?
发表于 2020-12-12 11:47 | 显示全部楼层
谢万士辰邀,我的观点是不要图简单,对某平台依赖越来越深,尽量保持全栈技术可以拆分拼接,避免从上到下深度依赖一套。哪天有个环节不适应你就痛苦了,换又不是不换又不是,越走越远,越用越窄。

如果我只会C#和unity,我网络部分宁可废点神找其他的具体c#的网络库。好歹保持点自立根生的能力,别越用越退化了
发表于 2020-12-12 11:54 | 显示全部楼层
虽然这是一个很蠢的提问(不要问我为什么了)。我就文不对题吧。

部分代码通用可以考虑脚本语言,比如lua。
本来让服务端直接用c#是最正常的方案,但是c#是封闭语言,确实有限制,这点挺无可奈何的。总之就是现在unity客户端很难直接用同一语言,只能用嵌入语言或者代码翻译器(不知道有没有)

浮点误差确实无法避免,虽然大部分浮点误差是使用不当造成的,但即使正确使用,不同设备上还是可能会有一点点误差(小数点最后一位)

但这点误差有很多办法可以消除,也不是就非得改成整型。整型呈现的时候还是要换算成浮点,定期将浮点数据取下有效数字,可能性能还好一些。

而且上面说这种误差是极小概率事件,是在实际运行的网络日志中发现的,大部分情况对游戏毫无影响,可以考虑无视。
发表于 2020-12-12 11:57 | 显示全部楼层
占坑,先说说现状,以后细答。
============================时间2017年6月10日============================
现在,我们团队正打算用类似UNet的方案,这周,我用这个方案写了个小Demo。
Demo的玩法是多玩家在同一个场景内采集资源、互相攻击、自我增益等等,主要是为主体游戏验证同步方案。
实现起来涉及到的框架功能如下:
1. 创建房间
2. 建立连接Peer
3. 创建、同步网络数据对象NetworkPlayer
4. 由NetworkPlayer创建本地对象
5. 使用SyncVar同步属性(Host拥有修改权限,Client仅能定时接收到同步)
例如HP
6. 使用NetworkTransform方案同步属性(Client有修改权限,并同步给Host及其他Client)
例如Position
7. Client使用Cmd调用Host逻辑
例如使用道具
8. Host使用Rpc调用网络对象逻辑,并下发至所有Client上的对应网络对象
例如使用道具成功
9. Client对Host发送Message
例如请求LocalPlayer所在位置的地图数据
10. Host对指定Client发送Message
例如返回对方所请求的地图数据


那么,在写起来的时候是什么一种感觉呢?
早上起床,我对着镜子刷着牙,然后开始认真思考自己是LocalPlayer还是RemotePlayer,我现在刷牙这么认真,会不会不同步出去,如果不同步出去我岂不是白刷了。
写代码时感觉要精分,上一行是Host,下一行可能就是Client了,上一行是Local,下一行可能就是Remote了。
实际书写碰到的不习惯:
1. 整条工作流非常长
相当于在C/S架构中,同时写Client、Server并且制定协议,在写Client的过程中还需要写Local、Remote,再往后还有View层的相关表现,导致一个功能的实现可能需要同时编写6个以上的文件
2. 在收发Cmd/Rpc、修改SyncVar时,需要脑子清醒
考虑自己是Host还是Client,是否有权限做相关操作
考虑自己是Local还是Remote,分别做什么样的处理
3. 在即是Host又是Client的情况下,代码共用所导致部分变量共用,部分代码写起来很猥琐,例如:
bool isA = false;
void A()
{
    if(isA) { return; }
    isA = true;
    RpcOnA();
}
void RpcOnA()
{
    //BUG!!!!如果是Host的话,isA此时为true
    if(isA) { return; }
    isA = true;
    //Do Something
}

//正确打开方式
void RpcOnA()
{
    if(!isHost)
    {
        if(isA) { return; }
        isA = true;
    }
    //Do Something
}
分析原因:
->1. C/S架构的工作流是,前后端先定接口,再写各自的逻辑,而现在我的Demo是前后端同时、同一个人写,所以工作流显得长
->2. 由于共用代码的缘故,工作流是前后端同时写,导致思维混乱,实现起来完全可以避免
分析好Host/Client的功能、接口
在初始的时候就就行Local/Remote的区分初始化、包括分支处理。
->3. 无解,除非不存在isHost && isClient的情况,由于C/S的架构本身就是前后端分离,所以不会有这种问题。


使用建议:
1. 实现做好结构分析、设计
2. 分离出数据、逻辑、表现
3. 数据:确定Host、Client的持有、同步需求
玩家们的背包数据在Host,每个Client拥有自己的背包数据,之间需要进行数据同步
4. 逻辑:确定Host、Client的职责、权限、交互接口
对背包的增减需要授信,所以逻辑在Host,同时对Client进行数据变化的推送
5. 表现:根据需求针对网络对象,在初始化期间进行对应表现逻辑注入
LocalPlayer注入至HUDPlayer,RemotePlayer注入至RemotePlayerManager
相同的事件,两边对进行不同的表现逻辑处理。
发表于 2020-12-12 12:01 | 显示全部楼层
掺和一下。我觉得吧,这个问题问的,以及已有的诸多回答,思路上都是有问题的。
你是使用语言和环境来构建产品,产品才是核心,而不是为了编码特性(方便、通用之类的)来为产品选择技术方案。
Unity提供的网络库能不能用?能,但是这玩意得看你需求,你想拿来做个moba或者mmo我劝你还是算了。你要是搞个卡牌什么的,自己写一套或者网上找一套基于C#标准实现的网络库也都很简单,复杂的mmo当然最好还是上C++。服务器简单记个排行榜分数什么的,那还是用人家直接提供的快。
至于什么碰撞啊,物理啊,想在服务器端重用unity组件,都是有代价的,性能也好,部署也好,可能都会很麻烦,这也得看你需求,你后台跑windows server,用c#写一个服务器,验证没有实时性要求,也不是不能用。单纯的问如何达到代码通用没有意义,很可能你为了代码通用做了一堆功夫,还不如自己写个简单的碰撞系统来的简单(大部分游戏其实只需要计算刚体是否碰上,没啥实际物理要求)
归根结底,得先把你产品想清楚了再来选择。
发表于 2020-12-12 12:06 | 显示全部楼层
关键字,Photon engine,有提供基于UNet的实现。
详情不清楚,我用的是nodejs。题主自行研究下。
发表于 2020-12-12 12:15 | 显示全部楼层
Unity确实可以写前后端通用的代码,我之前做个一个卡牌类手游就是这样做的,不过官方的Network以前功能限制很大,现在虽然改进了一些但是在国内还是面临延迟等各种问题,基本还是没什么人用的。回到题主的问题上来,我以前在Unity4.x时代是用uLink来做前后端通用的代码的,前后端战斗逻辑计算用一套通用算法,只是发送用户操作的数据。至于刚体碰撞这些肯定是不用操心的,既然后端也是unity开发的,在服务器端也都是有刚体碰撞这些组件的,不需要重写,实际上题主仔细学下官方的network思路就知道了,同样的人物、NPC,在服务器端一般只是比客户端少Render之类的表现层的东西,最后build为不带图形界面的后台运行程序就可以了。真的感兴趣的话可以了解一下uLink,现在5.x时代还是可以用的,他完全按照官方的思路进行了拓展,加了uLobby等很多专业网络架构的模块,会比直接用官方的好很多。
发表于 2020-12-12 12:17 | 显示全部楼层
不太现实。主要问题是市面上还没有任何物理引擎是消除了浮点数误差的,也就是会有可能造成不一致,如果物理部分自己实现,应该是可以的,之前做过战斗用lua写 可以两边通用的,也可以用c写,王者荣耀似乎用的是这个方法实现的帧同步,达到多个客户端跑一套代码和数据得到同样的结果
发表于 2020-12-12 12:24 | 显示全部楼层
用c++来写后端的逻辑。
然后复用这些c++代码作成类库作为plugin提供给unity3d前端。相当于不要用c#来写逻辑。
优点:基本上游戏核心逻辑是一套代码
缺点:调试不那么方便/C++开发成本比较高
发表于 2020-12-12 12:27 | 显示全部楼层
模块化,我正在设计一套MMORPG客户端服务端通用模块,common.dll dbdata.dll clientmsgpack.dll 大致分为基础组建类库,_比如字节流写入,读取类,编码转换,日志,常用算法.crc16,md5,tcp客户端服务端,, 配置文件类库,读取通用的游戏配置文件,如地图信息,怪物,npc配置文件。  封包协议库,定义客户端与服务端通讯协议结构。 数据库结构类,如角色数据库信息,角色背包,技能数据,脚本lua tabel序列化个人变量。 现在暂时分了这么多通用的类库,,还引用了大量的开源库,execl.log4. fastsocket .lua。踩了坑后再补充。
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-23 00:21 , Processed in 0.159966 second(s), 25 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表