> 技术文档 > 必看!鸿蒙原生游戏开发保姆级指南

必看!鸿蒙原生游戏开发保姆级指南


开篇

毋庸置疑、鸿蒙游戏生态肯定是开发者们的必争之地。

相信很多开发者都想将自己的游戏快速移植到鸿蒙操作系统上,但无奈没有时间去研究细节。

今天这篇游戏鸿蒙原生化保姆级指南,就是为大家精心准备的,希望大家能够喜欢。

开发准备

1.游戏引擎

必看!鸿蒙原生游戏开发保姆级指南必看!鸿蒙原生游戏开发保姆级指南

Cocos 引擎下载:

  • https://www.cocos.com/creator

下载 Cocos Dashboard,推荐使用 Cocos Creator 3.8.6+ 版本。

市面上支持发布鸿蒙原生游戏的引擎数量并不多,阿麟今天就以 Cocos 引擎为例,给大家讲解如何将自己的游戏项目发布为鸿蒙原生游戏。

之所以选择 Cocos 作为讲解,主要有几个考虑。

  1. 目前市面上大量的小游戏都采用 Cocos 制作,这些小游戏也在寻找新的增量,鸿蒙原生游戏就是一个很好的机会。

  2. Cocos 对游戏开发者开源、免费,也不收取任何后期费用,开发者没有成本负担

2.DevEco Studio

必看!鸿蒙原生游戏开发保姆级指南必看!鸿蒙原生游戏开发保姆级指南

下载地址:

  • https://developer.huawei.com/consumer/cn/download/

下载最新稳定版即可。

DevEco Studio 是一个面向全场景多设备的一站式分布式应用开发平台,支持 HarmonyOS 和 OpenHarmony 游戏、应用及服务开发。

对于鸿蒙游戏和应用开发者来说,这个工具是必须掌握的。

3. 开发资料

作为全球第一款支持鸿蒙操作系统的游戏引擎,也作为全球率先与鸿蒙游戏生态深度合作的游戏引擎,Cocos 社区和鸿蒙游戏社区都积累了非常多的产品案例和开发资源,大家可以通过以下途径获得。

  • 发布到鸿蒙:https://docs.cocos.com/creator/3.8/manual/zh/editor/publish/publish-openharmony.html

  • 构建说明:https://developer.huawei.com/consumer/cn/blog/topic/03176120152473057

  • 原生接口交互:https://developer.huawei.com/consumer/cn/blog/topic/03176120896060024

上面的资料已经讲明白了各个环节,接下来,阿麟就带大家走一遍流程,并指出需要重点关注的事项和风险点。

必看!鸿蒙原生游戏开发保姆级指南必看!鸿蒙原生游戏开发保姆级指南

构建发布

1. 平台选择

必看!鸿蒙原生游戏开发保姆级指南必看!鸿蒙原生游戏开发保姆级指南

构建发布时,平台选择记得选择 HarmonyOS NEXT,这才是我们提到的鸿蒙原生项目。

2. 脚本引擎选择

必看!鸿蒙原生游戏开发保姆级指南必看!鸿蒙原生游戏开发保姆级指南

如下图所示,不同的脚本选择,会让引擎的 TS/JS 代码的运行环境不同。

  1. 不管如何选择, 项目中的 ArkTS 代码均在方舟引擎环境中执行。

  2. 选择 Ark 后,引擎中的 TS/JS 代码在方舟引擎环境中执行。

  3. 选择 V8 后,引擎中的 TS/JS 代码在 V8 虚拟机中执行。

  4. 选择 JSVM 后,引擎中的 TS/JS 代码在 JSVM 中执行。

必看!鸿蒙原生游戏开发保姆级指南必看!鸿蒙原生游戏开发保姆级指南

除此之外,不同的引擎脚本环境,也影响脚本的 JIT 和 热更新功能。

引擎

JIT

热更新

JSVM

支持

支持

V8

不支持

支持

Ark

暂不支持

暂不支持

由此可见,构建鸿蒙原生游戏时,脚本引擎推荐选择 JSVM(在 v3.8.7 中会作为默认选项),在鸿蒙原生设备上,JSVM 的功耗、内存开销、性能和稳定性会优于 V8,并且会持续增强。

如果没有特殊需求,则不需要过多修改了,点击 Build(构建) 按钮,等待完成即可。

编译运行

1. 打开项目

构建完成后,启动 DevEco Studio,选择打开项目,选择 项目目录/native/engine/harmonyos-next

必看!鸿蒙原生游戏开发保姆级指南必看!鸿蒙原生游戏开发保姆级指南

