Expression (Cocos Creator)

最終更新: 2023年3月14日

概述

Expression是处理Cubism表情动态的功能,可以通过将表情参数的值与当前参数的值进行加算或正片叠底来设置。
在Cocos Creator标准动态播放功能Animator中,由于可设置为层的混合模式中没有正片叠底(Multiply),所以无法表达。

表情功能设置文件以.exp3.json格式输出。
请参考此处了解表情的机制。

为了使用Expression,需要提前在Prefab中进行“如何设置UpdateController”和“保存/恢复要操作的值”。

请参考此处查看相关教程文章。

按照以下步骤播放表情动态。

  1. 创建[.exp3.asset]
  2. 创建[.expressionList.asset]并追加[.exp3.asset]
  3. 播放表情动态
  4. 表情动态的计算及应用

创建[.exp3.asset]

[.exp3.asset]是从[exp3.json]转换而来的ScriptableObject资产。
如果变更[.exp3.asset],则无法保证正常运行。

要将[exp.json]转换为[.exp3.asset],请执行以下处理:

  1. 解析[exp.json]
  2. 创建CubismExpressionData
  3. 创建[.exp3.asset]

解析[exp.json]

使用CubismExp3Json.loadFrom(string exp3Json)或CubismExp3Json.loadFrom(TextAsset exp3JsonAsset)解析[exp3.json]。

创建CubismExpressionData

CubismExpressionData是一个记录解析后的.exp3.json信息的类,保存以下数据。

场地说明
Typestringjson文件类型。.exp3.json时,设置“Live2D Expression”。
FadeInTimenumber直到表情淡入所需的时间。值的单位是秒。
FadeOutTimenumber直到表情淡出所需的时间。值的单位是秒。
ParametersSerializableExpressionParameter[]应用表情的参数的ID、要应用的值、计算方法。

使用CubismExpressionData.CreateInstance(CubismExp3Json json)创建一个新的[.exp3.asset]。

使用CubismExpressionData.CreateInstance(CubismExpressionData expressionData, CubismExp3Json json)覆盖[.exp3.asset]。

  • CubismExp3Json json:CubismExp3Json是解析[exp3.json]后的数据。
  • CubismExpressionData expressionData:覆盖对象CubismExpressionData。

创建[.exp3.asset]

如下所示,创建[.exp3.asset]。

    const jsonSrc = readFileSync(asset.source, UTF8);
    const json = CubismExp3Json.loadFrom(jsonSrc);
    if (json == null) {
      console.error('CubismExp3Json.loadFrom() is failed.');
      return false;
    }
    const data = CubismExpressionData.createInstance(json);
    const serialized = EditorExtends.serialize(data);
    writeFileSync(outputFilePath, jsonSrc);
    asset.saveToLibrary('.json', serialized);
    refresh(outputFilePath);

这个处理由CubismExpression3JsonImporter.import()执行。

* 运行时,无需将CubismExpressionData转换为.asset。

创建[.expressionList.asset]并追加[.exp3.asset]

[.expressionList.asset]是列出各模型的[.exp3.asset]参考的资产。
使用CubismExpressionController来获取从CurrentExpressionIndex播放的表情动态。
[.exp3.asset]列表的顺序是按照[exp3.json]的载入顺序追加的。

创建[.expressionList.asset]

[.expressionList.asset]在与模型预制件相同的层次结构中创建。

    const source = JSON.parse(readFileSync(asset.source, UTF8));
    const expDataUuidsSource = Array.isArray(source.cubismExpressionObjects)
      ? (source.cubismExpressionObjects as any[])
      : undefined;
    if (expDataUuidsSource == null) {
      console.error('CubismExpressionListImporter.import(): parse error.');
      return false;
    }
    const expDataUuids = purseCubismExpressionObjects(expDataUuidsSource);
    if (expDataUuids == null) {
      console.error('CubismExpressionListImporter.import(): CubismExpressionObjects parse error.');
      return false;
    }
    const cubismExpressionObjects = new Array<CubismExpressionData>(expDataUuids.length);
    for (let i = 0; i < cubismExpressionObjects.length; i++) {
      const uuid = expDataUuids[i];
      // @ts-ignore
      cubismExpressionObjects[i] = EditorExtends.serialize.asAsset(
        uuid,
        CubismExpressionData
      ) as CubismExpressionData;
    }
    const list = new CubismExpressionList();
    list.cubismExpressionObjects = cubismExpressionObjects;
    await asset.saveToLibrary('.json', EditorExtends.serialize(list));

