|
0. 絮絮念
本来不想写这篇文章,一来做完这一波之后我再也不想做WSA平台……二来我觉得会做这个平台的人并不多,所以写下来意义也不大。不过在移植过程中ToLua的作者蒙哥给了我不少帮助,也说断断续续有人问他移植WSA平台的问题,我如果搞完了最好分享一下经验,再加上我担心“真香”定律之后在我身上应验,所以还是做一些记录的好。
但因为公司对于uwp平台也没有寄予特别高的期望,不计划投入特别多的时间精力,因此很多做法是短平快糙猛,怎么快怎么来。所以这里分享的一些做法是在短时间内为了解决问题而选取或查找到的解决方案,未必适合所有团队,还请读者自己斟酌取舍。
1. 移植目标
Windows 10 introduces the Universal Windows Platform (UWP), which provides a common app platform on every device that runs Windows 10. UWP平台是微软提出的一个挺伟大的构想,希望统一自己的各个设备上的开发工作。我觉得愿景挺好的,只是推广力度和结果不太令人满意,Windows Store上的App质量与数量都和iOS平台差距非常大,有兴趣的朋友可以去看看。
微软构想下的Universal Apps
但蚊子腿也是肉,有用户就有需求,在一个合作伙伴的建议下,我们尝试把手游项目移植到这个平台。在最初做了基本的调研和评估之后,我还比较乐观,觉得大约1人月的工作量应该可以搞定,只能说结果证明了我的幼稚,整个移植和踩坑的过程花了大约2人月左右的时间,现在还在做一些收尾的工作。
2. Unity打包配置注意事项
在打包过程中有一些需要注意的配置,这里列举下:
1.将Build Platform切换到 Windows Store Apps。UWP平台在Unity上叫做Windows Store Apps,貌似从5.x版本开始已经支持,我们用的是5.6.6f2版本。
最早以为合作方要的是windows版本,导致先搞了2天windows版本,所以还是先问清楚具体需求。另外也有朋友直接用微软提供的win32转UWP的工具来制作,但是貌似只能在Windows上跑,surface上并不支持。 2. Player Settings里使用IL2CPP、.Net 4.6的配置,否则工程会有很多接口不存在导致报错。(这个组合是我自己尝试出来的,也如果可以使用Mono的话更好,后续比如浏览器等插件很多都只支持Mono,不过Mono我没搞定,只能用这个打包方式……)
3. 先安装VS需要的组件,主要是通用Winidows平台开发,其中包含Windows 10 SDK。如果不安装组件直接Build的话,找不到Local Machine等运行方式,也会一直有编译错误。
4. 注意在Build页面选择好对应的配置,我使用的是如下的配置方式(注意,如果遇到了“Cannot resolve Assembly or Windows Metadata file 'Windows.Foundation.UniversalApiContract.winmd'”这样的错误提示,可能会是UWP SDK版本选择有问题。):
5. 需要的DLL要配置好WSAPlayer平台,否则不会放置到生成的VS工程里。
6. Graphics APIs选择DX11,我忘记为什么要这么做了,可能是有材质编译错误之类的,如果遇到了可以考虑修改。
7. 打包好了之后不做修改编译成uwp软件的话是没有任何权限的,需要点开项目里的Package.appxmanifest这个文件,点击功能,把网络权限勾上才能联网。(这个坑了我好久,我一直以为是服务器没有配置好……)也可以在Unity里的Player Settings里进行配置。
Unitty内的功能配置页面
Unity内的功能配置页面
8. Windows 10 SDK最好安装在C盘,有同事因为空间原因放在别的盘符了,提示“Could not find SDK "WindowsMobile, Version=10.0.xxxx.”,也许可以在某些地方配置,这个没继续排查。
9. 在windows设置里开启开发人员模式,确保目标设备已启用了开发人员模式,否则会报错。
3. ToLua的UWP平台编译
本来是直接使用了与Windows平台相同的ToLua.dll,在PC和Surface设备上运行都没有问题,以为就可以这样风平浪静地过去了。但是在提交审核的时候因为“支持的API测试”一项有问题而无法通过Windows Store的自动审核,最终还是选择自己编译一个uwp版本的dll,中间解决各种问题也花费了一周左右的时间,记录一下如下:
- 最初使用Windows版本的tolua.dll,x64版本是没有问题的,但是32位版本就会Crash,经过测试感觉是一跑lua代码就会挂,比如使用print输出就会崩溃。这个要感谢蒙哥帮忙排查之后在C#层进行了修复:
2. windows版本的Tolua.dll在提交审核的时候,“支持的API测试”项会提示如下图所示的失败结果。这里要重新使用通用windows的dll格式的工程重新编译一个版本。
3. 建立通用windows的ToLua Dll工程:
4. 使用luavm而非luajit。最初我查看了下ToLua和SLua的工程,都没有提供uwp的编译方式,而XLua提供了一个版本,使用的是Lua 5.3。因为luajit在编译时会有一些代码生成,这块实在不熟悉,因此选择了看上去可行的Luavm来进行ToLua的构建。将需要的相关代码引入VS工程中,其中luavm代码放置在lua下。
5. 配置附加包含目录,这里暴力地使用绝对路径……
6. 配置Lua的几个预定义宏:
7. 修复微软认为不安全的相关代码,Lua 5.1比Luajit要少很多了,主要包括:
- strerror --> strerror_s
- fopen --> fopen_s
- freopen --> freopen_s
- 不支持pclose和popen操作,上层逻辑不需要,直接内部处理掉;
- tmpfile --> tmpfile_s
- fscanf --> fscanf_s
- sprintf --> sprintf_s
- strncpy --> strncpy_s
- strcpy --> strcpy_s
- strcat --> strcat_s
- strncat --> strncat_s
- gmtime --> gmtime_s
- localtime --> localtime_s
- tmpnam --> tmpnam_s
这里主要是相关函数的替换,修改为安全的版本,花费一些时间但是并不困难。这里要开启SDL检查才会报出相应的错误,通过关闭SDL检查或者添加_CRT_INSECURE_DEPRECATE宏是可以在编译器不显示这些错误,但是提交Windows Store审核时会提示不允许使用这些接口。
8. release版本的优化开启会导致Lua中所有的false被认为是true。这个坑是在ToLua.dll编译的后期遇到的一个奇怪的现象,当时是发现debug的版本跑通了流程,但是release的版本界面无法关闭,排查发现代码中的所有false都当作了true来处理,逐项对比编译差异才发现是优化的选项导致的,最初使用关闭优化的方式来解决,后来蒙哥也提供了解决思路:
对于return bool 的函数都标记为 [return: MarshalAs(UnmanagedType.I1)]:[DllImport("ToLua.dll", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)] //这里指定return bool 类型
public static extern bool Lua_xxxx(); 简单测试可行,另外蒙哥也说可以尝试把Lua的C代码中的所有的bool换成BOOL来处理,这种方式可能更稳妥,但是修改代价稍微大一些,因此没有测试过。
9. 关注下Luajit和Luavm的区别。一方面是比如bit库是有差异的,另外一方面是对于...参数的处理。比如我们提供了一个tryCall函数来封装pcall,并在遇到Traceback的时候上报给错误收集服务器。
local traceback = traceback
if LuaEngine.Util.GetRuntimePlatform() == DeviceHelper.PLATFORM_MACOS then
function ClientUtils.trycall(func, ...)
return func(...)
end
else
function ClientUtils.trycall(func, ...)
local flag, msg = xpcall(func, traceback, ...)
if not flag then
logerror(msg, "LUA ERROR")
ClientUtils.trySendException("ClientUtils", msg)
end
return flag
end
end最初的版本已经踩了这个坑,当时在MacOS平台上使用luavm,如果使用xpcall,则...的可变参数传递会丢失,因此在uwp平台上也使用和MacOS平台相似的处理。
10. 如果要调试ToLua.dll中的代码的话,我使用的是?Attach到进程的方式。首先要在调试配置里选择dll为可调式程序集:
然后可以在编译的后处理里把dll和pdb拷贝到目标工程的运行目录(或者每次自己手动拷贝),接着Ctrl+F5运行游戏(不要调试,因为无法挂接两个调试器),然后在ToLua的工程里附加到进程:
这样就可以断点调试了。如果出了错误,在游戏功能Debug的时候也可以看到Dll的堆栈,所以也许有不需要附加到进程的方式,暂时没有去搞这块,知道的朋友也欢迎提供信息。
4. 结语
零零散散记录一些遇到的问题和解决方式,在处理中也解决了不少游戏内的问题,但是和平台移植关系性不大,就不在此记录了。
总之,希望这些零散的记录可以帮要做uwp移植的朋友绕过一些坑,节省一些开发时间,有问题也欢迎交流。对于uwp版本的tolua.dll的编译工程,我会做一些整理尝试merge到github上,目前需要的朋友可以暂时按照文章里已经列举的流程来做。 |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|