【心得】CocosCreator3.0.0 构建广告用playable单一Html

Creator 版本:3.0.0 - 3.0.1
目标平台:Html

先放上Demo连结,大佬们可以下载index.html来玩玩:
https://github.com/LoS-Light/CocosCreator3.0_SingleHtmlPlayable

部分Demo图片:
(视频)

[Ammo物理]

[模型动画]

正文:
因公司要發展Playable Ads, 故投入这方面的研究。
在CocosCreator2.x版,可以参考这两位大佬的文章来做到建构单一Html,
感谢(fkworld & chongshengzhujue)
fkworld:https://github.com/fkworld/cocos-to-playable-ad
chongshengzhujue:https://github.com/chongshengzhujue/playableFBCompile

但从3.0版开始,因引擎使用了SystemJs来管控模块,
故上述提供的工具皆无法使用了。
但因公司的需求,
故只好从零自己着手开發3.0专用的自动化转换单一Html的工具,
首先遇到的问题就是SystemJs,
因SystemJs引用模块都是透过路径来取用外部档案,
没有提供任何可以直接引用同一份文件内的脚本 ( <- 或许可能有提供,但我不知道也说不定),
故在这裡折腾了几天去魔改了SystemJs,
让它能够以相同的路径,但将它取用的资源从外部档案转为指向同一份Html裡的script tag区块,
这样第一步就算完成了。
接下来是引擎资源&游戏资源的部分,
这部分可以参考上述大佬们之前的作法,
包进引擎资源到Html裡:
style.css
cc.js
index.js
bundle.js
system.bundle.js
polyfills.bundle.js
settings.json
import-map.json

然后改写application.js,
自定义自己的游戏资源载入方案,
cc.assetManager.downloader.register(‘bundle’, downloadBundleHandler);
cc.assetManager.downloader.register(’.png’, arrayBufferHandler);
cc.assetManager.downloader.register(’.jpg’, arrayBufferHandler);
cc.assetManager.downloader.register(’.jpeg’, arrayBufferHandler);
cc.assetManager.downloader.register(’.ttf’, downloadFont);
cc.assetManager.downloader.register(’.plist’, downloadText);
cc.assetManager.downloader.register(’.json’, downloadJson);
cc.assetManager.downloader.register(’.bin’, downloadArrayBuffer);
cc.assetManager.downloader.register(’.mp3’, downloadWebAudio);
cc.assetManager.downloader.register(’.ogg’, downloadWebAudio);
cc.assetManager.downloader.register(’.wav’, downloadWebAudio);
cc.assetManager.downloader.register(’.mp4’, downloadVideo);
这样第二部引擎&游戏资源的部分也完成了。

再来是物理的部分,因Ammo Physics的资源并没有包进cc.js裡,而是产生6个外部档案,
wait-for-ammo-instantiation.js
_commonjsHelpers.js
ammo.js
ammo-instantiated.js
ammo.wasm.js
ammo.wasm
故大佬您也得将它们的代码包进Html裡。

这样前前后后折腾了两个礼拜后,终于作出了上述的展示用单一Html,
但这自动化工具还有很多内容没有测试以及实作,
例如整个Html的资源压缩,各playable广告渠道的支持等等,
故还无法用于production上,
所以暂时还不会公开本自动化工具,
但如果有能力的大佬,
可以按照上述提的思路来自行实作。

10赞

试玩了一下,这种方式很有意思。

1赞

厉害了, 期待开放自动化工具。。

1赞

我用 2.4 合并 json 引擎修改
var downloadJson = function downloadJson(url, options, onComplete) {
options.responseType = “json”;
let resg = url.split("/")[url.split("/").length -1];
if (window.resJsons[resg]) {
if (“string” === typeof window.resJsons[resg]) {
let data = JSON.parse(window.resJsons[resg]);
onComplete && onComplete(null, data);
} else {
onComplete && onComplete(null, window.resJsons[resg]);
}

  } else {
    downloadFile(url, options, options.onFileProgress, (function(err, data) {
      if (!err && "string" === typeof data) try {
        data = JSON.parse(data);
      } catch (e) {
        err = e;
      }
      onComplete && onComplete(err, data);
    }));
  }
};

请指点一下 问题 vconsole.min.js:10 Please load bundle internal first Error: Please load bundle internal first

我不太确定您的错误是什麽,
但我记得没错的话,
2.4版json的加载变成透过bundle了,
以下是改写的参考代码,
您试试。

cc.assetManager.downloader.register(‘bundle’, downloadBundleHandler);

