적을 생성하고 총알과 상호작용할 수 있도록 만들어 본다.

적은 Character를 상속하여 구현하고 리소스는 언리얼엔진의 다른 샘플에서 가져다 쓰기로 한다.

 

플레이어를 만들 때처럼 콜라이더 크기와 메시의 위치를 조절하고 정면을 방향을 맞춘다.


그리고 BP_Enemy는 플레이어와 동일한 스켈레탈 메시를 사용하고 구분하기 위해서 머티리얼은 복사하여 새로 생성하고 색만 바꾸어서 적용했다.

 

애니메이션은 언리얼에서 제공하는 3인칭 시점 게임 샘플에서 Idle과  RunForward만 가져다 사용했다.


가지고 온 애니메이션을 적용하니 메시가 이상하게 변형되었다. 아마도 리깅이 달라서 생긴 문제로 보인다. 

 

Unreal Engine - Enemy Mesh

 

이 상태로 작업해도 크게 문제는 없을 것 같아 그대로 진행한다.

 

애니메이션 에셋을 더블클릭하여 에셋의 디테일창을 연다. Idle과 Run 모두 Loop는 체크해 준다.

 

RunForward의 경우 애니메이션이 위치를 수정하는 게 포함되어 있어서 Root Motion > Force Root Lock을 체크해 준다.

 

Unreal Engine - Root Motion

 

보통 Enable Root Motion이 체크된 경우 애니메이션 동작이 위치 변형이 반영되는데 이 애니메이션은 RootMotion은 비활성화되어 있어도 위치가 변형되어 Force Root Lock을 체크했더니 해결되었다.

 

BP_EnemyAnimation

플레이어와 마찬가지로 Speed 변수를 만들어서 에너미의 Velocity의 크기를 가져다 상태를 전환하는 값으로 사용했다.

 

BP_Enemy의 Anim Class에 BP_EnemyAnimation을 적용시킨다.

Unreal Engine - Anim Graph
Unreal Engine - Anim State
Unreal Engine - Run to Idle
Unreal Engine - Idle to Run

 

적의 인공지능

적은 플레이어를 추적해서 공격하는 기능이 필요한데 우선 플레이어를 타깃으로 추적하는 부분까지만 구현하기로 한다.

 

AIController 블루프린트를 상속한 BP_EnemyAIController를 생성한다.

 

먼저 BP_Player 타입의 Target 변수를 만들고 시작할 때 GetPlayerCharacter를 캐스트 해서 변수를 저장한다.

 

Unreal Engine - BP_EnemyAIController > BeginePlay

 

타겟을 향해 이동하는 함수는 Move to Location을 사용한다.

 

타겟을 향해 이동할 때 타겟의 방향으로 회전하면서 이동하기 때문에 따로 회전하는 기능은 추가할 필요가 없다.

 

Unreal Engine - Event Tick > MovetoLocation

 

저장해 놓은 Target에서 위치를 가져와서 Move to Location의 Dest, 목표로 설정해 준다.

 

이렇게 만들어 놓은 AI 컨트롤러는 BP_Enemy > Details > Pawn > AI Controller Class에 할당한다.

 

적 스폰

이제 만들어 놓은 Enemy를 스폰해 본다.

 

스폰을 어디서 처리할지가 애매했는데 일단 게임의 전반적인 기능을 담당하는 BP_MyGameMode에서 스폰 기능을 구현하기로 한다.

 

BP_MyGameMode에 Spawn Enemy 함수를 추가한다.

 

적은 플레이어 위치를 기준으로 일정한 범위 내에서 랜덤 한 위치에 생성되도록 한다.

 

먼저 플레이어 위치 벡터를 가지고 와서 일정 범위 안에서 랜덤 한 값만큼을 오프셋으로 사용해서 생성될 위치를 정한다.

 

Unreal Engine - BP_MyGameMode > Spawn Enemy Func

 

Random Float in Range를 사용해서 Min ~ Max 범위 안의 값을 오프셋으로 사용한다.

 

Spawn Actor BP Enemy의 Spawn Transform에 생성한 무작위 위치를 할당하고 class는 BP_Enemy로 설정해 준다.

 

이제 이 함수를 호출해서 적을 생성하면 된다.

 

