How Can Unity+腾讯云开发=微信小游戏?

image

写在最前

时光飞逝,物是人非

技术方案总是带着时代的标签,曾经前沿的技术,经过时间的洗礼,可能已成为经典

如果你点进来是因实际需求而不是随意瞧瞧,请同时看看官方的最新进展,指不定有意外的收获

本故事主要讲解在使用 Unity 开发微信小游戏时,如何第一时间用上腾讯云开发的新能力,以及可能的最佳开发实践


故事背景

蛋先生:丹尼尔,好久不见,怎么愁眉苦脸的?

丹尼尔:蛋兄好,最近在折腾用 Unity 开发微信小游戏,服务用的是腾讯云开发,不过碰到些问题,一时半会儿搞不定

蛋先生:哦?什么问题,说来听听

丹尼尔:蛋兄,你也懂 Unity 吗?

蛋先生:略懂略懂

丹尼尔:如此甚好。我起初以为直接调用腾讯云开发,用官方的 Unity SDK 就行了

蛋先生:恩,这个想法没毛病

丹尼尔:但,官方并没有 Unity 版本的 SDK

蛋先生:然后呢?

丹尼尔:后来,我在将 Unity 转成微信小游戏的过程中,发现微信有提供 WeChatWASM 这个 Unity SDK,里面带了个 WX.cloud

蛋先生:那不就解了吗?

丹尼尔:我也天真地这么以为,可在 Unity 编辑器一运行,就…

image

蛋先生:这也正常,毕竟 Unity 编辑器又不是微信开发的,Play Mode 下没有微信小游戏运行环境,自然是跑不起来的

丹尼尔:所以我需要写代码,构建成 WebGL,再转换成微信小游戏,最后才能在微信开发者工具看到运行效果。而我运气不好,还遇到了开发者工具罢工,还得多走一步,用真机预览。这一个流程下来感觉要 1 分钟左右,每次改代码都得走这一长征路,想想头就大

image

蛋先生:会不会是使用姿势不对呢?

丹尼尔:我也怀疑过,直到我看到官方文档介绍的开发方式…

image

蛋先生:看来只能如此,不过对于微信本身的能力,大部分时间我们不需要怎么消费它的输出,好像问题也不大。比如:

var bannerAd = WX.CreateBannerAd(new WXCreateBannerAdParam()
{
   
    adUnitId = "xxxx",
    adIntervals = 30,
    style = new Style()
    {
   
        left = 0,
        top = 0,
        width = 600,
        height = 200
    }
});

bannerAd.OnLoad(()=> {
   
    bannerAd.Show();
});
bannerAd.OnError((WXADErrorResponse res)=>
{
   
    Debug.Log(res.errCode);
});

丹尼尔:恩,这倒是。但对于服务接口,我们是重度消费输出数据的,比如排行榜,好友列表等。总不能来回盲写代码,走一遍长征路调试吧

蛋先生:这长征路是难免的,但可以减少次数。比如在 Unity 编辑器开发时使用 Mock 数据,等业务逻辑走通再走长征路

丹尼尔:我还是希望尽早看到集成了云开发服务后的实际效果,这样可以早点发现问题,减少在长征路上浪费的时间

蛋先生:恩…

丹尼尔:还有个问题,WeChatWASM 对云开发 SDK 的支持,存在滞后的问题,当前只支持 CallFunction,不支持最新的数据模型。我就是冲着腾讯云开发刚新鲜出炉不久的数据模型来的

蛋先生:哦…

丹尼尔:烦死了,这也不行,那也不行,蛋兄,你给出出主意呗

蛋先生:自己搞一个吧

丹尼尔:这,蛋兄,你不是开玩笑的吧?这可不是我的主业务,我只想用云开发服务而已

蛋先生:恩,可以搞,但不能瞎搞。我们来分析一下要解决的核心问题:

一 要能用上云开发的最新功能,比如数据模型;

二 争取可以早点看到实际效果,避免走长征路;

三 实现成本要低,毕竟这不是主业务

丹尼尔:恩,那怎么办?

解决用上云开发最新功能的问题

蛋先生:云开发推出新功能,总是第一时间在 JS 环境(包括云函数,小程序和 Web 页面)提供的,对吧

image

image

丹尼尔:没错

蛋先生:所以我们实际应该直接调用这些 SDK,在 Web 环境下就调用 js-sdk,在小游戏环境下就调用小程序 sdk,这样就能确保享受到最新的功能了

丹尼尔:这些是运行在 JS 环境的吧

蛋先生:没错!所以我们需要实现一个包裹层,这个包裹层对内使用 Unity 脚本去调用 Javascript 函数,对外提供云开发的 Unity 版本 SDK

image

丹尼尔:具体怎么实现呢?

蛋先生:实现细节咱们后面再讲

