본문 바로가기
Programming/Godot

Godot사용팁-AnimationTree노드의 Blendmode2D로 애니메이션 컨트롤

by Wilkyway 2022. 3. 12.

오늘은 AnimationTree노드에 대해 알아보겠습니다.

 

처음 캐릭터의 애니메이션을 만들면 AnimationPlayer노드를 많이 사용하는데요, 이 노드만 이용해서 각종 상태를 코드로 컨트롤하려면 좀 힘듭니다. 많이 힘듭니다. 머리는 쥐가나고, 코드는 스파게티가 되고, 뭐 하나라도 추가하려면 완전...

그래서 여기서도 똑똑하신분이 상태 관리하라고 노드를 하나 주셨는데, 그게 바로 AnimationTree노드입니다. AnimationTree노드를 사용하려면 각각의 동작 Animation은 사전에 구현이 되어있어야합니다. 이미 존재하는 Animation을 컨트롤하는 상태관리자라고 보시면 됩니다. 참고로 저는 코로나 격리기간 중에 아래와 같은 게임을 7살 딸과 함께 만드는 중이었습니다. 탑다운 방식이다보니 상하좌우방면의 idle/walk(run)/attack의 애니메이션이 모두 필요한 상태입니다.

1. AnimationTree노드 추가

우선은 해당 노드를 한번 추가해줍니다. 그리고 인스펙터에서 Tree Root에서 "새 AnimationNodeStateMachine"을 선택합니다. 다른 강좌 영상을 봐도 거의 이거 하나만 씁니다. 아직 아래의 작업공간에는 아무것도 나타나지 않습니다. (제 화면의 idle박스와 walk박스는 미리 작업해 놓은 것이므로 무시하세요.)

내부의 분홍색 라인은 카메라 때문에 나타납니다. 무시하세요.

2. Add BlendSpace2D

화면 하단의 AnimationTree작업공간에서 빈 공간에 마우스 우클릭 후 Add BlendSpace2D를 선택/추가해줍니다. 그리고 이름을 idle이라고 바꾸도록 하겠습니다. 동일한 방법으로 하나 더 추가하여 walk도 만듭니다.

3. Animation 노드 연결

메뉴에서 화살표를 선택하고 idle박스에서 walk박스로 드래그해주면 그 방향으로 화살표 선이 나타나 연결됩니다. 동일한 방법으로 반대쪽도 수행해줍니다.

다음으로 idle박스를 선택한 후 빨간색으로 표시된 버튼을 눌러서, idle이 게임 시작의 최초 "시작"상태임을 인식시켜줍니다. 

(ps) 각 화살표를 클릭하면 인스펙터에서 설정 가능한 부분들이 나타납니다. 여기서 다룰 부분이 아니므로, 이번에는 패스하도록 하겠습니다.  

 

4. BlendSpace편집

idle박스의 편집버튼을 누르면 BlendSpace편집창이 나타납니다.

이미지상에 하단부분 클릭도 빼놓지 않고 추가해줍니다.

X축 및 Y축이 -1 ~ +1까지 있는 좌표계가 나타납니다. 이는 마우스, 키보드 등의 입력값을 말합니다. 즉 캐릭터의 현재 위치를 (0, 0)으로 보고, 이를 중심으로 마우스가 어디에서 눌렸는지를 받아들여 이에 대한 반응을 보여줍니다. (키보드일 경우는 중간이 없고 상/하/좌/우만 있겠죠?). 주의할 점은 Y값의 1이 화면에서는 아래쪽을 의미합니다. 즉, 위 그림에서 보이는 것처럼 (0, 1) 지점에 idle_down 애니메이션을 지정해아 합니다.

메뉴 아이콘의 3번째 버튼이 포인트 추가버튼입니다. 선택 후 위의 그림과 같이 마름모꼴의 각 지점을 클릭하면 에니메이션 추가를 할 수 있습니다. 각각의 좌표계에 애니메이션을 아래와 같이 추가합니다. 또한 혼합 버튼을 ...으로 변경합니다.

 

