ํ์๋ผ์ธ๐ฌ 05 - Custom Playables ํธ๋ ๋ง๋ค๊ธฐ
์ ๋๋ฉ์ด์ ๋ฐ ํํ ๋ฆฌ์ผ ์ ์์ ์ ์ฉํ ์ ๋ํฐ ํ์๋ผ์ธ์ ๋ํด ์์๋ณธ๋ค. ์ด๋ฒ ํฌ์คํ ์์๋ ํ์๋ผ์ธ์ ๊ฝ์ด๋ผ๊ณ ํ ์ ์๋ Custom Playables์ ๋ํด ๋ค๋ฃฌ๋ค.
- Playables?
- ์ ๋ํฐ ๊ณต์์ง์ ์์ - Default Playablesโจ
- ์คํฌ๋ฆฝํธ ๊ฐ๋จ์ค๋ช ๐
- ๋ง๋ฌด๋ฆฌ
ํ์๋ผ์ธ์์๋ ๊ธฐ๋ณธ์ผ๋ก ์กด์ฌํ๋ ํธ๋ ์ธ์ ์ฌ์ฉ์๊ฐ ๋ง๋ ํธ๋๊ณผ ํด๋ฆฝ์ ์ด์ฉํ ์ ์๋ค. ์ด๋ฌํ ์์ ์ ๋ถ๋ฅด๋ ๋ช ์นญ์ ํ์ฌ ํ๋๋ก ํต์ผ๋์ง ์๊ณ ์ฌ๋ฌ ๋จ์ด๋ก ์ฐ์ด๊ณ ์๋ค. ๊ทธ ์ค ๋ง์ด ์ฐ์ด๋ ๋จ์ด๋ ์๋์ ๊ฐ๋ค. ์๋์ ๋จ์ด๋ก ์ข ๋ ์์นญํด๋ณด๋ฉด ์ข์ ๊ฒ์ด๋ค.
- extending timeline
- custom playables
- timeline scripting
- custom track
Playables?
์ด ํฌ์คํ
์์๋ custom playables๋ผ๋ ๋จ์ด๋ก ์์ ํ๋ค.
Timeline์ ๋ด๋ถ์ ์ผ๋ก Playables API๋ฅผ ์์๋ฐ๊ณ ์๋ค. ํ์๋ผ์ธ ๊ด๋ฆฌ ์ปดํฌ๋ํธ ์ด๋ฆ๋ Playable Director์ด๊ณ , ํด๋์ค๋ค๋ Playables๋ฅผ ์์๋ฐ๊ณ ์๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
์์-์ ๋ํฐ์์ ์ง์ํ๋ TimeDilation Custom Playables Track
๊ทธ๋ ๋ค๋ฉด Playables๋ ๋ฌด์์ผ๊น ๊ถ๊ธํด์ง๋ค. ์ฐพ์๋ณด๋ ์ ๋๋ฉ์ด์ ์ด๋ ์ค๋์ค, ๊ทธ๋ฆฌ๊ณ ์คํฌ๋ฆฝํธ๊น์ง ๋ฏน์ค์ ๋ธ๋ ๋๋ฅผ ์ง์ํด์ค๋ค๊ณ ํ๋ค.
๐์ฐธ๊ณ : Unity Playable API Documentation
์ ๋ํฐ ๊ณต์์ง์ ์์ - Default Playablesโจ
๐์์ ์คํ ์ด ๋งํฌ: Default Playables
๋จผ์ ๊ณต์์์ ์ ๋ค์ด๋ฐ๋ ๊ฒ์ ์ถ์ฒํ๋ค. [Default Playables]์๋ ์์ ์ ํจ๊ป ์ปค์คํ ํ๋ ์ด์ด๋ธ์ ์ฝ๊ฒ ๋ง๋ค ์ ์๋ ์๋ํฐ์ธ [Playables Wizard]๋ฅผ ํจ๊ป ์ง์ํด์ฃผ๊ธฐ ๋๋ฌธ์ด๋ค.
์ํฌํธ๋ฅผ ์๋ฃํ๋ค๋ฉด ํ์๋ผ์ธ์์ ์์ ํธ๋์ ์์ฑํ ์ ์๋ค. ์์ ๋ ์ด 7๊ฐ์ง์ด๋ฉฐ ํ์ฉ์ฑ์ด ๋์ ๊ฒ๋ค๋ก ์ด๋ฃจ์ด์ ธ ์๋ค. ์์ค์ฝ๋๋ ๋ชจ๋ ๋ค์ด์๊ณ ๋์ค์ ์ด ์์ ๋ค์ ์ฐธ๊ณ ํ์ฌ ์ฝ๋๋ฅผ ์์ ํ๊ธฐ๋ ํ๊ธฐ ๋๋ฌธ์ ์๊ฐ์ด ๋ง๋ค๋ฉด ์ฒ์ฒํ ์์ ๋ฅผ ๋ค๋ค๋ณด๋ฉฐ ์ดํดํ๋ ๊ฒ์ ์ถ์ฒํ๋ค.
Playables Wizard ๐งโโ๏ธ
ํ๋ ์ด์ด๋ธ ์์๋๋ ์ปค์คํ ํ๋ ์ด์ด๋ธ ์คํฌ๋ฆฝํธ์ ํ์ ๋ง๋ค์ด์ฃผ๋ ์ญํ ์ ํ๋ค. ์ธ๋ถ์ ์ธ ์ฝ๋๋ฅผ ์์ฑํ ์๋ ์์ง๋ง ์ ์ด๋ ์ด๋ฆ, ํธ๋ ์์, ๋ธ๋ ๋ ํ์ , ๋ฐ์ธ๋ฉ ์ปดํฌ๋ํธ ์ ํ, ๋ณ์ ์ ํ ๋ฑ ํ์์ ์ธ ์์๋ค์ ๊ธฐ๋ฐ์ผ๋ก ๋น ๋ฅด๊ฒ ์คํฌ๋ฆฝํธ๋ฅผ ๋ง๋ค์ด์ค๋ค.
์ ๋ํฐ ์๋ํฐ์์ [Window โ Timeline Playable Wizardโฆ]๋ฅผ ์ ํํ์ฌ ์ฐฝ์ ์ฐ๋ค.
์ฐฝ์ ์ด๋ฉด ์ด๋ฌํ ์๋ํฐ์ฐฝ์ด ๋จ๊ฒ ๋๋ค. [Show Help]์ ์ฒดํฌ๋ฅผ ํ๊ฒ ๋๋ฉด ๊ฐ๊ฐ ์ด๋ค ์ญํ ์ ํ๋์ง ์ค๋ช ํด์ฃผ๋ ๋ฉ์ธ์ง๋ฐ์ค๊ฐ ๋ฌ๋ค. ์ฒ์ฒํ ์ฝ์ด๋ณด๋ฉด ์ดํด๊ฐ ๊ฐ๋ฅํ๋ค.
๊ทธ ์ค ์กฐ๊ธ ํท๊น๋ฆฌ๋ ๊ฒ์ [Exposed References]์ [Behaviour Variables]์ผํ ๋ฐ, ์ด ๋์ ํด๋ฆฝ์ ๋ฐ์ธ๋ฉ๋๋ ๋ณ์๋ค์ด๋ค. ์ด๋ฆ๋ง ๋ด๋ ์๊ฒ ์ง๋ง ๊ฐ๊ฐ ์ฐธ์กฐ์ ๊ฐ์ ๋ฐ๋๋ค. ์ฌ์ ์์ด์ ์ฐธ์กฐํด์ผํ ๋ณ์๋ Exposed References๋ก ์ง์ ํ๊ณ , ์ฌ์ ์๊ณ ๊ฐ๋ง ์กด์ฌํ๋ ๋ณ์๋ Behaviour Variables๋ก ์ง์ ํ๋ฉด ๋๋ค.
์คํฌ๋ฆฝํธ ๊ฐ๋จ์ค๋ช ๐
ํ์๋ผ์ธ ์ปค์คํ ํ๋ ์ด์ด๋ธ ์คํฌ๋ฆฝํธ ๋ณดํต 5๊ฐ์ง ์ข ๋ฅ๋ก ๋ถ๋ฅํ๋ค.
- ~Track.cs
- ํธ๋์ ์์, ๋ฐ์ธ๋ฉํ์ ์ ์ ํ๋ ๋ฑ ํธ๋ ์์ฒด์ ๊ด์ฌํ๋ ์คํฌ๋ฆฝํธ
- ~Clip.cs
- ๋ธ๋ ๋ฉ ํ์
๋ฑ ํด๋ฆฝ ์์ฑ์ ๊ด์ฌํ๋ ์คํฌ๋ฆฝํธ.
์ฐธ์กฐ๋ณ์(Exposed References)๋Resolve()
๋ผ๋ ํจ์๋ฅผ ํธ์ถํด์ผ๋ง ์ฌ์ฉํ ์ ์๊ธฐ ๋๋ฌธ์ Clip ์คํฌ๋ฆฝํธ์์CreatePlayable()
ํจ์๋ฅผ ํตํด Behaviour ์คํฌ๋ฆฝํธ์๊ฒ ๋๊ฒจ์ค๋ค.
- ~Behaviour.cs
- ํด๋ฆฝ์ ํด๋ฆญํ๋ฉด ์ธ์คํํฐ์ฐฝ์ ๋์ค๋ ๋ณ์๋ค(Behaviour Variables)์ด ์ฌ๊ธฐ์ ์กด์ฌํ๋ค.
- ~MixerBehaviour.cs
- ๊ฐ์ฅ ์ค์ํ ์คํฌ๋ฆฝํธ. ์ฌ์ ์์ ์ด๋ฃจ์ด์ง๋ ๊ฑฐ์ ๋ชจ๋ ์ฒ๋ฆฌ๋ ์ด ์คํฌ๋ฆฝํธ์์ ๋ด๋นํ๋ค.
ํด๋ฆฝ์ ๋ค์ด์ค ๋, ํด๋ฆฝ์ ํต๊ณผ ์ค์ผ ๋, ํด๋ฆฝ์ ๋๊ฐ ๋, ๋ธ๋ ๋ ๋๊ณ ์์ ๋ ๋ฑ๋ฑ์ ์ฒ๋ฆฌ๋ฅผ ๋ชจ๋ProcessFrame()
์ด๋ผ๋ ํจ์๋ฅผ overrideํจ์ผ๋ก์จ ์ฒ๋ฆฌ ๊ฐ๋ฅํ๋ค.
- ~Drawer.cs (Editor)
- ํด๋ฆฝ์ ์๋ํฐ. ํด๋ฆฝ์ ํด๋ฆญํ๋ฉด ์ธ์คํํฐ์ฐฝ์ ์ด ์๋ํฐ ์คํฌ๋ฆฝํธ์์ ์ค์ ํ ๋ ์ด์์์ผ๋ก ํ์๋๋ค.
~MixerBehaviour.cs ๋ถ์ฐ์ค๋ช
์ฃผ์ด์ง ์์ ๋ฅผ ๋ถ์ํ๋ ๊ฒ์ด ์คํฌ๋ฆฝํธ์ ๋ํ ์ดํด๊ฐ ๊ฐ์ฅ ๋น ๋ฅด๊ฒ ์ง๋ง, ๊ฐ์ฅ ์ค์ํ MixerBehaviour ์คํฌ๋ฆฝํธ๋ ์ข ๋ ์ค๋ช ์ ์จ๋๊ฒ ๋ค. ์๋๋ถํฐ ์ด์ด์ง๋ ๋ถ์ฐ์ค๋ช ๋ค์ ์คํฌ๋ฆฝํธ๋ฅผ ๋์ถฉ์ด๋ผ๋ ๋ถ์ํด๋ณธ ์ฌ๋์ ์ํด ์ ๋ ๊ฒ์ด๋ฏ๋ก ๋ฐ๋ก ์ดํด๊ฐ ํ๋ค ์๋ ์๋ค.
๋ง์ฝ ์์ ๋ฅผ ๋ถ์ํ๊ธฐ ์ด๋ ต๋ค๋ฉด ๋ค์ ํฌ์คํ ์์ ํ์๊ฐ ์์ฑํ ์ปค์คํ ํ๋ ์ด์ด๋ธ ํธ๋์ ๋ถ์ํ๋ ๋ด์ฉ์ ๋ค๋ฃฐํ ๋ ๊ทธ๊ฒ์ ๋ณด์๋ ์ข๋ค.
ProcessFrame() ์ฝ๋ ์ค๋ช
[Timeline Playable Wizardโฆ]๋ฅผ ํตํด ํ์๋ผ์ธ์ ๋ง๋ค์๋ค๋ฉด MixerBehaviour์ ์๋์ผ๋ก ProcessFrame()
์ overrideํ๋ ํจ์๊ฐ ์์ฑ๋์ด ์์ ๊ฒ์ด๋ค. ์ฃผ์ํด์ผํ ๊ฒ์ ์ ๋ํฐ ์๋ํฐ์ ํ๋ ์ด ๋ฒํผ์ ๋๋ฅด์ง ์์๋ ํ์๋ผ์ธ์ ์คํํ๊ฑฐ๋ ์ธ๋์ผ์ดํฐ๋ฅผ ์ฎ๊ธฐ๋ฉด ํจ์๊ฐ ํธ์ถ๋๋ค๋ ์ ์ด๋ค. ์ด๋ฅผ ์ผ๋์ ๋๊ณ ์คํฌ๋ฆฝํธ๋ฅผ ์ง์ผํ๋ค.
์๋์ ์ฝ๋๋ ProcessFrame()
ํจ์์์ ์์ผ๋ฉด ํธํ ๊ฒ๋ค์ ๋ํด ์ถ๋ ค๋์ ์ฝ๋์ด๋ค.
// ์ฃผ์: ์ด ํจ์๋ Play๋ชจ๋๊ฐ ์๋ Edit๋ชจ๋์์๋(ํ๋ ์ด ๋ฒํผ์ ๋๋ฅด์ง ์์์ ๋๋) ํธ์ถ๋จ.
public override void ProcessFrame(Playable playable, FrameData info, object playerData)
{
// ํธ๋์ ์กด์ฌํ๋ ํด๋ฆฝ์ ๊ฐฏ์
int inputCount = playable.GetInputCount();
int currentInputCount = 0;
for (int i = 0; i < inputCount; i++)
{
// ํด๋ฆฝ์ blending์ ๋น๋กํ์ฌ ๊ณ์ฐํ๋ ํธ๋ ์ ์ ์จ(0~1)
float inputWeight = playable.GetInputWeight(i);
if (inputWeight > 0f)
currentInputCount++;
}
// ํด๋ฆฝ์ด ์๋ ๊ณณ์ ์ง๋๋ ์ค
if (currentInputCount == 0)
{
Debug.Log("์์");
}
// ํด๋ฆฝ์ด 1๊ฐ์ธ ๊ณณ์ ์ง๋๋ ์ค
else if(currentInputCount == 1)
{
Debug.Log("1๊ฐ");
}
// ํด๋ฆฝ์ด 2๊ฐ ์ด์์ธ ๋ธ๋ ๋ฉ๋๊ณ ์๋ ๊ณณ์ ์ง๋๋ ์ค
else
{
Debug.Log("๋ธ๋ ๋ฉ");
}
}
Input Count
InputCount๋ ํด๋น ํธ๋์ ์กด์ฌํ๋ ํด๋ฆฝ์ ๊ฐฏ์๋ฅผ ๋ปํ๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก Playable.GetInputCount()
๋ฅผ ํตํด ํด๋ฆฝ์ ๊ฐฏ์๋ฅผ int
๋ก ๋ฐํ๋ฐ๋๋ค.
Input Weight
InputWeight๋ ํ์ฌ ํด๋ฆฝ์ด ํธ๋์์ blending์ ๋น๋กํ์ฌ ์ผ๋ง๋ ํธ๋์ ์ ์ ํ๊ณ ์๋์ง์ ๋ํ ๊ฐ์ด๋ค. 0์์ 1๊น์ง์ float
๊ฐ์ผ๋ก ๋ฐํ๋ฐ๋๋ค. ๋ง์ฝ ๋ธ๋ ๋ฉ๋๊ณ ์์ง ์๋ค๋ฉด 1์ ๋ฐํํ๊ณ , ํด๋น ํด๋ฆฝ์ด ์ฌ์๋๊ณ ์์ง ์๋ค๋ฉด 0์ ๋ฐํํ๋ค. ๋ธ๋ ๋ฉ๋๊ณ ์๋ค๋ฉด 0๊ณผ 1์ ์ฌ์ด๊ฐ์ ๋ฐํํ๋ค.
ํ๋ ์ด์ด๋ธ ํธ๋์ด ์ฌ์ ์ค์ ์๋ค๋ฉด ํจ์ ์์์ InputWeight๋ฅผ ์ด์ฉํ์ฌ ํ์ฌ ์ฌ์์ค์ธ ๊ณณ(์ธ๋์ผ์ดํฐ์ ์์น)์ ํด๋ฆฝ์ด ์๋์ง ์๋์ง ๊ฒ์ฌํ ์ ์๋ค.
๋ง๋ฌด๋ฆฌ
ํ์๋ผ์ธ์์ ์ด ์ปค์คํ ํ๋ ์ด์ด๋ธ๋ง ์ ์จ๋ ์ ๋ง ๋ฌด๊ถ๋ฌด์งํ ํ์ฅ์ด ๊ฐ๋ฅํ๋ค. ์ด ๋งค๋ ฅ์ ๋ฐํด์ ๋ค์ ํ๋ก์ ํธ๋ก ํ์๋ผ์ธ์ ์ฌ์ฉํ๋ฉด ์ด๋จ๊น ์๊ฐํ๊ณ ์๋ค. ํ๋ก์ ํธ์ฉ์ผ๋ก ์ปค์คํ ํ๋ ์ด์ด๋ธ์ ์ฌ์ฉํ ๋์๋ ์๊ฐ์ ์ซ๊ฒจ ๊ตฌํ์๋ง ๊ธ๊ธํ๋๋ฐ, ํฌ์คํ ์ ํ๋ฉด์ ์ฐจ๋ถํ ๋์๋ณผ ์ ์์ด์ ์ข์๋ค.
์ด์ ์ ์ค๋ช ํ ์๊ทธ๋๋ณด๋ค๋ ์ปค์คํ ํ๋ ์ด์ด๋ธ์ ์ถ์ฒํ๋ ์ด์ ๋ ๋ฐ๋ณต์ฌ์ฉ์ ์ฉ์ดํ๋ค๋ ์ ๋๋ฌธ์ด๋ค. ๋ค์ ํฌ์คํ ์์ ์ค์ ํ๋ก์ ํธ์ ์ฌ์ฉ๋ ์ฝ๋๋ฅผ ๋ถ์ํด๋ณด๋๋ก ํ์.