HarmonicMotion (Cocos Creator)
업데이트: 2023/03/14
개요
HarmonicMotion은 지정된 파라미터의 값을 주기적으로 반복하는 기능입니다.
주로 호흡처럼 항상 계속 동작하는 것에 사용합니다.
HarmonicMotion을 설정하는 방법은 여기를 참조하십시오.
Cubism SDK for Cocos Creator의 HarmonicMotion은 두 가지 요소로 구성됩니다.
- 동작시키는 파라미터 지정용 컴포넌트
- 각 파라미터의 값을 조작하는 컴포넌트
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
사인파의 주기를 설정합니다.
주기는 복수 설정할 수 있습니다.