HarmonicMotion (Cocos Creator)

最終更新: 2023年3月14日

概要

HarmonicMotionは、指定したパラメータの値を周期的に反復させる機能です。
主に呼吸のように常に動作し続けるものに対して使用します。
HarmonicMotionの設定方法については こちら をご覧ください。

Cubism SDK for Cocos CreatorにおけるHarmonicMotionは2つの要素によって構成されています。

  1. 動作させるパラメータ指定用のコンポーネント
  2. 各パラメータの値を操作するコンポーネント

1. 動作させるパラメータ指定用のコンポーネント

HarmonicMotionに使用するパラメータを指定するには、 CubismHarmonicMotionParameter を使用します。

CubismHarmonicMotionParameterはComponentを継承したコンポーネントで、
[Prefabのルート]/Parameters/ 以下に配置されたNodeにアタッチして使用します。
これがアタッチされたNodeと同じIDのパラメータの値を周期的に動作させます。

CubismHarmonicMotionParameterには、5つの設定項目があります。

  /** Timescale channel. */
  @property({ type: CCInteger, serializable: true, visible: true })
  public channel: number = 0;

  /** Motion direction. */
  @property({ type: Enum(CubismHarmonicMotionDirection), serializable: true, visible: true })
  public direction: CubismHarmonicMotionDirection = CubismHarmonicMotionDirection.Left;

  /**
   * Normalized origin of motion.
   * The actual origin used for evaluating the motion depends limits of the {@link CubismParameter}.
   */
  @property({ type: CCFloat, slide: true, range: [0.0, 1.0, 0.01], serializable: true, visible: true, })
  public normalizedOrigin: number = 0.5;

  /**
   * Normalized range of motion.
   * The actual origin used for evaluating the motion depends limits of the {@link CubismParameter}.
   */
  @property({ type: CCFloat, slide: true, range: [0.0, 1.0, 0.01], serializable: true, visible: true, })
  public normalizedRange: number = 0.5;

  /** Duration of one motion cycle in seconds. */
  @property({ type: CCFloat, slide: true, range: [0.01, 10.0, 0.01], serializable: true, visible: true, })
  public duration: number = 3.0;
  • channel

    CubismHarmonicMotionControllerで設定された、正弦波の周期の倍率を指定します。

    HarmonicMotionでは、一つのモデルに対して複数の周期を設定することができ、CubismHarmonicMotionControllerで設定することができます。

    ここには、CubismHarmonicMotionController.channelTimescalesのインデックスを設定します。
  • direction

    パラメータの中心を基準に、どの範囲で周期的に動作させるかを設定します。

    設定項目は以下の3つです。
  • Left : パラメータの中心から左半分の範囲だけで動作します。
  • Right : パラメータの中心から右半分の範囲だけで動作します。
  • Centric : パラメータの全体で動作します。
  • normalizedOrigin

    directionで基準にするパラメータの中心を設定します。

    そのパラメータの最小値を0、最大値を1としたときの値を中心に設定します。
  • normalizedRange

    normalizedOriginで設定された値を中心から値を動作させる振幅を設定します。

    そのパラメータの最小値を0、最大値を1としたときの、中心からの移動距離を設定します。

    この値は、normalizedOriginで設定された中心の位置からパラメータの最小値または最大値までの範囲だけ設定できます。
  • duration

    パラメータの周期を調整します。
  /** Evaluates the parameter. */
  public evaluate(): number {
    // Lazily initialize.
    if (!this.isInitialized) {
      this.initialize();
    }

    // Restore origin and range.
    let origin = this.minimumValue + this.normalizedOrigin * this.valueRange;
    let range = this.normalizedRange * this.valueRange;

    // Clamp the range so that it stays within the limits.
    const outputArray = this.clamp(origin, range);

    const originIndex = 0;
    const rangeIndex = 1;
    origin = outputArray[originIndex];
    range = outputArray[rangeIndex];

    // Return result.
    return origin + range * Math.sin((this.t * (2 * Math.PI)) / this.duration);
  }

  /**
   * Clamp origin and range based on {@link direction}.
   * @param origin Origin to clamp.
   * @param range Range to clamp.
   * @returns
   */
  private clamp(origin: number, range: number): [number, number] {
    switch (this.direction) {
      case CubismHarmonicMotionDirection.Left: {
        if (origin - range >= this.minimumValue) {
          range /= 2;
          origin -= range;
        } else {
          range = (origin - this.minimumValue) / 2.0;
          origin = this.minimumValue + range;
          this.normalizedRange = (range * 2.0) / this.valueRange;
        }
        break;
      }
      case CubismHarmonicMotionDirection.Right: {
        if (origin + range <= this.maximumValue) {
          range /= 2.0;
          origin += range;
        } else {
          range = (this.maximumValue - origin) / 2.0;
          origin = this.maximumValue - range;
          this.normalizedRange = (range * 2.0) / this.valueRange;
        }
        break;
      }
      case CubismHarmonicMotionDirection.Centric:
        break;
      default: {
        const neverCheck: never = this.direction;
        break;
      }
    }

    // Clamp both range and NormalizedRange.
    if (origin - range < this.minimumValue) {
      range = origin - this.minimumValue;
      this.normalizedRange = range / this.valueRange;
    } else if (origin + range > this.maximumValue) {
      range = this.maximumValue - origin;
      this.normalizedRange = range / this.valueRange;
    }

    return [origin, range];
  }

