HarmonicMotion (Cocos Creator)
最終更新: 2023年3月14日
概要
HarmonicMotionは、指定したパラメータの値を周期的に反復させる機能です。
主に呼吸のように常に動作し続けるものに対して使用します。
HarmonicMotionの設定方法については こちら をご覧ください。
Cubism SDK for Cocos CreatorにおけるHarmonicMotionは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
正弦波の周期を設定します。
周期は複数設定できます。