CocosCreator3.x打包后嵌入到uniapp
首先Cocos本身就支持跨平台,可以打包成APP,但由于项目中游戏只是APP的一部分,还有其他界面要开发,用游戏引擎来写APP的一些交互逻辑页面确实不太合适,所以在技术选型上又选择uniapp。
uniapp的web-view是可以嵌入在线的地址和本地的html页面,但嵌入本地的html仅支持APP端,如果你开发需要兼容多端,那么直接使用在线地址的形式嵌入即可,下面的内容也不必阅读了。
需求上因为只需要支持APP端即可,并且使用在线地址嵌入在等待游戏加载的时间有点久,所以我选用了将游戏打包成h5并以本地html页面嵌入到uniapp形式,可以省去了请求游戏引擎js等文件的所需要消耗的时间。
但在嵌入发生一些意外,游戏页面加载时会报 file 协议跨域,从而加载游戏失败,在Cocos论坛找到了解决方案:
在游戏项目的构建模板中修改 fetch 函数:
(构建模板在游戏引擎编辑器左上角菜单栏-项目-创建项目构建模板(选择对应的构建平台)-web手机端即可创建)
function fetchLocal(url) {
return new Promise(function (resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.onload = function () {
resolve(
new Response(xhr.response, {
status: 200
})
);
};
xhr.onerror = function () {
reject(new TypeError("Local request failed"));
};
xhr.open("GET", url);
xhr.responseType = "arraybuffer";
xhr.send(null);
});
}
window.fetch = fetchLocal;
如果你的游戏需要使用到 fetch 来进行网络请求,你可以额外使用 window 全局属性来替代原来的 fetch:
// 在window.fetch被修改为fetchLocal之前赋值
window.fetchRemote = window.fetch;
function fetchLocal(url) {
...
}
window.fetch = fetchLocal;
还有,如果你游戏还用到远程服务器上的图片作为背景啥的,那么在运行时也应该会发生跨域问题的;
所以你还需要在修改Image对象:
let OldImage = Image;
let oldProto = Image.prototype;
Image = function (width, height) {
let image = new OldImage(width, height);
image.crossOrigin = "anonymous";
Object.defineProperty(image, "crossOrigin", {
set() {
return true;
}
});
return image;
};
Image.prototype = oldProto;
完整的构建模板代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title><%= projectName %></title>
<!--http://www.html5rocks.com/en/mobile/mobifying/-->
<meta
name="viewport"
content="width=device-width,user-scalable=no,initial-scale=1,minimum-scale=1,maximum-scale=1,minimal-ui=true"
/>
<!--https://developer.apple.com/library/safari/documentation/AppleApplications/Reference/SafariHTMLRef/Articles/MetaTags.html-->
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="format-detection" content="telephone=no" />
<!-- force webkit on 360 -->
<meta name="renderer" content="webkit" />
<meta name="force-rendering" content="webkit" />
<!-- force edge on IE -->
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="msapplication-tap-highlight" content="no" />
<!-- force full screen on some browser -->
<meta name="full-screen" content="yes" />
<meta name="x5-fullscreen" content="true" />
<meta name="360-fullscreen" content="true" />
<!--fix fireball/issues/3568 -->
<!--<meta name="browsermode" content="application">-->
<meta name="x5-page-mode" content="app" />
<!--<link rel="apple-touch-icon" href=".png" />-->
<!--<link rel="apple-touch-icon-precomposed" href=".png" />-->
<link rel="stylesheet" type="text/css" href="<%= cssUrl %>" />
</head>
<body>
<div id="GameDiv" cc_exact_fit_screen="true">
<div id="Cocos3dGameContainer">
<canvas
id="GameCanvas"
oncontextmenu="event.preventDefault()"
tabindex="99"
></canvas>
</div>
</div>
<script>
window.fetchRemote = window.fetch;
let OldImage = Image;
let oldProto = Image.prototype;
Image = function (width, height) {
let image = new OldImage(width, height);
image.crossOrigin = "anonymous";
Object.defineProperty(image, "crossOrigin", {
set() {
return true;
}
});
return image;
};
Image.prototype = oldProto;
function fetchLocal(url) {
return new Promise(function (resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.onload = function () {
resolve(
new Response(xhr.response, {
status: 200
})
);
};
xhr.onerror = function () {
reject(new TypeError("Local request failed"));
};
xhr.open("GET", url);
xhr.responseType = "arraybuffer";
xhr.send(null);
});
}
window.fetch = fetchLocal;
</script>
<!-- 注意上面的脚本排在 include(cocosTemplate, {}) 前面 -->
<%- include(cocosTemplate, {}) %>
<!-- 用于和uniapp通信 -->
<script src="src/uni.webview.1.5.4.js"></script>
</body>
</html>