Unreal Engine/Gameplay Ability System

[UE] Gameplay Ability System -9- Prediction

KANTAM 2023. 6. 3. 16:12

https://github.com/tranek/GASDocumentation#concepts-ga

 

GitHub - tranek/GASDocumentation: My understanding of Unreal Engine 5's GameplayAbilitySystem plugin with a simple multiplayer s

My understanding of Unreal Engine 5's GameplayAbilitySystem plugin with a simple multiplayer sample project. - GitHub - tranek/GASDocumentation: My understanding of Unreal Engine 5's Gamepl...

github.com

단순히 위의 문서를 보고 제멋대로 해석해서 적은 것입니다. 차라리 위의 문서를 봐주세요. 저 영어 못 합니다.

4.10 Prediction

GAS는 클라이언트 측의 prediction에 대한 지원을 즉시 사용할 수 있다. 그러나 GAS는 모든 것을 predict하지는 않는다. GAS안의 클라이언트 측 prediction은 클라이언트가 어빌리티를 활성화하고 이펙트를 적용하는데 서버의 허가를 기다리지 않아도 된다는 의미이다. 클라이언트 측 prediction은 서버가 줄 허가와 이펙트가 적용될 타겟을 예측할 수 있다. 그런 다음 서버는 클라이언트가 활성화되고 예측이 정확한지 여부를 클라이언트에게 알려준 후 어빌리티 네트워크 대기 시간을 실행한다. 만약 클라이언트가 클라이언트의 prediction이 잘못되었다면, 클라이언트는 서버에 맞게 잘못 된 prediction으로부터 변화를 롤백한다. 

 

GAS와 연관된 prediction의 한정된 소스는 플러그인 소스 코드안의 GameplayPrediction.h안에 있다. 

 

에픽의 마인드셋은 당신이 고칠 수 있는 것에만 predict하는 것이다. 예를 들어, 파라곤과 포트나이트에서는 데미지를 predict하지 않는다. 데부분은 데미지 처리 시 ExecutionCalculations를 사용하며 predict되지 않는다. 이것은 데미지와 같은 것들을 예측할 수 없다는 의미가 아니다. 할 수 있다면 아주 훌륭한 것이다. 

... we are also not all in on a "predict everything: seamlessly and automatically" solution. We still feel player prediction is best kept to a minimum (meaning: predict the minimum amount of stuff you can get away with).
Dave Ratti from Epic's comment from the new Network Prediction Plugin

에측 되는 것:

  • 어빌리티 활성화
  • 트리거된 이벤트
  • 게임플레이 이펙트 어플리케이션:
    • 어트리뷰트 수정 (예외: Executions do not currently predict, only attribute modifiers)
    • 게임플레이 태그 수정
  • 게임플레이 큐  이벤트 (both from within predictive gameplay effect and on their own)
  • 몽타주
  • 무브먼트 (built into UE5 UCharacterMovement)

예측 되지 않는 것:

  • 게임플레이 이펙트 제거
  • 게임플레이 이펙트 periodic effects (dots ticking)

From GameplayPrediction.h

 

게임플레이 이펙트의 적용은 예측할 수 있지만, 게임플레이 이펙트의 삭제는 예측할 수 없다. 이 한계를 극복하기 위한 한가지 방법은 게임플레이 이펙트를 지우고싶을 때, 그 반대의 이펙트를 예측하는 것이다. 이동속도가 40% 느려진다고 예측하자. 우리는 이동속도 40%증거 버프를 통해 예측적으로 지울 수 있다. 그러고 같은 시간에 게임플레이 이펙트를 모두 지운다. 이것은 모든 시나리오에 적절하지는 않으며 게임플레이 이펙트 제거를 예측을 위한 지원은 여전히 필요하다. Dave Ratti from Epic has expressed desire to add it to a future iteration of GAS.

 