(-1, 0) : idle_left

(+1, 0): idle_right

(0, -1) : idle_top

(0, +1): idle_down

 

여기까지 진행하면 BlendSpace2D지정은 완료가 됩니다.

 

5. 테스트

이번엔 잘 지정이 되었는지 테스트를 해보겠습니다. 메뉴의 위쪽에 경로: root를 선택합니다. 

그럼 애니메이션 박스를 만들었던 화면으로 전환되는데, 여기서 idle버튼을 플레이합니다.(박스 안쪽에 작은 실행버튼을 클릭합니다.) 그리고 다시 편집 버튼을 눌러 아까의 BlendSpace편집 화면으로 들어갑니다.

그리고 마커 버튼을 선택한 다음 마름모 영역 안에서 마우스를 드래그 하면 캐릭터가 해당 방향으로 애니메이션을 전환하는 모습을 볼 수 있습니다.

동일한 방법으로 walk 애니메이션도 추가해 줍니다. (attack애니메이션도 있으면 추가합니다.)

 

6. 스크립트 코딩

그럼 이렇게 만든 애니메이션을 어떻게 사용하는지 보겠습니다. 우리가 사용할 idle애니메이션은 "AnimationTree"노드의 "parameters/playback"이라는 속성에 존재합니다. 

이 속성을 활용하기 위해 anim_mode = anim_tree.get("parameters/playback")을 사용합니다. 그리고 실제 애니메이션을 구현하는 것은 anim_mode.travel 함수입니다. anim_mode.travel("idle")과 같이 사용하면 idle애니메이션을 실행합니다.

extends KinematicBody2D


const SPEED = 120
var direction = Vector2(0,0)
var motion = Vector2(0,0)
onready var anim_tree = $AnimationTree
onready var anim_mode = anim_tree.get("parameters/playback")


func _physics_process(delta):
	controls()
	movement()	
	anim_control()
	
func controls(): 
# 키보드 입력을 받아서 방향을 정하는 함수
	var LEFT = Input.is_action_pressed("ui_left")
	var RIGHT = Input.is_action_pressed("ui_right")
	var UP = Input.is_action_pressed("ui_up")
	var DOWN = Input.is_action_pressed("ui_down")
	
	direction.x = -int(LEFT) + int(RIGHT)
	direction.y = -int(UP) + int(DOWN)
	
	
func movement():
# 방향을 크기 1인 벡터 motion으로 만들고, 이를 이용해 동작을 구현
	motion = direction.normalized()
	move_and_slide(motion * SPEED, Vector2(0,0))

func anim_control():
# 방향에 따라 애니메이션 지정. 애니메이션의 방향 값만 설정해 놓음
	match direction:
		Vector2(-1,0):
			anim_tree.set('parameters/walk/blend_position', Vector2(-1,0))
			anim_tree.set('parameters/idle/blend_position', Vector2(-1,0))
		Vector2(1,0):
			anim_tree.set('parameters/walk/blend_position', Vector2(1,0))
			anim_tree.set('parameters/idle/blend_position', Vector2(1,0))
		Vector2(0,-1):
			anim_tree.set('parameters/walk/blend_position', Vector2(0,-1))
			anim_tree.set('parameters/idle/blend_position', Vector2(0,-1))	
		Vector2(0, 1):
			anim_tree.set('parameters/walk/blend_position', Vector2(0, 1))
			anim_tree.set('parameters/idle/blend_position', Vector2(0, 1))	
	
    # 방향이 설정된 상태에서 애니메이션을 선택
	if motion.length()!=0: # motion의 크기가 0이 아니면 이동중이므로 walk 애니
		anim_mode.travel("walk")
	else:		# motion의 크기가 0이면 멈춤이므로 idle 애니
		anim_mode.travel("idle")

 

이상으로 AnimationTree노드의 BlendSpace2D속성을 이용한 애니메이션 구현을 알아보았습니다. 

 

~~끝~~

반응형

댓글0