摘要

对cocos进行定制js引擎主要是去掉uuid重复问题,以及bundle加载一次后不在加载问题。

版本说明

使用 CocosCreator 的 2.4.15 版本。

  1. 在引擎代码目录cocos-engine-2.4.15\cocos2d\core\platform下添加hall.js脚本

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    // const downloadScript = require('../asset-manager/download-script');
    var js = require('./js');
    // const hall = require('../platform/hall');
    // var downloadScript = require('./../asset-manager/download-script');
    var hall = {

    /**
    * 是否进入子游戏,如果是子游戏则会在
    * CCClass中记录 347
    * 如果为true则会记录当前加载的uuid和classname
    */
    isChildGame:false,
    };
    (function () {
    var _uuidToClass = [];
    var _nameToClass = [];
    var _scriptPathUrl = '';
    var downloaded = {};
    /**
    * 设置脚本名称和脚本uuid
    * @method setClassByNameAndUuid
    * @param {String,String} classname,classuuid
    * @return {Function} constructor
    */
    hall.setClassByNameAndUuid = function (classname,classuuid) {
    _nameToClass.push(classname);
    _uuidToClass.push(classuuid);
    };
    /**
    * 设置脚本名称
    * @method setClassByName
    * @param {String} classname
    * @return {Function} constructor
    */
    hall.setClassByName = function (classname) {
    _nameToClass.push(classname);
    };
    /**
    * 设置脚本uuid
    * @method setClassByUuid
    * @param {String} classuuid
    * @return {Function} constructor
    */
    hall.setClassByUuid = function (classuuid) {
    _uuidToClass.push(classuuid);
    };
    /**
    * 设置当前加载的脚本路径
    * @method setScriptPathUrl
    * @param {String} path
    * @return {Function} constructor
    */
    hall.setScriptPathUrl = function (path) {
    _scriptPathUrl = path;
    };
    /**
    * 设置下载的脚本状态 用于标记是否还去下载新的脚本
    * @method setDownloaded
    * @param {x:string} obj
    * @return {Function} constructor
    */
    hall.setDownloaded = function (obj) {
    downloaded = obj;
    };

    /**
    * 设置下载的脚本状态 用于标记是否还去下载新的脚本
    * @method getTest
    * @return {Function} constructor
    */
    hall.getTest = function () {
    // _scriptPathUrl = path;
    console.log("打印uuid");
    console.log(_uuidToClass);
    console.log("打印Class");
    console.log(_nameToClass);
    console.log("打印全部加载下载js");
    console.log(downloaded);
    console.log("打印当前加载的js路径");
    console.log(_scriptPathUrl);
    // console.log(downloadScript);
    return _uuidToClass;
    };

    /**
    * 注销子游戏的所有js类和uuid 并取消设置下载记录
    * @method unregisterChildGameClass
    * @return {Function} constructor
    */
    hall.unregisterChildGameClass = function () {
    // 注销掉js中的类以及uuid
    // js脚本492左右
    js.unregisterChildGameClass(_nameToClass,_uuidToClass);
    _nameToClass = [];
    _uuidToClass = [];
    downloaded[_scriptPathUrl] = null;
    hall.isChildGame = false;
    };
    })();
    /**
    * 表示引擎层面
    * download-script脚本表示h5的网页版本

    if(hall.isChildGame){
    hall.setScriptPathUrl(url);
    };
    hall.setDownloaded(downloaded);

    */
    /**
    * 原生层面
    * resources\.editors\Creator\2.4.x\resources\builtin\jsb-adapter\engine
    * engine:适配引擎层面的一些 api
    * jsb-loader.js 60行左右

    if(cc['hall'].isChildGame){
    cc['hall'].setScriptPathUrl(url);
    };
    cc['hall'].setDownloaded(loadedScripts);

    */

    // hall.unregisterChildGameClass = function () {};
    /**
    * 需要在js中添加该方法进行注销掉
    js.unregisterChildGameClass = function (name,uuid) {
    for (var i = 0; i < name.length; i++) {
    var classname = name[i];
    delete _nameToClass[classname];
    }
    for (var k = 0; k < uuid.length; k++) {
    var classuuid = uuid[i];
    delete _idToClass[classuuid];
    }
    };
    */

    cc['hall'] = hall;

    module.exports = hall;
  2. 在CCClass中define方法中添加判断当前加载的是否为子游戏判断,如果是子游戏则开始记录子游戏的uuid和className

    1
    2
    3
    if(hall.isChildGame){
    hall.setClassByNameAndUuid(className,uuid);
    }

    0

  3. 在js脚本中添加注销指定数组的uuid和className方法主要是hall脚本进行调用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    /**
    * hall脚本调用注销掉当前脚本
    * @method unregisterChildGameClass
    * @param {*} name 数组
    * @param {*} uuid 数组
    */
    js.unregisterChildGameClass = function (name,uuid) {
    for (var i = 0; i < name.length; i++) {
    var classname = name[i];
    delete _nameToClass[classname];
    };
    for (var k = 0; k < uuid.length; k++) {
    var classuuid = uuid[k];
    delete _idToClass[classuuid];
    };
    };

    2

  4. 在resources.editors\Creator\2.4.x\resources\builtin\jsb-adapter\engine下修改jsb-loader.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    // 判断是否存在
    if(cc['hall']){
    if(cc['hall'].isChildGame){
    cc['hall'].setScriptPathUrl(url);
    };
    cc['hall'].setDownloaded(loadedScripts);
    }else{
    console.warn("当前项目不支持大厅,cc上缺少hall方法");
    }

    1

  5. 大厅使用方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    // 加载方法
    test(name) {
    // 在进入子游戏前进行设置
    //@ts-ignore
    cc.hall.isChildGame = true;
    // 获取路径
    let path = jsb.fileUtils.getWritablePath() + name;
    console.log('-----path----',path);

    cc.assetManager.loadBundle(`${path}/assets/bundle1`, (err, bundle) => {
    if (err) {
    // 删除文件夹并退出
    return;
    }
    try {
    // 加载场景闪屏问题有所优化
    cc.director.preloadScene('game', (completedCount, totalCount, item) => {
    }, () => {
    // 加载分包中的场景
    bundle.loadScene('game', (err, scene) => {
    // 加载完成后运行Bundle包中指定的场景
    //@ts-ignore
    console.log(cc.hall.getTest());
    cc.director.runScene(scene);
    //@ts-ignore

    });
    })
    } catch (e) {
    // 游戏错误
    cc.game.end();
    }
    });
    }


    // 销毁方法
    // 释放bundle
    // 获取当前bundle
    let b = cc.assetManager.getBundle('bundle1');
    // 释放资源
    b.releaseAll();
    // 移除bundle
    cc.assetManager.removeBundle(b);
    //@ts-ignore
    cc.hall.unregisterChildGameClass();
    cc.director.loadScene('loading')