Cocos Creator 资源加载流程剖析【五】——从编辑器到运行时

我们在编辑器中看到的资源,在构建之后会进行一些转化,本章将揭开Creator对资源进行的处理。

资源处理的整体规则

首先我们将Creator的开发和运行划分为以下几个场景:

编辑器

当我们将资源放到编辑器中时,Creator会为每个资源生成唯一的uuid以及meta文件,并在项目的library目录下生成对应的json文件来描述这个资源的信息,而uuid与资源的映射关系被放在library目录下的uuid-to-mtime.json文件中。由于资源的引用关系是靠uuid来维系的,所以我们可以在Creator中随意地修改资源文件名、移动资源路径,而不用担心资源的关联丢失问题。

我们在编辑器中编辑的prefab、anim、场景等文件本质上是一个json文件,Cocos Creator 设计了一套json规则用于描述各种资源,prefab的json描述了prefab的结构以及每个节点的属性,但部分属性会放到meta文件中,一般是针对该资源在编辑器中的设置。

预览

预览的时候使用的是library目录下的资源,不仅仅是项目assets目录下的所有资源(包括未被引用到的资源),引擎提供的一些默认资源也可以在library目录下找到。预览的模板位于引擎安装目录下的resources/static/preview-templates,程序的启动脚本为boot.js。

构建

项目构建之后,资源会从library目录下移动到构建输出的目录中,基本只会导出参与构建的场景和resources目录下的资源,及其引用到的资源。脚本资源会由多个js脚本合并为一个js,各种json文件也会按照特定的规则进行打包(所谓的packAssets)。

各种资源的处理

  • 基础图片

图片的meta文件大概如下所示,除了ver和uuid之外,还有3个属性:

  • Type有sprite和raw两种,如果选择了raw,那么就不会有subMetas等属性,而且在Creator的资源管理器面板中可以发现这个图片左边的小箭头消失了。
  • WrapMode为环绕模式,包含clamp差值和repeat重复两种,但这里的设置在Creator中一般是无效的,因为在Sprite组件中是用Type进行控制,它提供了九宫格、平铺、填充等方式。
  • FilterModel提供了3种差值过滤选项,Point点差值、Bilinear双线性差值、Trilinear三线性差值,性能依次下降,效果依次提升。

这里的subMetas描述了一个SpriteFrame信息,详情可参考Sprite组件

{
  "ver": "2.0.0",
  "uuid": "a0576798-bdf4-4f06-972e-5557dee6ee1b",
  "type": "sprite",
  "wrapMode": "clamp",
  "filterMode": "bilinear",
  "subMetas": {
    "boss_b_hp1": {
      "ver": "1.0.3",
      "uuid": "5425ad9a-e2e0-4c6e-825b-c3ea43b09e4e",
      "rawTextureUuid": "a0576798-bdf4-4f06-972e-5557dee6ee1b",
      "trimType": "auto",
      "trimThreshold": 1,
      "rotated": false,
      "offsetX": 0,
      "offsetY": 0,
      "trimX": 0,
      "trimY": 0,
      "width": 78,
      "height": 78,
      "rawWidth": 78,
      "rawHeight": 78,
      "borderTop": 0,
      "borderBottom": 0,
      "borderLeft": 0,
      "borderRight": 0,
      "subMetas": {}
    }
  }
}

这样的一个图片会在library/imports/xx目录下生成3个文件(如果将图片的type设置为raw则不会有SpriteFrame对应的json文件),分别是以图片uuid为文件名的json文件和png,以及SpriteFrame的uuid为文件名的json文件

Texture对应的json文件内容如下,每一个纹理都会生成一个这样的重复的文件:

{
  "__type__": "cc.Texture2D",
  "content": "0"
}

SpriteFrame对应的json文件内容如下:

{
  "__type__": "cc.SpriteFrame",
  "content": {
    "name": "boss_b_hp1",
    "texture": "a0576798-bdf4-4f06-972e-5557dee6ee1b",
    "atlas": "",
    "rect": [
      0,
      0,
      78,
      78
    ],
    "offset": [
      0,
      0
    ],
    "originalSize": [
      78,
      78
    ]
  }
}

在构建之后,资源会被导出到res目录下,json文件放在import目录下,png等资源文件放在raw-assets目录

  • 图集资源