また、CubismHarmonicMotionParameterは、CubismHarmonicMotionControllerが参照先を取得するためのマーカーとしても使用しています。

2. 各パラメータの値を操作するコンポーネント

各パラメータに開閉の値を適用するには、 CubismHarmonicMotionController を使用します。
これはComponentを継承したコンポーネントで、使用する際はCubismのPrefabのルートにアタッチします。

初期化時に、PrefabにアタッチされたすべてのCubismHarmonicMotionParameterの参照を取得します。
実行中に周期的に値を動作させるパラメータを追加/削除した場合、CubismHarmonicMotionController.refresh()を呼んで参照を取得し直します。

  /** Refreshes the controller. Call this method after adding and/or removing {@link CubismHarmonicMotionParameter}. */
  public refresh() {
    const model = CoreComponentExtensionMethods.findCubismModel(this);

    if (model == null || model.parameters == null) {
      return;
    }

    // Catch sources and destinations.
    this.sources = FrameworkComponentExtensionMethods.getComponentsMany(
      model.parameters,
      CubismHarmonicMotionParameter
    );
    this.destinations = new Array<CubismParameter>(this.sources.length);

    for (let i = 0; i < this.sources.length; ++i) {
      this.destinations[i] = this.sources[i].getComponent(CubismParameter);
    }

    // Get cubism update controller.
    this.hasUpdateController = this.getComponent(CubismUpdateController) != null;
  }

  ...

  /** Called by Cocos Creator. Makes sure cache is initialized. */
  protected start() {
    // Initialize cache.
    this.refresh();
  }

CubismHarmonicMotionControllerは、毎フレームのlateUpdate()のタイミングで、CubismHarmonicMotionParameterでマーキングされたパラメータに対して算出された値を適用します。

  /** Called by cubism update controller. Updates controller. */
  protected onLateUpdate(deltaTime: number) {
    // Return if it is not valid or there's nothing to update.
    if (!this.enabled || this.sources == null) {
      return;
    }

    // Update sources and destinations.
    for (let i = 0; i < this.sources.length; ++i) {
      this.sources[i].play(this.channelTimescales);

      CubismParameterExtensionMethods.blendToValue(
        this.destinations[i],
        this.blendMode,
        this.sources[i].evaluate()
      );
    }
  }

  ...

  /** Called by Cocos Creator. Updates controller. */
  protected lateUpdate(deltaTime: number) {
    if (!this.hasUpdateController) {
      this.onLateUpdate(deltaTime);
    }
  }

CubismHarmonicMotionControllerには、2つの設定項目があります。

  /** Blend mode. */
  @property({ type: Enum(CubismParameterBlendMode), serializable: true, visible: true })
  public blendMode: CubismParameterBlendMode = CubismParameterBlendMode.Additive;

  /** The timescales for each channel. */
  @property({ type: [CCFloat], serializable: true, visible: true })
  public channelTimescales: number[] = [];
  • blendMode

    パラメータに値を適用する際のブレンドモードです。

    設定できる値は以下の3つです。
    • Override : 現在の値を上書きします。
    • Additive : 現在の値に加算します。
    • Multiply : 現在の値に乗算します。
  • channelTimescales

    正弦波の周期を設定します。
    周期は複数設定できます。
この記事はお役に立ちましたか?
はいいいえ
この記事に関するご意見・
ご要望をお聞かせください。