본문으로 바로가기

[Unreal Engine 5] Gameplay Ability System - 2

category UnrealEngine/기능 2024. 3. 17. 21:57

GameAbilitySystem의 가장 중요한 부분중 하나는 AbilitySystemComponent 다.

이 Component는 Actor에 추가할 수 있으며 AbilitySystem, Granding Abilities, Activating Abilities, Handling Notifications,

GameplayEffect applied 등 많은 것을 처리한다.

 

즉, 해당 캐릭터(Actor)가 GameplayAbilitySystem에 추가되길 원한다면, AbilitySystemComponent는 꼭 추가해야 한다.

 

또한 전 시간에 설명했듯이, 우리는 힘, 지능, 민첩과 같은 능력치를 Attribute라고 하기로 했다.

이 Attribute를 모아놓은 것을 AttributeSet이라고 한다.

 

이제 우리는 AbilitySystemComponent를 추가하여 Gameplay Ability System에 대해 알아볼 것이다.

그런데 그전에 알아둬야 할 것이 있다.

 

AbilitySystemComponent는 꼭 Character가 가지고있지 않아도 된다.

 

우리가 어떠한 Actor에 AbilitySystemComponent와 AttributeSet을 추가했다고 해보자.

그리고 이 Actor가 어떠한 영향에 의해 ( HP가 0이 되었다거나, 특정 로직으로 강제로 삭제해야 한다거나.. ) 파괴된다면

AbilitySystemComponent와 AttributeSet도 당연히 파괴되어야 한다.

그리고 다시 Actor를 만들어 낸다면, AbilitySystemComponent와 AttributeSet이 재 생성된다.

 

결국 '다시시작' (부활) 이 가능한 게임에서는 재사용이 가능할 수 있는 객체를 파괴하고 있다는 것이다.

 

그럼 Actor대신 어떠한 객체에 AbilitySystemComponent를 넣고, 해당 객체가 관리할 수 있다고 해보자.

이 경우에는 Actor가 파괴되더라도, AbilitySystemComponent와 AttributeSet을 재사용할 수 있다.

우리의 Actor의 힘이 10이였다고 해보자, 그 상태로 다시 시작을 한다고 하여서 힘이 10에서 변할 필요가 있을까?

그것 또한 아니다.

 

파괴되더라도 Actor를 새로 생성하고, 우리가 관리하던 객체에 연결해주기만 하면 된다.

 

이 문서를 작성하면서, 우리의 캐릭터는 PlayerState에서 AbilitySystemComponent를 가지게 할 것이다.

AI는 동일하게 캐릭터가 AbilitySystemComponent를 가지게 된다.

 

일단 PlayerState를 만들어 AbilitySystemComponent를 선언해준다.

 

그리고 PlayerState의 생성자에서 AbilitySystemComponent를 만들어준다.

 

여기서 궁금할건 SetIsReplicated와 SetReplicationMode이다.

 

이는 Replicate (복제) 에 대해서 조금 알아야 한다.

 

우리가 멀티플레이어 게임에서, 어떠한 변수를 선언하고 해당 변수를 Replicated 변수로 선언했다고 하자.

그리고 해당 변수의 값이 서버에서 변경되었을 때

 

 

서버는 모든 클라이언트들에게 변경된 해당 변수 값을 알려주고, 그 값으로 업데이트 합니다.

이 행위를 복제(Replicate)라고 합니다.

 

이러면, 멀티플레이어 개발을 해보신 분들은 어떠한 의구심을 품을 수 있습니다.

? : 그렇다면 Replicate 선언된 변수가 클라이언트 중 하나에서 변경된다면, 그 값은 서버에 알려주나요? (혹은 변경 되어야 한다라고 알려주나요?) : (즉, Replicate가 양방향으로 작동하나요?)

 

복제는 단방향으로만 작동한다. 변수가 Replicate로 표시되면 서버는 해당 변경 사항을 알지 못하기 때문에 클라이언트에서는 해당 값을 변경해서는 안된다.