게임플레이 이펙트의 제거를 예측할 수 없고 어빌리티의 쿨다운에는 반대되는 게임플레이 이펙트 차선책이 없기에 완전히 예측할 수 없다. 서버의 복제된 쿨다운 이펙트는 여전히 클라이언트에 존재할 것이며 이것을 우회할려는 시도(with Minimal replication mode for example)은 서버에 의해 무시당할 것이다. 이것은 높은 레이턴시를 가진 클라이언트는 서버에게 쿨다운 작업을 계속하도록 지시하는데 시간이 더 걸리고, 서버의 쿨다운 이펙트의 제거 요청를 받는데 시간이 걸리다는 뜻이다. 이것은 높은 레이턴시의 플레이어는 낮은 레이턴시의 플레이어보다 사격 속도가 낮고 불이익이 있다는 것을 의미한다. 포트나이트는 이런 이슈를 피하기위해 커스텀 bookkeeping을 쿨다운 이펙트 대신에 사용한다. 

 

데미지 예측에 관해서, 대부분의 사람들이 GAS를 시작할 때 가장 먼저 시도하는 것 중 하나임에도 불구하고 개인적으로 추천하지 않는다. 특히 죽음을 예측하는 것을 추천하지 않는다. 데미지를 예측할 수 있어도 그렇게 하는건 아주 어렵다. 데미지를 예측하는데 잘못된 예측이 있었다면, 플레이어는 적의 체력이 다시 돌아오는 것을 볼 것이다. 캐릭터의 죽음을 잘못 예측했다면, ragdolling 시작한 다음 서버가 수정할 때, regdolling을 멈추고 당신을 향해서 사격을 시작할 것이다. 

 

Note: 어트리뷰트를 바꾸는 Instant 게임플레이 이펙트(코스트 이펙트처럼)는 자신에게 완벽하게 예측할 수 있다. 다른 캐릭터에 대한 Instant 어트리뷰트의 변화를 예측하는 것은 그들의 어트리뷰트 안에 잠깐의 비정상적인 혹은 일시 변동을 발생시킬 수 있다. 예측된 Instant 이펙트들은 Infinite 이펙트처럼 대해진다. 그러므로 그들은 잘못 예측되었다면 롤백될 수 있다. 서버의 이펙트가 적용되었을 때, 거기에는 짧은 시간동안 2가지의 같은 이펙트가 존재하여 Modifier가 2번 적용되거나 안 될 수도 있다. 그것은 결국에는 혼자서 교정할 것이지만 종종 플레이어에게 blip이 일어날 수 있다.

 

GAS의 예측 구현이 해결하려고 하는 문제:

  1. "Can I do this?" Basic protocol for prediction.
  2. "Undo" How to undo side effects when a prediction fails.
  3. "Redo" How to avoid replaying side effects that we predicted locally but that also get replicated from the server.
  4. "Completeness" How to be sure we /really/ predicted all side effects.
  5. "Dependencies" How to manage dependent prediction and chains of predicted events.
  6. "Override" How to override state predictively that is otherwise replicated/owned by the server.

from GameplayPrediction.h

 

4.10.1 Prediction Key