由于平台机制问题,鸿蒙原生项目暂时只能放在 native 下。

2. 真机调试

设备要求

你要准备一台支持 HarmonyOS 5.0.1(13)以上的华为手机。

打开手机的 USB 调试
  1. 找到 设置->关于本机->软件版本

  2. 点击 软件版本 6 次,会询问你是否需要打开开发者选项,点击 确认 即可打开。

  3. 打开 设置->系统->开发者选项->USB 调试

  4. 用数据线连接打开了 DevEco Studio 项目的电脑

你应该能在 DevEco Studio 右上角发现你的设备。

必看!鸿蒙原生游戏开发保姆级指南必看!鸿蒙原生游戏开发保姆级指南

设置签名
  1. 在 DevEco Studio 中打开 File -> Project 窗口,切换到 Singing Configs 标签。必看!鸿蒙原生游戏开发保姆级指南必看!鸿蒙原生游戏开发保姆级指南

  2. 勾选自动签名(Automatically generate signature)

  3. 如果未登录,请先登录

  4. 点击确认即可

3. 启动项目

必看!鸿蒙原生游戏开发保姆级指南必看!鸿蒙原生游戏开发保姆级指南

点击右上角的 Run \'entry\' 或者 Debug \'entry\' 即可在真机上预览项目。

如果启动时提示安装失败,有可能是签名设置的问题,请再次检查签名情况。

平台标志

在项目开发中,我们一套项目代码会同时发布到多个平台。

所以通常需要根据具体平台来处理一些特定的功能。

比如鸿蒙原生系统特有的元服务卡片、碰一碰、设备流转等能力,是其他平台没有的。

相关代码就需要使用平台标志进行过滤,才能保证没有问题。

鸿蒙原生平台在 Cocos 引擎中的标志为 sys.OS.OPENHARMONY,使用下面代码即可进行判定。

improt { sys } from \'cc\';if(sys.os == sys.OS.OPENHARMONY){ // 特有的游戏逻辑}

原生通信基础

1. 目录结构

原生通信必然涉及到对项目代码进行改动,我们先来熟悉一下项目目录结构,如下图所示:必看!鸿蒙原生游戏开发保姆级指南

2. 运行线程

Cocos 发布出来的鸿蒙原生游戏项目,有两个线程,用于处理不同的事务。

  1. 主线程:用于执行 ArkTS 代码,系统原生  UI 渲染

  2. Cocos 线程:用于执行引擎渲染和代码脚本

两个线程中的数据不能直接相互访问,需要通过 Worker 的通信机制才能实现。

在 DevEco Studio 打开的项目代码中,cocos_worker.ts 里的代码就是运行在 Cocos 线程中的,其余代码默认是在主线程。

引擎脚本调用原生

callStaticMethod

引擎提供了一个非常方便的接口来调用原生功能,函数原型如下:native.reflection.callStaticMethod(clsPath,methodName,paramStr,isSync)

  • clsPath:string:对应的函数文件位置,无需后缀名

  • methodName:string:方法名称, 模块/方法,如果模块为 entry,可以直接写方法名

  • paramStr:string:参数,如果需要传多个,则需要转为 JSON 字符串,如果无参数,则填空字符串 \'\'

  • isSync:boolean:是否为同步调用,默认为 true

新增原生代码

我们在 DevEco Studio 中新增一个代码文件,比如:src/main/ets/Test.ets

Test.ets里,我们写一个简单的测试函数。 