* 此项目由CubismExpressionListImporter.import()处理。

追加[.exp3.asset]

要将[.exp3.asset]追加到[.expressionList.asset],请执行以下操作:

    const jsonSrc = readFileSync(asset.source, 'utf8');
    const json = CubismExp3Json.loadFrom(jsonSrc);
    if (json == null) {
      console.error('CubismExp3Json.loadFrom() is failed.');
      return false;
    }
    const data = CubismExpressionData.createInstance(json);
    const serialized = EditorExtends.serialize(data);
    asset.saveToLibrary('.json', serialized);
    refresh(outputFilePath);

    const dirPath = Path.join(Path.dirname(asset.source), '../');
    const dirName = Path.basename(dirPath);
    if (dirPath.length == 0) {
      console.warn('CubismExpressionDataImporter.import(): Not subdirectory.');
      return true;
    }
    const expressionListFilePath = Path.join(
      dirPath,
      dirName + `.${CubismExpressionListImporter.extension}`
    );
    updateExpressionListFile(expressionListFilePath, asset.uuid);
    refresh(expressionListFilePath);

* 此项目由CubismExpressionDataImporter.import()处理。

播放表情动态

您可以通过在CubismExpressionController.CurrentExpressionIndex中设置要播放的表情动态的索引,以播放/变更表情动态。

执行以下处理以播放表情动态。

  1. 设置播放过程中表情动态的退出时间
  2. 原始化一个新的表情动态,并将其追加到表情动态播放列表中

设置播放过程中表情动态的退出时间

播放期间的表情动态存在时,请设置退出时间,以便退出正在播放的表情动态。

    const playingExpressions = this._playingExpressions;
    if (playingExpressions.length > 0) {
      const playingExpression = playingExpressions[playingExpressions.length - 1];
      playingExpression.expressionEndTime =
        playingExpression.expressionUserTime + playingExpression.fadeOutTime;
      playingExpressions[playingExpressions.length - 1] = playingExpression;
    }

这个处理由CubismExpressionController.startExpression()执行。

原始化一个新的表情动态,并将其追加到表情动态播放列表中

创建拥有表情动态播放信息的CubismPlayingExpression。

CubismPlayingExpression保留以下信息:

场地说明
Typestringjson文件类型。.exp3.json时,设置“Live2D Expression”。
FadeInTimenumber直到表情淡入所需的时间。值的单位是秒。
FadeOutTimenumber直到表情淡出所需的时间。值的单位是秒。
Weightnumber表情权重。值的范围为0到1。
ExpressionUserTimenumber自表情播放开始以来经过的时间。值的单位是秒。
ExpressionEndTimenumber退出表情播放的时间。值的单位是秒。
DestinationsCubismParameter[]表情适用的参数数组。
Valuenumber[]表情应用于参数的值。元素的数量和顺序与Destinations相同。
BlendCubismParameterBlendMode[]表情应用于参数的计算方法。元素的数量和顺序与Destinations相同。要设置的计算方法是Override、Additive、Multiply。

CubismPlayingExpression可以使用CubismPlayingExpression.create(CubismModel model, CubismExpressionData expressionData)创建。

  • CubismModel model:播放表情动态的模型。
  • CubismExpressionData expressionData:要播放的表情动态的[exp3.asset]数据。

将创建的表情动态追加到播放列表中,如下所示。

    const playingExpression = CubismPlayingExpression.create(
      this._model,
      expressionsList.cubismExpressionObjects[this.currentExpressionIndex]
    );

    if (playingExpression == null) {
      return;
    }

    // Add to PlayingExList.
    playingExpressions.push(palyingExpression);

这个处理由CubismExpressionController.startExpression()执行。

表情动态的计算及应用

表情计算和应用是从CubismExpressionController.onLateUpdate()调用的。

* 必须在ParameterStore.saveParameters()之后应用表情。
Expression是针对当前值,于每帧新应用表情值的功能。
如果在ParameterStore.saveParameters()之前应用,将会保存表情应用的结果,所以表情的参数值会无限加算或正片叠底。

请问这篇文章对您有帮助吗?
关于本报道,敬请提出您的意见及要求。