解决少走长征路,尽早看到实际效果的问题

丹尼尔:好吧,我还有一个问题,为什么要考虑 Web 环境呢?我只想开发微信小游戏而已啊

蛋先生:这就是为了解决第二个核心问题 - 缩短调试路径。虽然我们在 Unity 编辑器的 Play Mode 无法预览效果,但我们可以退而求其次,构建成 WebGL。当你开发完实际的调用云开发的代码后,按 Command + B ,这会构建成 WebGL 应用,并自动在浏览器打开,你就可以直接预览实际效果了,这样可以省去转换成小游戏的步骤,时间上也会节省不少

丹尼尔:虽然不能在 Unity 编辑器直接预览,还是有点小遗憾,但这样的调试路径还是可以接受的

蛋先生:恩,是时候总结一下这种方案的可能的最佳开发流程了

【Unity 编辑器开发阶段】:使用 Mock 数据,这样可省去构建成 WebGL 的时间,同时可确定业务逻辑所使用接口的输入和输出数据结构

【浏览器调试阶段】:根据确定的业务逻辑接口,通过 Unity TCB SDK Wrapper 开发调用云开发服务的代码,构建成 WebGL,预览实际的效果

【微信小游戏预览阶段】:最后直接构建成微信小游戏,进行最终效果预览

image

技术实现细节

丹尼尔:哎呦,不错哦!不过,我现在比较好奇的是怎么实现这个,以及实现的成本咋样?

蛋先生:那咱们接着继续聊

Unity 调用 Javascript 同步方法

丹尼尔:首先,Unity 怎么调用 Javascript 方法呢?

蛋先生:分两种情况,同步和异步。同步方法比较简单,官方文档 已经很详细了,但咱们也来个小示例

首先,定义个要被 Unity 调用的 JavaScript 方法。我们在 Assets/Plugins 目录下创建 .jslib 后缀的文件,比如叫 tcbsdk.jslib

// Assets/Plugins/tcbsdk.jslib

const asmLibraryArg = {
   
  Hello: function () {
   
    console.log("Hello, world!");
  },
  ...
}
mergeInto(LibraryManager.library, asmLibraryArg);

接着,在 C# 脚本里进行映射,比如 Assets/Scripts/DemoSDK.cs

// Assets/Scripts/DemoSDK.cs

public class DemoSDK
{
   
    [DllImport("__Internal")]
    public static extern void Hello();
}

然后,你就可以通过 DemoSDK.Hello() 调用 tcbsdk.jslib 里的 Hello 方法了

丹尼尔:看上去挺简单的,有啥需要注意的吗?

蛋先生:还真有,tcbsdk.jslib 里的 asmLibraryArg 这个变量的存在是有意义的,且不能修改成其它变量名

丹尼尔:为啥?

蛋先生:它的存在主要是为了方法间互相调用。来,我们继续看例子,看看 HelloCallOtherFn 是怎么调用 Hello 的

// Assets/Plugins/tcbsdk.jslib

const asmLibraryArg = {
   
  Hello: function () {
   
    console.log("Hello, world!");
  },
  HelloCallOtherFn: function () {
   
    console.log("Call HelloCallOtherFn");
    // 方法间调用方式一
    _Hello();
    // 方法间调用方式二
    asmLibraryArg.Hello();
  },
  ...
}
mergeInto(LibraryManager.library, asmLibraryArg);

丹尼尔:asmLibraryArg.Hello(); 这个我懂,但为啥是 _Hello();?明明方法名是 Hello 啊

蛋先生:嘿嘿,jslib 里的方法在构建成 WebGL 时都会经过加工后合并进 webgl.wasm.framework.unityweb.js ,这个文件你可以在生成的 WebGL 产物里找到,来看个代码片段

// webgl.wasm.framework.unityweb.js

var unityFramework = (() => {
   
	return function (unityFramework) {
   
		...
		function _Hello() {
   
      		console.log("Hello, world!");
    	}
  		function _HelloCallOtherFn() {
   
    		console.log("Call HelloCallOtherFn");
    		// 方法间调用方式一
    		_Hello();
    		// 方法间调用方式二
		    asmLibraryArg.Hello();
  		},	
		...
		var asmLibraryArg = {
   
			Hello: _Hello,
			...	
		}	
		...
	}
})

看到没?真相就在这儿了。不过,我不推荐用 _Hello(),因为这样你就没法用编辑器的功能,比如点击跳转到方法定义。

image

我们前面提到变量名必须是 asmLibraryArg,这其实是一种取巧的方式,这样即可以实现方法间调用,又可以充分享受编辑器的智能辅助体验,一箭双雕

image

丹尼尔:蛋兄,你可真是个小机灵鬼

蛋先生:咳咳~

Unity 调用 Javascript 异步方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值