클라이언트가 어빌리티를 활성화하였을 때, 클라이언트가 생성하는 정수 식별자로써 Prediction Key의 컨셉위에서 GAS의 예측이 이루어진다.

  • 클라이언트가 어빌리티를 활성화하였을 때, 클라이언트는 예측 키를 생성한다. 이 것은 Activation Prediction Key이다.
  • 클라이언트는 이 예측 키를 서버에게 CallServerTryActivateAbility()를 통해 보낸다.
  • 클라이언트는 예측 키가 유효한 동안 적용되는 모든 게임플레이 이펙트에 이 예측 키를 추가한다. 
  • 클라이언트의 예측키는 범위에서 벗어난다. 동일한 어빌리티에서 추가로 예측된 이펙트는 새로운 Scoped Prediction Window가 필요하다.
  • 서버는 클라이언트로부터 예측 키를 받는다. 
  • 서버는 이 예측키가 적용된 모든 게임플레이 이펙트에 이 키를 추가한다. 
  • 서버는 클라이언트에 이 예측키를 클라이언트에 다시 replicate한다.
  • 클라이언트는 서버로부터 replicate된 게임플레이 이펙트를 받고 이펙트를 적용하는데 사용된 예측 키도 받는다. 만약 replicate된 이펙트 중 어떤 것이라도 이펙트와 매치된다면 클라이언트는 같은 에측 키를 적용하고, they were predicted correctly. 클라이너트가 복제된 이펙트를 지우기 전에 일시적으로 2개의 이펙트 복사본이 있을 것이다. 
  • 클라이언트는 서버로부터 예측키를 다시 받는다. 이것은 Replicated Prediction Key이다. 이 예측 키는 이제 오래된 것으로 표시된다.
  • 클라이언트는 모든 현재 오래된 replicated 예측 키와 만들어진 이펙트를 제거한다. 서버로 부터 replicate된 이펙트는 남는다. 클라이언트가 추가한 이펙트와 서버로부터 replicate 버전과 맞지 않은 것을 받지 못한 이펙트는 잘못 예측된 것이다. 

Prediction keys are guaranteed to be valid during an atomic grouping of instructions "window" in GameplayAbilities starting with Activation from the activation prediction key. You can think of this as being only valid during one frame. Any callbacks from latent action AbilityTasks will no longer have a valid prediction key unless the AbilityTask has a built-in Synch Point which generates a new Scoped Prediction Window.

 

4.10.2 Creating New Prediction Windows in Abilities

어빌리티 태스크로부터 콜백 안에 더 많은 액션을 예측하려면, 새로운 Scoped Prediction Key를 통해 새로운 Scoped Prediction Window를 만들어야 한다. 이것은 때때로 클라이언트와 서버 사이의 Synch 포인트라고도 한다. 모든 입력 관련 작업과 같은 일부 어빌리티 태스크에는 새로운 scoped prediction window를 만드는 기능이 내장되어 있다. 즉, 어빌리티 태스크의 콜백의 원자성 코드에는 사용할 유효한 scoped prediction key가 있다. WaitDelay 태스크와 같은 다른 태스크에는 콜백을 위한 새 scoped prediction widnow를 만드는 내장 코드가 있지 않다. 만약 WaitDelay처럼 새로운 socped prediction wodnow를 만드는 내장 코드가 없는 어빌리티 티스크 후에 예측 행동이 필요하다면, 우리는 OnlyServerWait 옵션과 WaitNetSync 어빌리티 태스크를 사용하여 수동적으로 해야한다. 클라이언트가 WaitNetSync에 OnlyServerWait를 입력했을 때, 그것은 어빌리티의 활성화 예측 키를 기반으로 새로운 scoped prediction key를 생성한다. 그리고 서버로 RPC하고, 적용된 새로운 이펙트에게 보낸다. 서버가 WaitNetSync에 OnlyServerWait를 입력했을 때, 계속하기 전에 클라이언트로부터 새로운 scoped prediction key를 받을 때까지 기다린다. 이 새로운 scoped prediction key는 활성화 예측 키와 같은 동작을 한다. 활성화 예측 키는 이펙트로에 적용되고 클라이언트에 다시 복제되어 오래된 것으로 표시된다. scoped prediction key는 범위에서 벗어날 때가지 유효하다. 이는 scoped prediction window가 닫혔음을 의미한다. 다시 말하지만, 원자적 연산만, nothing latent, 새로운 scoped prediction key를 사용 가능하다. 

 

필요한 만큼 scoped prediction window를 만들 수 있다. 

 

만약 당신만의 커스텀 어빌리티 태스크에 synch 포인트 기능을 추가하고 싶다면 인풋이 WaitNetSync AbilityTask 코드를 본질적으로 주입하는 방법을 살펴봐라.

 