방식은 일정 시간 간격으로 생성되도록 할 것이다.

 

BP_MyGameMode의 Event Begin Play에서 Set Timer by Event를 호출하고 Custom Event인 EnemySpawnEvent를 만든다. EnemySpawnEvent는 SpawnEnemy를 호출하는 기능만 하며 Set Timer by Event의 Event 파라미터에 등록한다.

 

Time에 적을 생성할 주기를 정해주는데 일단 3초 간격으로 적이 생성되도록 한다.

 

그리고 3초마다 계속 생성되도록 Looping은 True로 체크해 준다.

 

Unreal Engine - BP_MyGameMode > EventGraph

 

여기까지 진행하고 테스트를 해보는데 적이 플레이어 주변 랜덤한 위치에 생성은 되지만 움직이지 않는다.

 

Auto Possess AI

BP_Enemy의 디테일 창으로 다시 돌아가서 Pawn 탭의 Auto Possess AI 옵션을 확인한다.

 

Unreal Engine - Auto Possess AI

 

해당 옵션은 기본 값으로 Placed in World로 되어있는데 이 옵션은 미리 맵에 생성된 액터에게만 해당하며 플레이 도중에 생성된 액터는 동작하지 않는다.

 

각 옵션의 사용법을 알아둔다.

 

Disabled

AI 컨트롤러가 캐릭터를 자동으로 제어하지 않는다. AI 컨트롤러를 수동으로 할당해한다.

 

Placed in World

맵에 배치된 AI 캐릭터가 게임 시작 시 AI 컨트롤러에 의해 자동으로 제어된다. 주로 에디터에서 맵에 직접 배치된 AI 캐릭터에 사용된다.

 

Spawned

게임 도중 스폰된 AI 캐릭터가 AI 컨트롤러에 의해 자동으로 제어된다. 런타임 중에 생성된 AI 캐릭터에 사용된다.

 

Placed in World or Spawned

맵에 배치된 AI 캐릭터와 게임 도중 스폰된 AI 캐릭터 모두 AI 컨트롤러에 의해 자동으로 제어된다. 모든 상황에서 AI 캐릭터를 자동으로 제어할 때 사용한다.

 

이 옵션을 적의 배치 방식에 맞는 Spawned로 설정한다.

 

이제 다시 플레이해 보면 여전히 동작하지 않는다.

 

NavMeshBoundsVolume

만들어놓은 지형에 AI가 돌아다닐 수 있는 범위를 정해주어야 한다.

 

해당 범위만큼 내비게이션의 길 찾기 연산에 포함되기 때문에 복잡하고 넓을수록 많은 연산을 차지하게 된다.

 

Place Actor에서 NavMeshBoundsVolume을 찾아서 레벨에 생성한다. 그리고 AI가 돌아다닐 수 있는 범위만큼 크기와 높이를 조절한다.

 

범위가 원하는 대로 지정됐는지 확인하려면 플레이하지 않고 뷰포트에서 키보드 'P'를 누르면 지정된 범위만큼 녹색으로 표시가 된다.

Unreal Engine - NavMeshBoundsVolume

 

이제 진짜로 테스트 플레이를 해본다.

 

Unreal Engine - Test Play

 

랜덤 한 위치에서 적이 생성되고 생성된 적은 플레이어를 추적하기 시작한다.

 

추적하는 동안 이동하는 애니메이션이 재생되고 목적지에 도착하면 일반 상태의 애니메이션이 재생된다.

 

플레이어가 이동하면 변경된 위치를 계속해서 따라가게 된다. 여기까지 원하는 대로 잘 동작하게 되었다.

 

 

728x90
반응형

무기 생성

무기는 언리얼엔진의 1인칭 슈팅 게임 샘플에서 에셋을 가져다 사용했다.

 

Unreal Engine - Gun

 

플레이 시 캐릭터의 손에 위치하게 생성하도록 한다.

 

총에 대한 기능을 구현하고 참조하는 데 사용하기 위해서 BP_Gun 클래스를 만든다.

 

BP_Gun은 기본적인 클래스인 Actor를 상속하여 만들고 메시를 넣기 위해서 SkeletalMesh 컴포넌트를 추가한다.

 

