HarmonicMotion (Cocos Creator)

업데이트: 2023/03/14

개요

HarmonicMotion은 지정된 파라미터의 값을 주기적으로 반복하는 기능입니다.
주로 호흡처럼 항상 계속 동작하는 것에 사용합니다.
HarmonicMotion을 설정하는 방법은 여기를 참조하십시오.

Cubism SDK for Cocos Creator의 HarmonicMotion은 두 가지 요소로 구성됩니다.

  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에는 두 가지 설정 항목이 있습니다.

  /** 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

    파라미터에 값을 적용할 때의 블렌드 모드입니다.

    설정할 수 있는 값은 다음 세 가지입니다.
    • Override: 현재 값을 덮어씁니다.
    • Additive: 현재 값에 가산합니다.
    • Multiply : 현재 값에 곱합니다.
  • channelTimescales

    사인파의 주기를 설정합니다.
    주기는 복수 설정할 수 있습니다.
이 기사가 도움이 되었나요?
아니요
이 기사에 관한 의견 및 요청사항을 보내 주시기 바랍니다.