Note: WaitNetSync를 사용할 때, 이것은 클라이언트로부터 계속실행하라는 요청을 듣기 전까지 서버의 게임플레이 어빌리티의 실행을 막는다. 이것은 악의가 있는 유저에 의해 게임을 해킹하고 의도적으로 새로운 scoped prediction key를 보내는 것을 딜레이 하여 잠재적으로 오남용될 수 있다. 에픽은 WaitNeySync를 거의 사용하지 않지만, 잠재적으로 새로운 버전의 어빌리티 태스크를 구축하는 것을 추천한다. a new version of the AbilityTask with a delay that automatically continues without the client if this is a concern for you.

 

샘플 프로젝트는 스프린트 어빌리티에서 WaitNetSync를 사용하며 스태미나 코스트를 적용할 때마다 새로운 scoped prediction window를 생성하며 so that 예측이 가능하다. 이상적으로 우리는 코스트와 쿨다운을 적용할 때 유효한 예측 키를 원한다. 

 

자신의 클라이언트에서 2번 플레이되는 예측되는 이펙트를 가지고 있다면, 당신의 예측 키가 오래되어 'redo' 문제가 발생한다. 새로운 scoped prediction key를 생성하는 이펙트를 적용하기 바로 전에 OnlyServerWait와 함께 WaitNetSync 어빌리티 태스크를 넣음으로써 보통 이 문제를 해결할 수 있다. 

 

4.10.3 Predictively Spawning Actors

클라이언트에서 예측적으로 액터를 스폰시키는 것은 고급 주제이다. GAS는 이것을 다룰 수있는 기능을 out of the box로는 제공하지 않는다(the SpawnActor AbilityTask only spawns the Actor to the server). 주된 컨셉은 복제된 액터를 클라이언트와 서버 모두에 스폰하는 것이다. 

 

만약 액터가 단순히 미용적인 요소이거나 게임플레이에 목적으로 제공되는게 아니라면, 간단한 해결책은 액터의 IsNetRelevantFor()을 재정의하여 서버가 본인의 클라이언트에 복제하는 것을 막는다. owning 클라이언트는 로컬로 스폰된 버전을 가지고 있을 것이며 서버와 다른 클라이언트는 서버의 복제된 버전을 갖고 있을 것이다. 

bool APAReplicatedActorExceptOwner::IsNetRelevantFor(const AActor * RealViewer, const AActor * ViewTarget, const FVector & SrcLocation) const
{
	return !IsOwnedBy(ViewTarget);
}

 

피해를 예측해야 하는 발사체처럼 게임플레이에 영향을 미치는 경우, 이 문서 범위 밖에 있는 고급 로직이 필요하다. Look at how UnrealTournament predictively spawns projectiles on Epic Games' GitHub. They have a dummy projectile spawned only on the owning client that synchs up with the server's replicated projectile.

 

4.10.4 Future of Prediction in GAS

GameplayPrediction.h는 향후 게임플레이 이펙트의 제거 예측과 주기적인 이펙트를 위한 기능을 추가할 수 있다고 말한다. 

 

에픽의 Dave Ratti는 latencyreconciliation문제, 쿨다운 예측, 높은 레이턴시의 플레이어의 불이익에 대한 문제를 고치는데 관심을 표했다.

 

에픽의 새로운 Network Prediction 플러그인은 CharacterMovementComponent가 그랬던 것처럼 GAS와 완전히 상호작용될 것으로 예상된다.

 

4.10.5 Network Prediction Plugin

에픽은 최근 CharacterMovementComponent를 새로운 Network Prediction 플로그인으로 교체하는 작업을 시작했다. 이 플러그인은 초기 단계이지만 언리얼 엔진 깃허브에서 얼리 액세스로 사용할 수 있다. 그 실험적인 베타 버전이 어떤 엔진의 미래 버전에서 데뷔할지 말하는 것은 너무 이르다.