图集分为plist和图片两个文件,图集图片的meta和普通图片的meta一样,而plist文件的meta记录了图集中所有碎图的信息。主要有ver、uuid、rawTextureUuid、size、type以及subMetas等属性,subMetas记录了每一个碎图的meta信息,结构和普通图片的meta一样。

{
  "ver": "1.2.4",
  "uuid": "315d61c8-b6c8-4635-b517-f868dd8b3495",
  "rawTextureUuid": "01979186-b9a2-4130-a307-a2eacb5fe30f",
  "size": {
    "width": 1024,
    "height": 1024
  },
  "type": "Texture Packer",
  "subMetas": {
    "role1001-move1.png": {
      "ver": "1.0.3",
      "uuid": "8e225dbc-7905-416f-a7ac-0730893ad30d",
      "rawTextureUuid": "01979186-b9a2-4130-a307-a2eacb5fe30f",
      "trimType": "auto",
      "trimThreshold": 1,
      "rotated": false,
      "offsetX": 0,
      "offsetY": -52,
      ...

在library目录下会生成plist的json文件,type为cc.SpriteAtlas,记录了图集中所有spriteFrames的uuid,每一个碎图都会有一个描述其SpriteFrame的json文件生成。最后,图片文件照常会有一个Texture和SpriteFrame的json生成。

{
  "__type__": "cc.SpriteAtlas",
  "_name": "role1001.plist",
  "_objFlags": 0,
  "_native": "",
  "_spriteFrames": {
    "role1001-move1": {
      "__uuid__": "8e225dbc-7905-416f-a7ac-0730893ad30d"
    },
    "role1001-move2": {
      "__uuid__": "7e0641ef-5974-4c2d-bad3-80c59a3195d8"
    },
    ...

构建之后,cc.SpriteAtlas与所有的cc.SpriteFrame会合为一个json,而图片本身仍然会导出cc.Texture和cc.SpriteFrame的json。

【合并初始场景依赖的所有json】会让所有用到的json都合并成一个。【内联所有SpriteFrame】会将所有用到的SpriteFrame的json信息复制到引用它们的场景或prefab的json中,如果是单独的一个SpriteFrame,会被直接合并。(这种情况下,其他场景加载该资源时如何处理?即该资源已经被打包到其他场景或prefab中。多个prefab同时引用时谁能打包到该资源呢?加载一个打包资源中的一个json,是否会直接加载该json包中的所有json)

  • AutoAtlas自动图集

AutoAtlas可以自动将当前目录以及子目录下所有的图片进行合图,他的meta文件描述了合图的规则,如最大尺寸、是否允许旋转、是否强制图片转为正方形、尺寸是否为2的幂、使用的合图算法等等...

{
  "ver": "1.1.0",
  "uuid": "691bdbcd-78c9-41da-864f-481d1af5c8ff",
  "maxWidth": 1024,
  "maxHeight": 1024,
  "padding": 2,
  "allowRotation": true,
  "forceSquared": false,
  "powerOfTwo": true,
  "heuristices": "BestAreaFit",
  "format": "png",
  "quality": 80,
  "contourBleed": false,
  "paddingBleed": false,
  "filterUnused": false,
  "subMetas": {}
}

而在library目录下,AutoAtlas只会生成一个简单的json文件,在预览的时候,AutoAtlas不会发生任何作用。

{
  "__type__": "cc.SpriteAtlas",
  "_name": "AutoAtlas"
}

构建之后,会生成cc.SpriteAtlas类型的一个json文件,记录所有碎图的uuid。AutoAtlas所在目录下的碎图会合成一张,而它们的SpriteFrame信息则不会像plist图集一样合并到图集的json文件中,而是每个SpriteFrame一个json文件。

{
  "__type__": "cc.SpriteAtlas",
  "_spriteFrames": {
    "building_01": {
      "__uuid__": "d47RnkKqBHw6xXpAKXUDWt"
    },
    "building_02": {
      "__uuid__": "a8CDt9ghBA5LzcZdD79OcY"
    },
    "building_03": {
      "__uuid__": "f4JnL6lkFFjZC9QkBYLbZM"
    },
    "building_04": {
      "__uuid__": "0cwdvX5/pBXYpf4xhZG+I+"
    },
    "building_05": {
      "__uuid__": "64GzrRUetDzreLftZ9Unt5"
    }
  }
}
  • 场景与prefab

场景和prefab类似,都是用一个json文件来描述节点树。json文件首先描述一个数组,数组的第一个元素(下标0)描述的是该资源的类型以及该资源特定的属性,接下来是一个一个的节点、组件对象,每个对象都描述了自身的各种属性,以及它们和其它对象的关系,其中的__id__字段对应的值表示当前json数组的下标。

[
  // 数组的第一个元素,资源概述
  {
    "__type__": "cc.prefab",    // 类型,场景的__type__为cc.SceneAsset
    "_name": "",
    "_objFlags": 0,
    "_native": "",
    "data": {                   // 数据(该prefab的根节点id),场景为scene字段
      "__id__": 1
    },
    "optimizationPolicy": 0,    // 创建优化策略(场景无该选项)
    "asyncLoadAssets": false    // 是否开启延迟加载资源(场景无该选项)
  },
  
  // 数组的第二个元素,prefab的根节点,其name为Base,有2个子节点,id为2和5
  {
    "__type__": "cc.Node",
    "_name": "Base",
    "_objFlags": 0,
    "_parent": null,
    "_children": [
      {
        "__id__": 2
      },
      {
        "__id__": 5
      }
    ],
    "_tag": -1,
    "_active": true,
    "_components": [],
    "_prefab": {
      "__id__": 8
    },
    "_id": "",
    "_opacity": 255,
    "_color": {
      "__type__": "cc.Color",
      "r": 255,
      "g": 255,
      "b": 255,
      "a": 255
    },
    "_cascadeOpacityEnabled": true,
    "_anchorPoint": {
      "__type__": "cc.Vec2",
      "x": 0.5,
      "y": 0.5
    },
    "_contentSize": {
      "__type__": "cc.Size",
      "width": 0,
      "height": 0
    },
    "_rotationX": 0,
    "_rotationY": 0,
    "_scaleX": 1,
    "_scaleY": 1,
    "_position": {
      "__type__": "cc.Vec2",
      "x": 0,
      "y": 0
    },
    "_skewX": 0,
    "_skewY": 0,
    "_localZOrder": 0,
    "_globalZOrder": 0,
    "_opacityModifyRGB": false,
    "groupIndex": 0
  },
  {
    ...
  },
  // Sprite组件的数据,它挂载在本数组中下标为2的Node上(第三个元素)
  {
    "__type__": "cc.Sprite",
    "_name": "",
    "_objFlags": 0,
    "node": {
      "__id__": 2
    },
    "_enabled": true,
    "_spriteFrame": {
      // 所有的__uuid__都指向了一个新的资源
      "__uuid__": "d4ed19e4-2aa0-47c3-ac57-a402975035ad"
    },
    "_type": 0,
    "_sizeMode": 1,
    "_fillType": 0,
    "_fillCenter": {
      "__type__": "cc.Vec2",
      "x": 0,
      "y": 0
    },
    "_fillStart": 0,
    "_fillRange": 0,
    "_isTrimmedMode": true,
    "_srcBlendFactor": 770,
    "_dstBlendFactor": 771,
    "_atlas": null
  },
  {
    "__type__": "cc.prefabInfo",
    "root": {
      "__id__": 1
    },
    "asset": {
      "__id__": 0
    },
    "fileId": "acUWY0/UZLeZdVqtcRkZuq",
    "sync": false
  },
  ...
]
  • 关于资源依赖和prefab嵌套
    • 场景和prefab依赖的资源,我们都可以在它们的json文件中,找到__uuid__这样的属性,通过这个字段记录了资源间的依赖。
    • 查看了最新的CocosCreator2.x,目前的prefab还不支持真正意义上的嵌套,目前的嵌套prefab本质上是将一个prefab的内容拷贝到另一个prefab中。
  • 关于挂载脚本
    • 自定义的脚本组件挂载到prefab或场景的某节点时,在json文件中生成的组件对象的__type__对应的是该脚本的23位uuid。
    • 脚本定义了资源类变量,可在属性检查器中拖拽资源赋给脚本变量的,prefab会记录该资源的__uuid__,如果拖拽了prefab自身的节点,则记录其__id__
    // 组件的__type__为脚本的23位uuid
    "_components": [
      {
        "__type__": "b8386waIgRGVJwXT7yno4pm",
        "node": {
          "__id__": 1
        },
        // myRootNode和mySpriteFrame为脚本中的2个变量,在属性检查器中拖拽的
        "myRootNode": { // myRootNode记录着当前prefab中id为2的节点
          "__id__": 2
        },
        "mySpriteFrame": {  // mySpriteFrame记录着一个外部的SpriteFrame的uuid
          "__uuid__": "40t3EpX7tCnq5b2lM2bG8F"
        },
      }
    ],

Scene和prefab对应的meta文件比较简单,prefab包含了创建优化策略选项,Scene包含了是否自动释放资源选项,他们都包含了是否延迟加载资源的选项。大致如下所示:

// prefab的meta文件内容
{
  "ver": "1.0.0",
  "uuid": "c7d921c2-6021-4613-93bd-6201de418e24",
  "optimizationPolicy": "AUTO",
  "asyncLoadAssets": false,
  "subMetas": {}
}

// scene文件的meta文件内容
{
  "ver": "1.0.0",
  "uuid": "2afc2a6e-f61e-4f46-8a52-af34d838a4b0",
  "asyncLoadAssets": false,
  "autoReleaseAssets": false,
  "subMetas": {}
}

在library目录下,以及构建目录中,prefab和scene基本是json文件本身内容的一个复制。可能会根据prefab和scene的选项稍微修改json数组首元素的内容(比如添加asyncLoadAssets字段)。

  • Creator动画

Creator动画保存在anim文件中,每一个anim都是一个动画Clip。我们可以在Creator中的资源管理器右键/新建/Animation Clip来创建新的anim动画文件。要使用动画我们需要为一个节点挂载Animation组件,然后将anim文件拖拽到Animation组件的clips属性中。关于Creator动画的更多详情可以参考官方文档 https://docs.cocos.com/creator/manual/zh/animation/

anim文件本质是一个json文件,它的内容大致如下,除了Creator标准的json字段,以及Clip的全局属性(wrapMode、speed等)外,curveData字段记录所有的动画信息,events字段记录了该动画中所有的帧事件。它的meta文件只记录了ver、uuid以及一个空的subMetas。

{
  "__type__": "cc.AnimationClip",
  "_name": "1",
  "_objFlags": 0,
  "_native": "",
  "_duration": 0.25,
  "sample": 60,
  "speed": 1,
  "wrapMode": 1,
  "curveData": {
    "paths": {
      "build_b_2": {
        "props": {
          "position": [
            {
              "frame": 0,
              "value": [
                39,
                29
              ]
            },
            {
              "frame": 0.25,
              "value": [
                109,
                29
              ]
            }
          ]
        }
      }
    }
  },
  "events": [
    {
      "frame": 0.25,
      "func": "",
      "params": []
    }
  ]
}

该文件会被直接拷贝到library目录下,构建之后会直接导出该文件。

  • 声音音效类资源

声音音效资源的meta文件非常简单,目前唯一的一个自定义属性就是downloadMode,即声音的加载模式,有Web Audio和DOM Audio两种。前者兼容性更好,但会占用更多的内存,故建议短音效用Web Audio,长音乐使用DOM Audio。

{
  "ver": "2.0.0",
  "uuid": "ab548e86-4fca-4320-a8a0-0c1a714d1443",
  "downloadMode": 0,
  "subMetas": {}
}

在library目录下,Creator会为每个声音资源生成一个以uuid为命名的json文件,以及将声音文件以uuid命名。json文件的内容如下:

{
  "__type__": "cc.AudioClip",
  "_name": "music_logo",
  "_objFlags": 0,
  "_native": ".mp3",
  "loadMode": 0
}

构建之后library目录下的json和声音文件会被复制到构建目录下的import和raw-assets目录中。

  • Spine骨骼动画

每个Spine都是由json(Creator暂时不支持skel格式)、atlas、png三个文件组成,它们的meta文件非常简单,没有什么特殊的信息。

在library目录下,png会生成对应的SpriteFrame和Texture的json,以及图片自身。atlas会生成一个简单的json文件,如下所示。骨骼json会进行转换,变成Creator标准的资源格式json,以uuid命名,在当前目录下会创建一个以uuid命名的目录,放着转换前的Spine json文件,名为raw-skeleton.json。(Creator格式的json比原Spine的json要大不少)

{
  "__type__": "cc.Asset",
  "_name": "raptor",
  "_native": ".atlas"
}

构建之后,png对应的SpriteFrame、Texture的json,以及Atlas的json。Spine本身的json会转换成Creator标准的资源格式json输出到构建目录下,而且raw-skeleton.json并不在构建目录中。

  • 脚本资源的处理

在Creator中支持TS和JS脚本,这里不讨论如何编写脚本。脚本的meta文件中有几个有意思的属性,与Plugin相关,意为是否将该脚本作为插件导入。对第三方插件或者底层插件,有可能需要选中Plugin选项,这样的脚本简称插件脚本(未勾选该选项的为普通脚本)。脚本插件在打包时是不会参与构建的。

关于该选项的详细介绍可以查看 https://docs.cocos.com/creator/manual/zh/scripting/plugin-scripts.html

{
  "ver": "1.0.5",
  "uuid": "8c87839a-4fd0-4b9e-9363-23bbf1bd16ef",
  "isPlugin": false,
  "loadPluginInWeb": true,
  "loadPluginInNative": true,
  "loadPluginInEditor": false,
  "subMetas": {}
}

在library目录下,TS会被编译成JS脚本,所有的JS脚本都会以其uuid命名存储。与JS文件一起生成的还有map文件(这里放着编译前的原文件内容和路径等相关信息)。

构建之后所有的TS和JS脚本会被编译成JS,打包到一个project.dev.js文件中。构建一般会生成4个js,记录所有资源相关设置的settings.js,启动脚本main.js,开发者的代码project.dev.js以及cocos引擎cocos2d-js.js。如果开启了调试模式,构建出来的js会被精简为一行,剔除所有的注释和空行换行,并自动将一些变量名进行混淆,使用更简短的命名,而不影响代码执行的效果。如果开启了Source Maps,构建代码时会生成map文件,否则不会生成。

我们可以在Creator编辑器中的项目菜单/项目设置/模块设置下选择剔除我们不需要用到的模块,从而精简cocos2d-js.js文件的大小(新一代的js打包工具如rollup.js已经可以支持到在打包的时候自动根据引用到的代码去剔除无用代码)。

  • 字体资源的处理

CocosCreator的字体可以分为3类,系统字、BMFont以及TTF字体。系统字不需要额外的字体资源,而是使用内置的系统字体。BMFont的资源是一张图片以及一个fnt。而TTF字体的资源是一个TTF文件。

fnt资源的meta文件如下所示,指定了fontSize,以及使用的纹理。

{
  "ver": "2.1.0",
  "uuid": "e2fd9257-452a-4ae2-a932-e567c5fd6e91",
  "textureUuid": "1afd96d7-225c-484b-ab27-fe12902096d6",
  "fontSize": 32,
  "subMetas": {}
}

在library目录下,除了图片相关的Texture、SpriteFrame等json。fnt文件会被转成一个cc.BitmapFont的json文件,文件内容如下所示,_fntConfig描述了fnt字体的字号、宽高、图集以及每一个字在图集中的坐标尺寸等信息。

{
  "__type__": "cc.BitmapFont",
  "_name": "b0",
  "_objFlags": 0,
  "_native": "",
  "fntDataStr": "",
  "spriteFrame": {
    "__uuid__": "a3e89811-562f-4a58-943f-895c807f087b"
  },
  "fontSize": 32,
  "_fntConfig": {
    "commonHeight": 32,
    "fontSize": 32,
    "atlasName": "b0_0.png",
    "fontDefDictionary": {
      "36": {
        "rect": {
          "x": 81,
          "y": 0,
          "width": 79,
          "height": 111
        },
        "xOffset": 0,
        "yOffset": 0,
        "xAdvance": 79
      },
      ...

构建之后,cc.BitmapFont和SpriteFrame这2个json会被合并(我们往往需要同时使用到它们)。

TTF的meta文件只有ver、uuid和空的subMetas字段。在library目录下会生成一个以TTF资源的uuid命名的json文件,在相同目录下有一个以TTF资源的uuid目录,目录下放着ttf资源。

{
  "__type__": "cc.TTFFont",
  "_name": "BlackHanSans-Regular",
  "_objFlags": 0,
  "_native": "BlackHanSans-Regular.ttf"
}

构建后该json文件会剔除_objFlags字段后导出,而TTF文件会导出到raw-assets目录下。

  • 粒子资源的处理

粒子资源大致可以分为plist和prefab两种:

  • 对于plist粒子,存在图片使用Base64编码合并到plist文件中,和引用外部粒子图片的区别。plist的meta文件只有ver、uuid和空的subMetas字段。在library目录下会生成plist和它对应的json文件,如下所示,如果是带纹理的粒子,会生成对应的Texture和SpriteFrame的json。构建之后会导出plist的json文件,在raw-assets中导出plist文件,如果引用了外部纹理也会导出纹理对应的图片和json。
{
  "__type__": "cc.ParticleAsset",
  "_name": "p_star_fly",
  "_objFlags": 0,
  "_native": ".plist",
  "texture": {
    "__uuid__": "1544eed3-42e4-46fc-a392-0c4d8b1b9847"
  }
}
  • prefab类型的粒子和普通的prefab一样,library目录下会生成prefab的json文件(包含所有的粒子属性)以及粒子的plist文件(library目录下默认会有一些内置的粒子系统)。而构建之后,如果粒子系统的File字段指定了一个plist文件,构建出来的raw-assets目录中会导出plist,而导出的粒子json是一个比较简短的json(因为大部分的属性都定义在plist文件中了),除非我们在编辑器中编辑了自定义的属性。

资源打包规则

在了解了Creator对单个资源的处理之后,我们要对Creator资源打包规则做更深入的分析。对于资源打包,我们主要关注的2点是IO和包体,json的合并可以减少IO操作,在某些情况下也可能增大包体。

关于图片的合并

在Creator构建后每一个图片都会生成一个描述cc.Texture2D的json以及一个cc.SpriteFrame的json,而其中所有的cc.Texture2D.json都会被合并成一个,应该说一个项目在构建之后,正常来说最多只会有一个cc.Texture2D的json,只是它的data字段会很长。不论图片是来自不同目录的图片、图集、自动图集、Spine、粒子系统或者BMFont等等,都不影响它们的cc.Texture2D.json被合并。

{
  "type": "cc.Texture2D",
  "data": "0|0|0|0|0|0|0|0|0|0|0|0"
}

图片对应的SpriteFrame又会被怎样合并呢?默认的情况下(即不考虑依赖和构建选项的情况)只有plist图集和BMFont字体这两种资源的SpriteFrame会有合并的操作。plist的json会与图集中所有的SpriteFrame的json合并为一个json。BMFont字体的fnt对应的json会与SpriteFrame合并为一个json。

接下来我们来看一下资源依赖的情况,使用prefab去引用各种类型的资源,json又会如何合并呢?prefab引用的所有资源中,只有单个图片和自动图集中的SpriteFrame会被合并到prefab的json中。

如果我们在构建时勾选了“内联所有SpriteFrame”,json又会如何合并呢?除了单个图片和自动图集,prefab中用到的图集的SpriteFrame也会被合并进来,但图集的合并是拷贝,也就是说原来的图集和图集中所有SpriteFrame合并的那个json仍然存在。

如果我们的资源同时被多个prefab引用,在这种情况下,是否勾选“内联所有SpriteFrame”又会有怎样的区别呢?

  • 不勾选的情况下,图集多个prefab共同引用的部分SpriteFrame会被提取出来进行合并(单张图片和AutoAtlas)。共同部分至少需要2个SpriteFrame,比如说A和B,每一个引用到公共SpriteFrame的prefab必定同时引用到A和B,如果有一个prefab只引用了A,那么A和B就不会被合并。

Fa6qC6.png

  • 勾选的情况下,不存在共用资源的说法,每个prefab都会合并它用到的SpriteFrame(单张图片、AutoAtlas、图集),如果这些资源被多个prefab引用,那么会被复制到每一个prefab的json中。

Fa6H4x.png

前面介绍了prefab的依赖对构建打包的影响,在Creator中,除了prefab可以去引用资源外,场景也可以引用外部资源,但正常情况下场景不会去将其引用的SpriteFrame打包进来。在勾选了“内联所有SpriteFrame”的情况下,场景的json才会去合并引用到的SpriteFrame。

在勾选了“合并初始场景依赖的所有JSON”后,初始场景引用到的所有json都会被合并到初始场景的json文件中,这种合并不是拷贝,而是将场景引用到的所有资源的json文件合并到一起(除了SpriteFrame外,还有粒子json、plist图集完整json、Spine骨骼json、BMFont字体json、动画json等等)。如果没有勾选“内联所有SpriteFrame”,这些json只会放在启动场景的json中,不会影响包体。值得一提的是图片的cc.Texture2D这个json,所有被初始场景引用到的纹理会从这个json中剥离,并合并到初始场景。

posted @ 2019-05-09 10:37  深圳-宝爷  阅读(7591)  评论(4编辑  收藏  举报