디지털 양피지/Unity3D2015. 2. 13. 17:31

1. Animation 만들기

Animation을 만들 GameObject를 선택하고 Window-Animation 창을 연다. 왼쪽에 Create New Clip을 선택하고 Animation 폴더를 만들어 저장하면 해당 GameObject에 대한 Animation이 만들어진다.


Animation 창에서 Samples를 설정하는데 기본 값은 60이다. 이는 1초에 보여주는 이미지를 설정하는 것으로 숫자가 클 수록 부드러운 동작을 볼 수 있다. 모바일 환경에서는 15~20 정도가 적당한다.




이상태에서 필요한 KeyFrame을 선택하고 GameObject를 움직이면 Animation 이 생성 된다. 아래 이미지는 6프레임을 선택하고 값을 변경한 모습을 보여준다. (프레임을 선택한 상태에서 GameObject를 변경하면 자동으로 녹화된다.)



2. 메카님

메카님은 유니티 4.0부터 지원하는 기능으로 간단한 작업방식으로 한번에 제작한 Animation을 다른 객체에도 적용할 수 있어 에니메이션 작업을 수월하게 수행 할 수 있다. 먼저 아래와 같이 Animator Controller를 생성한다.




TestCharControl이라고 이름을 주고 생성하면 Finite State Machine 편집기가 나온다. 여기에 미리 만들어 놓은 Amimation Clip을 끌어다 놓으면 하나의 State가 완성된다. 이전에 만들었던 Idle을 가지고 다음과 같이 만들 수 있다.

(Project View에 미리 만들어놓은 idle animation을 아래와 같이 Animation Controller에 끌어다 놓는다.)



기본적으로 주황생 상태로 표시 되는데 재생 상태로 설정이 되어 있기 때문이다.

애니메이션 2개를 추가하고 State를 클릭하고 오른쪽 마우스 메뉴에서 'Make Transition'을 클릭하면 하얀선이 나온다. 이렇게 전이될 State를 아래와 같이 만든다.




Jump의 경우 땅에 있을 때에만 가능해야 하는데 이럴 경우 왼쪽 아래의 Parameter를 추가하여 동작할 수 있도록 한다.

이러한 Parameter를 이용하여 전이 될때 조건을 설정하여 특정 값일때만 이동하거나 Trigger를 연결 시킬수도 있다. 아래 그림과 같이 Transition을 선택하면 Inspector에서 Condition을 설정할 수 있다.



이렇게 만들어진 Animation Controller는 게임 오브젝트에 Animator에 넣어 객체를 Animate 할 수 있다.

그림과 같이 Char_Root라는 Character에 Animation Controller를 추가하고 재생하면 프로그레시브가가 움직이면서 State가 재생 되는 모습을 볼 수 있다.





캐릭터가 Ground에 있는지 알기 위해서는 일반적을 Physics2D.Linecast 를 사용한다. 

public static RaycastHit2D Linecast(Vector2 start,Vector2 end, int layerMask = DefaultRaycastLayers, float minDepth = -Mathf.Infinity, float maxDepth = Mathf.Infinity);

Return 값은 RaycastHit2D를 하지만 이를 이용하여 true/false 값을 많이 사용한다.

start와 end 포인트 사이에 특정 레이어에 GameObject가 있는지 확인할 수 있다. 사용지 주의 할 점은 3번째 parameter인 layerMask 이다. 선택한 layer를 전달하는게 아니라 layer bitmask 를 전달해야 한다.


bool grounded = Physics2D.Linecast (start.position, end.position, 1 << LayerMask.NameToLayer("Ground"));


예를 들어 위와 같이 두 지점 사이에 Ground Layer가 있는지를 알수 있다. 


음...왜 이렇게 써야 하나 고민을 했는데 ....API Manual을 보니 LayerMask에 이를 지원하는 함수가 있다. 위와 같은 경우 다음과 같이 바꾸어 쓰면 똑같은 결과를 얻을 수 있다.


bool grounded = Physics2D.Linecast (transform.position, groundCheck.position,  LayerMask.GetMask("Ground"));


public static int GetMask(params string[] layerNames);    // Name을 통해 LayerMask값을 int로 받아 올 수 있다.


스크립트에서 메카님을 통해 설정한 값을 사용하는 방법은 아래와 같다.

using UnityEngine;

using System.Collections;


public class TestCharMove : MonoBehaviour {


private Animator animator;

private float horizontalAmount;

private Vector2 horizontalSpeed;

[HideInInspector]

public bool facingRight = true;

[HideInInspector]

public bool jump = false;

public float maxSpeed = 5.0f;

public float moveForce = 365f;

public float jumpForce = 300f;

public Transform groundCheck;

private bool grounded = false;

void OnEnable(){

  // Animator Component를 가져온다.

animator = GetComponent<Animator>();


}

void Flip(){

facingRight = !facingRight;

Vector3 theScale = transform.localScale;

theScale.x *= -1;

transform.localScale = theScale;

}

void Start () {

}

// Update is called once per frame

void Update () {

  grounded = Physics2D.Linecast (transform.position, groundCheck.position,  LayerMask.GetMask("Ground"));

if(Input.GetButtonDown("Jump") && grounded){

  jump = true;

}

}

 

void FixedUpdate(){

horizontalAmount = Input.GetAxis("Horizontal");

Debug.Log ("Horizontal: "+horizontalAmount);

animator.SetFloat("moveLR", Mathf.Abs (horizontalAmount));

if(horizontalAmount*rigidbody2D.velocity.x < maxSpeed){

rigidbody2D.AddForce(Vector2.right*horizontalAmount*moveForce);

}

if(Mathf.Abs(rigidbody2D.velocity.x) > maxSpeed){

rigidbody2D.velocity = new Vector2(Mathf.Sign(rigidbody2D.velocity.x)*maxSpeed, rigidbody2D.velocity.y);

}

if(horizontalAmount > 0 && !facingRight){

Flip();

}else if(horizontalAmount < 0 && facingRight){

Flip();

}

if(jump){

animator.SetTrigger("jump");

rigidbody2D.AddForce(new Vector2(0f, jumpForce));

jump = false;

}

if(horizontalAmount == 0){

horizontalSpeed = rigidbody2D.velocity;

horizontalSpeed.x = 0;

rigidbody2D.velocity = horizontalSpeed;

}

}

}


위와 같이 필요한 곳에 Animator 컴퍼넌트를 가져와 SetFloat, SetTrigger등을 통해 설정할 수 있다.


'디지털 양피지 > Unity3D' 카테고리의 다른 글

Unity3D - Gizmos 활용  (0) 2015.02.16
Unity3D - Sorting Layer 사용하기  (0) 2015.02.16
Unity3D - Sprite(Sprite Editor)  (0) 2015.02.13
Unity - 최적화  (0) 2015.01.13
Unity Script Basic- 1  (0) 2015.01.07
Posted by 빨간 양말