유니티 3D의 삼각함수를 이용한 원운동 애니메이션의 예
아래의 그림과 같이 빈 게임오브젝트 안에 Sphere 오브젝트를 포함시키고 Sphere를 약간 위쪽으로 이동하여 부모 오브젝트의 중심에서 떨어지게 배치한다
Sphere 의 부모인 빈 게임오브젝트에 회전을 적용하면 자식 오브젝트인 Sphere 가 Pivot 중심으로 회전하는 효과를 낼 수 있다
이 때 Sphere가 회전하면서 Y축상의 위치가 최대가 될 때 회전 속도가 최소가 되고 Y축상의 위치가 최저가 될 때 회전 속도가 최대가 되도록 제어하려고 한다.
즉, 위에서 Sphere 가 Pivot 중심으로 회전할 때 아래로 향할 때는 속도가 증가해야 하고 올라갈 때는 속도가 점차 감속되도록 자연스러운 애니메이션을 구현하려고 한다
위의 그림처럼 Sphere 가 현재 위치에 있다가 왼쪽으로 회전하면서 내려올 때 속도가 점차 증가하면서 가장 아래쪽에 위치할 때 속도가 최대가 되어야 한다면 현재 각도가 0도 라면 180도 위치에서 속도가 최대가 되어야 하며 180도를 통과하면서 속도가 점차 줄어들어서 360도(0도) 지점에서 속도가 최소가 되도록 제어해야 한다. 이처럼 증가와 감소가 규치적으로 반복되는 운동은 삼각함수를 이용하여 쉽게 구현할 수가 있다
위의 요구사항은 0도~360도 운동을 반복하면서 가속도 증가/감소 가 1회 발생한다. 즉, 위의 원운동(360도)에서는 삼각함수 사인값 특성(0도~180도 구간)이 나타나야 한다는 것이다. 결론은 360도를 180도로 환산하여 삼각함수 Sin 값을 적용하면 된다
아래의 스크립트를 작성하고 Sphere를 포함하고 있는 부모 오브젝트에 포함시키고 Play 모드로 테스트하면 회전 속도가 증가 감소를 반복하면서 회전하는 애니메이션을 확인할 수 있다
#pragma strict
function Start () {
}
function Update () {
var deg:float = transform.eulerAngles.z; //현재의 회전각도 (일반각)
if(deg<0.5 || deg>359.5)deg = 1;
var rad:float = deg/2*(Mathf.PI/180); // 라디안 각으로 변환
var sVal:float = Mathf.Sin(rad);
transform.Rotate(Vector3.forward*sVal*Time.deltaTime*300);
}
삼각함수를 이용한 부드러운 직선운동의 예
아래 그림의 Scene 뷰에 있는 Sphere 오브젝트를 X 축상의 10 위치에서 15 까지 이동하는 애니메이션을 구현할 때 삼각함수를 사용하려고 한다
시작점에서 도착점까지 이동할 때 시작시에는 점차 가속도가 자연스럽게 증가하도록 해야하고 도착점에 도달할 때는 점차 속도가 줄어들면서 부드럽게 정지하도록 한다.
위의 요구사항은 삼각함수의 사인파 곡선 중 0도~180도 사이의 구간에 해당하는 내용이므로 Mathf.Sin() 함수를 활용하면 된다.
다음과 같은 스립트를 작성하여 Hierarchy 뷰의 Sphere 에 포함시키고 Play 모드로 테스트하면 된다
#pragma strict
internal var posStart:float; //시작점(X좌표)
internal var posEnd:float = 15; //도착점(X좌표)
internal var range:float; //전체거리(도착점-시작점)
internal var posCurrent:float; //현재위치(X좌표)
function Start () {
posStart = transform.position.x;
range = posEnd - posStart;
posCurrent = posStart+0.1f;
}
//x좌표 10~15 사이의 이동
function Update () {
if(posCurrent >14.99) return;
var deg:float = (posCurrent-posStart)/range*180f;//전체거리에 대한 현재 이동위치를 180도(일반각)로 변환
var delta:float = Mathf.Sin(deg/180*Mathf.PI); //라디안 각으로 변환
transform.Translate(Vector3.right*delta*0.1f); //사인값의
posCurrent = transform.position.x;
}