unreal actor role & remote role c++
RPC를 사용하거나 Replicated와 같은 공유변수로 선언할 경우에는 롤(Role)을 기억해야 한다.
Role은 총 3가지가 있다.
Authority,
AutonomousProxy,
SimulatedProxy
이런식이며 아래 그림을 통행 무슨 뜻인지 링크를 통해 이해할 수 있을 것이다.
위 그림은 Server Client에서 디버그 띄우는 모습이다. 각 빙의된 캐릭터의 이름위에 Authority라는 로그는 서버의 입장에서는 두 객체 모두 서버 소유의 객체라는걸 알 수 있다(Authority가 권위, 권력이라는 명사이기때문에 알 수 있다).
위 그림은 해당 Client(Client1이라 쓰여져 있다.)에서 보면 내가 동작하는 빙의된 캐릭터에는 AutonomousProxy라고 적혀 있으며 이것은 해당 클라이언트에게 할당된 자리인거다. 하지만 반대로 다른 캐릭터에는 SimulatedProxy라고 적혀 있는데 이것은 뜻에서 알 수 있듯이 다른 Client에서 조종하고 그 값을 다른 Client들에게 전달하여 전달받은 값만큼 움직이는 것이다.
SimulatedProxy가 달라지는 모습은 해당 게시물의 영상에서 잘 나타나 있다.
https://codakcoo.tistory.com/21
Unreal RPC c++ 기초2
먼저, 자신의 함수의 생성에서 기본으로 들어가면 만약 자신의 AnimMontage를 실행하는 Server매크로 함수를 생성하고 싶을떄 다음과 같이 설정하면 된다. .h UFUNCTION(Server, Reliable, WithValidation) void Serve
codakcoo.tistory.com
액터 롤 및 리모트 롤
액터 오브젝트 리플리케이션의 여러가지 부분에 대한 것입니다.
docs.unrealengine.com
Authority | 서버 소유 객체. |
AutonomousProxy | 클라이언트에게 할당된 빙의된 객체 |
SimulatedProxy | 클라이언트에게 빙의된 객체 의외에 다른 클라이언트들에게 빙의된 객체들에게 값을 받아 내 클라이언트에게 움직이는 객체. |
하지만, 이게 왜 중요할까라고 생각할 수도 있지만 매우 중요한 조건이다. 그 다음 예시가 그렇다.
위 그림과 같이 3개의 클라이언트가 있다고 가정해보겠다(server포함).
Client1에서 입력을 하여 RPC를 통해 Server->Multicast를 실행하면 아마 다음과 같이 전달 될것이다.
만약 해당 호출 함수가 AnimationMontage 실행 함수여서 Notify를 실행시키면 다음과 같이 실행 될것이다.
Notify에서 함수를 실행하여 ApplyDamage나 PointDamage함수 등을 실행하면 호출은 어떻게 되는걸까?라고 생각하면 다음과 같이 실행된다. RPC와 같은 기능을 안쓰고 개별함수로 호출하면 다음과 같은 일이 발생한다.
Notify가 AuthonomousProxy에서만 실행되는게 아니라 Authority(권위)에서도 실행되며 호출이 두번씩 발생하는 오류가 생겨버린다. 만약 이런상황이 생기면 뒤따르는 오류는 아마 Replicated변수일 것이다(Replicated변수는 Server에서 변환하지 않을 경우 값이 달라진다). 아니면 호출이 2번 실행되는거기 때문에 변수의 값이 두번 참조될 수도 있는거다. 서론이 길어졌으니 본론으로 빠지면 필요한 방법은 다음과 같다.
.h
UFUNCTION()
void WeaponTrace();
UFUNCTION(Server, Reliable)
void Server_WeaponTrace();
UFUNCTION과 UFUNCTION(Server, Reliable) 두가지 함수를 생성해준다(이 방식까지는 Replicated 변수를 변경할때와 같다).
.cpp
void UCombatComponent::WeaponTrace()
{
ACharacterBase* CO = Cast<ACharacterBase>(GetOwner());
if(!CO) return;
if (CO->GetLocalRole() == ROLE_Authority) // 소유자가 Authority면 통과.
{
/*************코드***************/
}
else // Authority가 아닌 다른 소유.
{
Server_WeaponTrace(HandType, StartSocket, EndSocket);
}
}
void UCombatComponent::Server_WeaponTrace_Implementation()
{
WeaponTrace(HandType, StartSocket, EndSocket);
}
위같은 코드는 ActorComponent이기 때문에 GetLocalRole()을 이용하여 해당 값이 Role_Authority인지 파악한다. 근데 여기서 GetLocalRole()과 GetRemoteRole() 총 두가지 호출방법이 있지만 이 두가지는 완전히 다른 변수이다.
/** Returns how much control the local machine has over this actor. */
UFUNCTION(BlueprintCallable, Category=Replication)
ENetRole GetLocalRole() const { return Role; }
/** Returns how much control the remote machine has over this actor. */
UFUNCTION(BlueprintCallable, Category=Replication)
ENetRole GetRemoteRole() const;
FORCEINLINE_DEBUGGABLE ENetRole AActor::GetRemoteRole() const
{
return RemoteRole;
}
위 코드와 같이 Role변수와 RemoteRole이라는 두 가지 변수가 존재한다.
Role: Role_Authority인지 확인한다.
RemoteRole: Role_AutonomousProxy또는 Role_SimulateProxy인지 파악하는 용도이다.
■하지만 Role을 확인하는 것도 RPC : Server Function으로 호출하면 Server안에서 호출하는거기때문에 Client1에서 함수를 호출하였다해도 Server Function안에서는 해당객체를 AutonomousProxy로 인식하는게 아니라 Authority로 인식한다. 그렇기에 GetLocalRole()이나 GetRemoteRole()를 사용하기 위해서는 Server Function에서 호출보다는 UFUNCTION() 또는 UFUNCTION(Client, Reliable)같은 함수에서 호출해야 인식이 가능하다.
아래 영상에서 차이를 보고 이만 마치겠다.
https://www.youtube.com/watch?v=RrUQGg2Fq3w