function test(param:string){    console.log(\'callStaticMethod_test\',param);    return \'native_\' + param;}

在 entry/build_profile.json5 文件中的 buildOption 字段中,加入如下内容,以确保函数能够被正确访问(一定不要忘了!)。

必看!鸿蒙原生游戏开发保姆级指南

我们在 Cocos 引擎中新建一个按钮,新增一个按钮响应脚本函数,写下下面的代码。

if(sys.os == sys.OS.OPENHARMONY){    let result = native.reflection.callStaticMethod(\'entry/src/main/ets/native_api/OSAbility\',\'entry/test\',\'test native call\', true);    console.log(result);}

在引擎的构建面板中再次打包,并在 DevEco Studio 中新运行项目,就可以进行测试了。

参数和返回值仅支持 string|number|boolean 基础类型,如果需要返回对象,请使用 JSON 字符串,并做对应的序列化和反序列化。

执行线程

这里需要注意,虽然我们的 test 函数是被 Cocos 线程中的脚本调用的,但是 test 的执行环境是主线程,如下图所示:

必看!鸿蒙原生游戏开发保姆级指南必看!鸿蒙原生游戏开发保姆级指南

大部分情况下,我们使用 native.reflection.callStaticMethod 是为了调用原生平台的能力(如访问电池余量、网络状态、图片读取等等),这个特性使我们在调用原生功能的时候非常方便。

同步与异步调用

为了更方便地与原生层交互,鸿蒙原生提供了同步和异步两种调用方式,我们以获取电池信息为例。

同步获取电池信息
//原生:entry/src/main/ets/native_api/OSAbility.etsfunction  getBatteryInfo():string{  return JSON.stringify({     batterySOC:batteryInfo.batterySOC //电池电量百分比    ,chargingStatus:batteryInfo.chargingStatus // 电池充电状态  });}//引擎脚本:Test.tslet result = native.reflection.callStaticMethod(\'entry/src/main/ets/native_api/OSAbility\',\'entry/getBatteryInfo\',\'\', true);let batteryInfo = JSON.parse(result);
异步获取电池信息
//原生:entry/src/main/ets/native_api/OSAbility.etsfunction  getBatteryInfoSync(param:string,cb:Function):void{  setTimeout(()=>{    cb(JSON.stringify({      batterySOC:batteryInfo.batterySOC //电池电量百分比    ,chargingStatus:batteryInfo.chargingStatus // 电池充电状态    }));  },10);}//引擎脚本:Test.tslet result = native.reflection.callStaticMethod(\'entry/src/main/ets/native_api/OSAbility\',\'entry/getBatteryInfoSync\',\'\', false);let batteryInfo = JSON.parse(result);

注意1:异步调用会使引擎脚本阻塞等待,因此需要注意那种特别耗时,或者永远不会触发回调的情况。

注意2:v3.8.6 中实现异步调用时,即使用不上也必须保留 param:string 参数,否则调用会导致进程崩溃。(后续版本会优化)

原生调用引擎脚本

cocos.evalString

//引擎中 ABC.tswindow[\'test\'] = (str:string,n:number)=>{    console.log(str,n);}//原生层代码import cocos from \'libcocos.so\';cocos.evalString(`test(\'abc\',3)`);

如上图所示,libcocos.so 提供了一个 evalString函数,用于原生层调用 Cocos 引擎脚本中的全局函数。

线程安全

需要注意的是,cocos.evalString只能在 Cocos 线程中被调用

我们需要修改一下项目源码,才能方便调用。

1. cocos_worker.ts

在 cocos_worker.ts 中,switch case 语句里,添加如下代码,用于接收来自其他线程的 evalString 消息。

case \"evalString\":      cocos.evalString(msg.param);      break;

2. 调用

在需要调用 cocos.evalString 的地方,按照下面方式,向 cocos worker 线程发送消息即可。

import { WorkerManager } from \'../cocos/WorkerManager\';const cocosWorker = WorkerManager.getInstance().getWorker();cocosWorker.postMessage({ type: \"async\", data: { name:\"evalString\", param: `test(\'abc\',3)` } });

注意1:跨线程通信走的是 worker 间的消息机制,其性能远低于直接的函数调用,因此需要避免高频调用。

3. 覆盖处理

已知问题:v3.8.6 中,cocos_worker.ts 会在每一次构建时被还原,此问题会在 v3.8.7 中修复。

但对于 v3.8.6 的开发者,可以用下面的方式解决。

  1. 复制一个 cocos_worker.ts 到项目根目录下(与 assets 平级),后期对 cocos_worker.ts 的修改,以这个文件为主

  2. 新建一个构建扩展

  3. 在构建扩展的 hook.ts 中的 onAfterBuild 里,添加如下代码:

if(options.platform === \'harmonyos-next\' ){    let src = `${Editor.Project.path}/cocos_worker.ts`;    let dest = `${Editor.Project.path}/native/engine/harmonyos-next/entry/src/main/ets/workers/cocos_worker.ts`;    console.log(`copy ${src} to ${dest}`);    const fs = require(\'fs\');    fs.writeFileSync(dest, fs.readFileSync(src)); }

编译扩展:

npm installnpm run build

刷新扩展后,再次打包,就可以实现 cocos_worker.ts 的修改生效了。

结束语

以上就是 Cocos 项目进行鸿蒙原生化的主要流程、经验与注意事项,通过这份指南,相信大家能够快速上手鸿蒙原生游戏开发,抢占市场先机。

后续我们还会持续分享更多鸿蒙原生适配、能力接入、开发调试等相关内容,并同步优化开发者文档,助力开发者轻松上架鸿蒙原生游戏。

欢迎关注 Cocos 官方公众号,第一时间获取更多实用信息与技术干货。

必看!鸿蒙原生游戏开发保姆级指南
玫瑰情缘网