대신 RPC (Remote Procedure call)로 처리합니다. 물론 이에 대해선 나중에 작성하겠습니다.

 

그럼 SetIsReplicated에 대해 알 수 있습니다.

SetIsReplicated 함수는 해당 컴포넌트를 복제시킬것이냐 라는 것입니다.

 

ReplicationMode는 다음과 같이 요약할 수 있다.

 

 

ReplicationMode::Full은 GameplayEffect가 모든 클라이언트에 복제됩니다.

ReplicationMode::Mixed는 GameplayEffect가 소유하고 있는 클라이언트에서만 복제됩니다.

그리고 Gameplay Cues와 Gameplay Tags는 모든 클라이언트에 복제됩니다.

ReplicationMode::Minimal은 GameplayEffect가 복제되지 않습니다. 그리고 Gameplay Cues와 Gameplay Tags는 모든 클라이언트에 복제됩니다.

 

위에서 설명했듯 우리가 아직 알지못하는 GameplayEffect, Gameplay Cues, Gameplay Tags가 나왔습니다.

이는 추후에 알아보도록 하며

Mixed는 플레이어에, Minimal은 AI에 적합하므로 해당 문서에서는 이와 같이 작성할 것입니다.

 

이제 위에서, 우리는 Actor에 AbilitySystemComponent가 붙어있어야 GameplayAbilitySystem에 참여할 수 있다고 했습니다.

AbilitySystem은 Owner Actor와 Avatar Actor를 설정할 수 있습니다.

Owner Actor는 해당 Component를 가지고 있는 Actor 입니다.

Avatar Actor는 해당 Component를 적용받고 화면에 보여질 Actor 입니다.

AI (적군)은 Owner Actor와 Avatar Actor가 해당 Actor가 될 것입니다.

 

우리의 캐릭터는 PlayerState가 AbilitySystemComponent를 가지기로 했습니다.

그러므로 Owner Actor는 PlayerState이며 Avatar Actor는 Actor 입니다.

 

이제 OwnerActor와 AvatarActor를 설정해주어야 합니다.

해당 설정은 InitAbilityActorInfo 함수로 설정합니다.

 

이제 문제는, 해당 함수를 언제 어디서 호출해야 하는가 입니다.

알아야 할 점은 다음과 같습니다.

InitAbilityActorInfo는 Possession이 끝난 후에 수행되어야 합니다.

(즉, Controller가 Pawn에 Set된 후에 수행되어야 합니다.)

 

몇 가지 타이밍이 있습니다.

 

1. Actor가 AbilitySystemComponent를 가지고 있는 경우

Server는 PossessedBy가 호출되면 InitAbilityActorInfo를 호출하면 됩니다.

Client는 AcknowledgePossession이 호출되면 InitAbilityActorInfo를 호출하면 됩니다.

 

 

2. PlayerState가 AbilitySystemComponent를 가지고 있는 경우

Server는 PossessedBy가 호출되면 InitAbilityActorInfo를 호출하면 됩니다.

Client는 AcknowledgePossession을 사용할 수 없습니다. 왜냐면 우리의 AbilitySystemComponent는 PlayerState에 있기 때문입니다.

대신 OnRep_PlayerState를 사용합니다. 해당 함수는 PlayerState가 복제되었을때 오는 콜백 함수입니다.

 

3. AI 캐릭터

AI 캐릭터는 간단합니다.

AbilitySystemComponent를 Actor가 가지고 있고 Controller가 Pawn에 Set되어야 한다는 제약도 없습니다.

BeginPlay에서 해주면 됩니다.

 

이제 InitAbilityActorInfo를 해봅시다.

 

Enemy는 BeginPlay에서 하면 됩니다.

Owner와 Avatar는 Actor 자기 자신이므로 this로 등록합니다.

 

PlayerState 상태에서는, 두 곳 (PossessedBy, OnRep_PlayerState) 에서 처리한다고 했습니다.

다음과 같이 작성합니다.

 

 

이 것으로 AbilitySystemComponent가 등록이 완료되었습니다.