Unreal Engine - BP_Gun

 

추가한 SkeletalMesh 컴포넌트에 무기 메시를 추가한다.

 

Unreal Engine - Add Mesh

 

무기 장착

만들어 놓은 BP_Gun을 사용해서 게임이 시작될 때 플레이어의 손 위치에 생성되도록 한다.

 

그렇게 하기 위해서 먼저 플레이어 캐릭터로 사용하고 있는 Skeletal Mesh 파일을 더블 클릭하여 열어준다.

 

Skeletaon Tree 창에서 적당한 위치에 무기를 장착할 위치로 사용할 소켓을 추가한다.

 

Unreal Engine - Skeleton Tree
Unreal Engine - Weapon Socket

 

이제 BP_Player 파일을 열고 무기를 생성하는 함수를 추가한다.

 

Unreal Engine - Equip Weapon

 

Spawn Actor from class는 특정 클래스를 선택하여 생성할 수 있다. 여기서 드롭다운을 열고 생성하려는 BP Gun을 선택한다.

 

Attach Actor to Component는 액터의 위치를 특정할 수 있다. 여기서 위에서 플레이어 캐릭터의 Skeleton Tree에 추가한 소켓에 위치하도록 설정한다.

 

그리고 Event Graph로 돌아가 BeginPlay에서 Equip Weapon을 호출한다.

 

탄환 추가

Actor를 상속한 BP_Bullet을 생성한다.

 

BP_Bullet에 Static Mesh 컴포넌트를 추가하여 탄환으로 사용할 적당한 메시를 추가한다.

Unreal Engine - BP Bullet

 

탄환의 기능을 담당할 Projectile Movement 컴포넌트를 추가하여 탄환의 동작을 세팅한다.

 

Unreal Engine - Projectile

 

속도는 발사하는 기능까지 구현한 이후에 테스트를 하면서 적당한 속도를 세팅하기로 하고 Projectile Gravity Scale의 값은 0으로 설정하여 중력의 영향을 받지 않고 직선방향으로 날아가도록 한다.

 

탄환 발사

BP_Gun에 Fire 함수를 추가하여 탄환을 발사하는 기능을 구현한다.

 

Unreal Engine - BP Gun Fire

 

Spawn Actor from class를 사용해서 BP_Bullet을 생성하고 탄환이 생성될 위치는 총의 SkeletalMesh에서 총구의 위치에 소켓을 만들고 Spawn Transform의 위치로 사용한다.

 

탄환의 발사를 위해서 새로운 Input Action과 맵핑을 추가한다.

 

IA_Fire, 마우스 좌클릭으로 맵핑한다. 

 

Unreal Engine - IA_Fire

 

 

Down으로 트리거를 세팅하여 누른 상태에서 인풋이 리턴되도록 하고 밸류는 bool타입으로 한다.

 

BP_Gun 수정

발사 속도를 설정하기 위해서 BP_Gun을 수정한다.

 

발사 속도 FireRate(float), 시간을 확인하기 위한 Timer(float), 발사 가능 여부를 확인하기 위한 CanFire(Boolean) 변수를 추가한다.

 

Unreal Engine - Check FireRate

 

FireRate는 0.5로 설정하고

매프레임 시간을 체크하여 발사를 했다면 FireRate만큼 대기 후 CanFire가 되도록 만든다.

 

그리고 CanFire를 확인하여 발사되도록 Fire함수를 수정한다.

 

Unreal Engine - Fire Function

 

Fire 함수 호출 시 CanFire를 확인하고 True일 때만 발사가 되도록 한다.

 

발사가 진행되고 나면 CanFire를 False로 만든다.

 

Unreal Engine - Test Play

 

좌클릭을 누르고 있는동안 Fire가 호출되고 이때 CanFire를 체크하고 FireRate 간격으로 탄환이 발사된다.

 

이벤트 그래프 수정

Event Tick에서 CanFire를 체크하는 과정을 단순화할 필요가 있어 보인다.

 

찾아보니 SetTimerbyEvent라는 함수가 있어서 이걸 사용하기로 한다.

 

SetTimer by Event는 호출된 이후 Time 파라미터만큼 대기한 후 Event를 실행시킨다.

 