function downloadBundleHandler(nameOrUrl, options, onComplete) {
    let bundleName = cc.path.basename(nameOrUrl);
    let url = nameOrUrl;
    if (!REGEX.test(url)) url = 'assets/' + bundleName;
    var version = options.version || cc.assetManager.downloader.bundleVers[bundleName];
    var count = 0;
    var config = `${url}/config.${version ? version + '.' : ''}json`;
    let out = null, error = null;

    downloadJson(config, options, function (err, response) {
        if (err) {
            error = err;
        }
        out = response;
        out && (out.base = url + '/');

        count++;
        if (count === 2) {
            onComplete(error, out);
        }
    });

    var js = `${url}/index.${version ? version + '.' : ''}js`;
    downloadScript(js, options, function (err) {
        if (err) {
            error = err;
        }
        count++;
        if (count === 2) {
            onComplete(error, out);
        }
    });
};

function downloadScript(url, options, onComplete) {
    var d = document, s = document.createElement('script');

    s.type = "text/javascript";
    s.charset = "utf-8";
    s.text = window.resMap[url];

    d.body.appendChild(s);

    onComplete(null);
}

function downloadJson(url, options, onComplete) {
    let data = window.resMap[url];
    data = JSON.parse(data);
    onComplete(null, data);
};

厉害了~~~

1赞

我的流程 是 2.4.3版本 修改web 打包后 把所有 的 json 合并到 ,引擎找 json 导致 找不 我就 修改了 一下 downloadBundleHandler 下载方式 如果 合并 中有 直接使用 ,onComplete(err, data); 回掉参数 报错了 说
Please load bundle internal first Error: Please load bundle internal first

目的是 把 这个时间优化掉 2.4.4 合并了 大多数 json 但是 加载速度没有明显变化

你好 问下text 和 Image 怎么重写

厉害了~~~

抱歉这么晚才回覆,
请问您是要问2.x还是3.x的版本,
两种版本写法是不一样的。

3.x版本要如何修改

这里是我的写法,您可能要视情况修改一下后,成为您的版本。

cc.assetManager.downloader.register('.png', arrayBufferHandler);
cc.assetManager.downloader.register('.jpg', arrayBufferHandler);
cc.assetManager.downloader.register('.jpeg', arrayBufferHandler);
cc.assetManager.downloader.register('.ttf', downloadFont);

function arrayBufferHandler(url, options, callback, img) {
var data = window.resMap[url];

    var img = new Image();
    function loadCallback() {
        img.removeEventListener('load', loadCallback);
        img.removeEventListener('error', errorCallback);

        callback(null, img);
    }
    function errorCallback() {
        img.removeEventListener('load', loadCallback);
        img.removeEventListener('error', errorCallback);

        callback(new Error('Load image (' + url + ') failed'));
    }

    img.addEventListener('load', loadCallback);
    img.addEventListener('error', errorCallback);
    img.src = data;
};

function getFontFamily(fontHandle) {
    var ttfIndex = fontHandle.lastIndexOf(".ttf");
    if (ttfIndex === -1) {
        ttfIndex = fontHandle.lastIndexOf(".tmp");
    }
    if (ttfIndex === -1) return fontHandle;

    var slashPos = fontHandle.lastIndexOf("/");
    var fontFamilyName;
    if (slashPos === -1) {
        fontFamilyName = fontHandle.substring(0, ttfIndex) + "_LABEL";
    } else {
        fontFamilyName = fontHandle.substring(slashPos + 1, ttfIndex) + "_LABEL";
    }
    return fontFamilyName;
}

function downloadFont(url, options, onComplete) {
    let fontFamilyName = getFontFamily(url);
    let data = "url(data:application/x-font-woff;charset=utf-8;base64,PASTE-BASE64-HERE) format(\"woff\")";
    data = data.replace("PASTE-BASE64-HERE", window.resMap[url]);

    let fontFace = new FontFace(fontFamilyName, data);
    document.fonts.add(fontFace);

    fontFace.load();
    fontFace.loaded.then(function () {
        onComplete(null, fontFamilyName);
    }, function () {
        cc.warnID(4933, fontFamilyName);
        onComplete(null, fontFamilyName);
    });
}

好的 谢谢您

:+1::+1::+1::+1::+1:

你好 问一下 3d模型要怎么修改 (.FBX 文件)

您指的FBX修改是什麽意思,能够更加详细说明您的问题吗?

谢谢大佬,解决了,之前是3d模型加载方式有问题,修改bin加载方式好了

请问downloadWebAudio这个是怎么实现的。

mark.

不好意思,回覆晚了,抱歉

function downloadWebAudio(url, options, onComplete) {
    var context = new (window.AudioContext || window.webkitAudioContext)();

    var data = window.resMap[url];
    data = base64toArray(data);

    context["decodeAudioData"](data.buffer, function (buffer) {
        onComplete(null, buffer);
    }, function (e) {
        onComplete(e, null);
    });
}