BP_Gun의 Event Graph로 이동한다.

 

CanFire를 True로 바꾸어 주는 Custom Event를 생성한다.

 

Event Graph > Add Custom Event > ResetCanFire > SetCanFire = true

 

Unreal Engine - Custom Event

 

Fire 함수로 이동해서 SetCanFire = false 뒤에 SetTimerbyEvent 노드를 추가한다.

 

Event를 끌어서 Create Event 노드를 만들고 실행시킬 ResetCanFireEvent를 선택한다.

 

Time 파라미터는 GetFireRate를 가져와 연결해 준다.

 

Unreal Engine - SetTimerbyEvent

 

플레이했을 때 문제없이 동작하는 걸 확인했다.

 

제공되는 함수를 잘 파악하고 있으면 동일한 기능을 더 간단하면서 효율적으로 구현할 수 있을 것 같다.

728x90
반응형

플레이어 애니메이션

언리얼 엔진에서 기본으로 포함된 모델에는 애니메이션도 포함되어 있어 이걸 활용해 움직일 때 플레이어가 애니메이션이 재생되도록 만들어 본다.

 

애니메이션은 Idle,  Wakl_Fwd 두 가지밖에 없어 일단 두 가지 동작만 추가한다.

Unreal Engine - Tutorial Animation

 

BP_PlayerAnimation 추가

먼저 블루프린트를 추가한다. 

BluePrints 폴더 우클릭 > Animation > Animation Blue Print > BP_PlayerAnimation

Unreal Engine - Animation Blue Print

 

애니메이션 블루프린트를 생성할 때 어떤 모델을 사용할 것인지 스켈레톤을 특정하는 창이 뜬다.

 

플레이어의 스켈레톤인 TutorialTPP_Skeleton을 선택하여 생성한다.

 

애니메이션 블루프린트 창을 열면 Event Graph와 Anim Graph 탭이 보인다.

 

먼저 Anim Graph 창에서 State Machine을 추가한다.

 

Animation State Machine

빈 공간을 우클릭하여 추가하거나 Output Pose에서 Result를 드래그하여 추가할 수 있다.

 

Unreal Engine - Animation State Machine

 

생성한 StateMachine은 Output Pose의 Result와 연결한다.

 

StateMachine을 더블클릭하면 상태머신 내부로 이동하고 여기서 애니메이션을 추가할 수 있다.

 

내부에는 Entry 노드가 있는데 여기서 화살표 아이콘을 드래그하여 빈 곳에 놓고 Add State를 선택하면 애니메이션을 추가할 수 있다.

 

또는 애니메이션 에셋을 드래그하여 빈 공간에 놓아도 추가할 수 있다.

 

이때 사용할 수 있는 애니메이션 리스트를 볼 수 있는 창이 있다.

 

Unreal Engine - State Machine Select Animation

 

위 사진에서 점 세 개로 된 아이콘을 클릭하면 사용가능한 애니메이션 목록이 보이는데 블루프린트를 생성할 때 특정한 스켈레톤에서 사용가능한 애니메이션 목록으로 보인다.

 

여기서 Idle과 Walk 애니메이션 두 가지를 일단 끌어다 놓는다.

 

그리고 Entry에서 바로 연결되는 State는 기본상태로 Idle과 연결시켜 주고 Idle은 테두리 부분에 마우스를 올리면 색이 변경되는데 이 상태에서 드래그하면 다른 애니메이션과 연결할 수 있는 상태가 된다.

 

Idle과 Walk를 서로 왔다 갔다 할 수 있도록 연결시켜 놓는다.

 

Unreal Engine - State Transition

 

추가한 애니메이션을 더블 클릭하면 애니메이션 세부 설정을 할 수 있는 창을 열어준다.

 

이때 테두리가 아닌 중심을 잘 선택해야 하는데 이 상태는 마우스 커서가 십자 모양이다.

 

Unreal Engine - Animation Detail

 

세부설정에서 해당 애니메이션 노드를 선택하고 디테일 창 > Settings > Loop Animation을 체크해서 반복 재생하도록 한다.

 

Unreal Engine - Animation Loop

 

Walk 애니메이션도 움직이는 상태인 동안 계속해서 재생되어야 하기 때문에 해당 옵션을 체크해 준다.

 

Animation Event Graph

스테이트 머신에 추가한 두 애니메이션 사이에 연결한 트랜지션에는 어떤 조건에서 애니메이션이 전환되는지 상태가 필요하다.

 

이동에 관련된 애니메이션이기 때문에 플레이어가 움직임과 관련된 값인 Velocity를 가지고 조건을 만들어 본다.

 

이벤트 그래프에는 Event Blueprint Update Animation과 Try Get Pawn Owner 노드가 기본으로 있다.

 

Try Get Pawn Owner 노드에서는 이 애니메이션 블루프린트가 연결된 Pawn 즉 플레이어의 정보들을 가지고 올 수 있다.

 

Return Value를 드래그하여 GetVelocity 노드를 추가한다.

 

Unreal Engine - Animation Event Graph GetVelocity

 

Velocity는 방향을 포함한 Vector3 값인데 현재 움직이는지 여부만 판단하면 되기 때문에 이 값을 float 형태로 사용하기 위해서 Vector Length 함수로 크기만 가지는 값의 형태로 만든다.

 

그리고 이 값을 State에서 사용하기 편하도록 변수를 추가해 값만 가져다 쓸 수 있도록 한다.

 

Unreal Engine - Event Graph Add Variable

 

이벤트 그래프 창에서 My Blue Print 탭을 보면 VARIABLES 목록이 있고 여기에 변수를 추가할 수 있다.

 

Speed 이름의 Float 타입 변수를 추가한다.

 

이벤트 그래프에 Vector Length의 리턴값을 끌어다 놓고 SetSpeed와 연결한다.

 

이 값은 매번 업데이트 되어야하기 때문에 Event BluePrint Update Animation과 연결이 필요하다.

 

Unreal Engine - Animation Event Graph Flow

 

이제 Speed에는 플레이어가 움직일 때마다 변경되는 값이 저장된다.

 

상태 머신 트랜지션 조건

Unreal Engine - State Transition

 

다시 상태머신 창으로 돌아와서 위 트랜지션 아이콘을 더블 클릭하면 트랜지션 창이 열린다.


해당 창에는 Result 노드가 기본으로 있다. 이 노드의 인풋 값인 Can Enter Transition은 Boolen 타입의 값을 받고 있다.

 

따라서 Speed 값의 상태에 따라서 Boolean 타입을 반환하도록 연산자를 추가해주어야 한다.

 

Speed 값은 0일 때는 Idle , 0이 아니면 Walk이다. 이걸 연산자를 사용해 표현한다.

 

먼저 사용할 값인 Speed의 값을 GetSpeed를 통해서 가지고 온다.

 

그리고 링크를 끌어다 놓고 Operator를 검색해 보면 다양한 연산자들이 나오는데 현재 Idle -> Walk로 전환되는 상태가 어떨 때인지 조건이기 때문에 != 연산자와 연결한다.

 

Unreal Engine - Transition Idle to Walk

 

밑에 비교할 값은 연결된 게 없으면 상수를 입력해서 결정할 수 있어 보인다. 비교할 값은 0이기 때문에 기본값 그대로 둔다. 그리고 리턴되는 Boolean 값을 Result와 연결한다.

 

Walk -> Idle 도 마찬가지로 노드를 구성하는데 여기서는 연산자를 == 를 사용해서 속도가 0일 때 즉 움직이지 않을 때는 Idle 애니메이션이 재생되도록 하면 된다.

 

Unreal Engine - Transition Walk to Idle

 

연산자는 A (연산자) B 형태로 위에 들어오는 값이 A, 아래가 B라는 점을 염두한다.

 

플레이어 애니메이션 블루프린트 연결

이제 지금까지 만든 애니메이션 블루프린트를 플레이어에서 사용하도록 한다.

 

BP_Player > Details > Animation > Anim Class

 

여기서 파일 검색 아이콘을 눌러서 위에서 만든 BP_PlayerAnimation를 검색해서 등록한다.

 

Unreal Engine - Add Anim Class

 

 

결과 

Unreal Engine - Test Play

 

움직일 때 애니메이션이 잘 전환되고 기존 동작들과도 문제가 없어 보인다.

728x90
반응형

+ Recent posts