Unreal 服务器
UE4基本的设置服务器相关API
AActor的网络设置
Replicates是代表了Actor是否具备网络连接的功能(是否与服务器连接在一起,有网络连接才能进行“同步”和“广播")
C++代码就是
bReplicates = true;UActorComponent的网络设置
Component Replicates代表了一个ActorComponent是否与网络连接一起,不过得注意的一点是:拥有该组件的Actor在连接网络的情况下,该组件的网络设置才有效。
C++代码就是
bReplicates = true;UE4编辑器模拟联网(RunDedicatedServer)
RunDedicatedServer:勾选RunDedicatedServer直接在编辑器运行来模拟联网模式
NumberOfPllayers: 同时开启客户端的数量
如图3个客户端(包括编辑器):
AActor的网络判断API(C++)
在这里我先说明一点,UE4的客户端代码和服务器代码是同一套代码(有点牛),服务器可能缺少了渲染等少数功能。
(1)HasAuthority :判断此时运行的是在客户端还是服务器上
看看源码:
FORCEINLINE_DEBUGGABLE bool AActor::HasAuthority() const { return (Role == ROLE_Authority); }其中Role是Actor上一个宏变量,可以用来判断当前角色处于服务器或者客户端的哪种情况
/** Describes how much control the local machine has over the actor. */ UPROPERTY(Replicated) TEnumAsByte<enum ENetRole> Role;ENetRole宏:
UENUM() enum ENetRole { /** No role at all. */ ROLE_None, /** Locally simulated proxy of this actor. */ ROLE_SimulatedProxy, /** Locally autonomous proxy of this actor. */ ROLE_AutonomousProxy, /** Authoritative control over the actor. */ ROLE_Authority, ROLE_MAX, };当role为
[1]ROLE_None时,根本不存在任意角色
[2]ROLE_SimulatedProxy 网络游戏中别的玩家在本地客户端的一个角色代理
[3]ROLE_AutonomousProxy 网络游戏中自己的玩家在本地客户端的一个角色代理
[4]ROLE_Authority: 网络游戏在服务器上的角色
测试下:
void AMyProjectCharacter::BeginPlay() { Super::BeginPlay(); UWidgetComponent* nameWidgetComponent = this->FindComponentByClass<UWidgetComponent>(); if (nullptr == nameWidgetComponent) return; UUserWidget* nameUserWidget = nameWidgetComponent->GetUserWidgetObject(); if (nullptr == nameUserWidget) return; UTextBlock* textBlock = Cast<UTextBlock>(nameUserWidget->GetWidgetFromName(FName("TextBlock_46"))); if (nullptr == textBlock) return; FString name = "name_none"; if (GetLocalRole() == ENetRole::ROLE_AutonomousProxy) { name = "ROLE_AutonomousProxy"; } else if (GetLocalRole() == ENetRole::ROLE_SimulatedProxy) { name = "ROLE_SimulatedProxy"; } else { } textBlock->SetText(FText::FromString(name)); }
[1]这里对于每个客户端而言,自己的角色就是“ROLE_AutonomousProxy”,其他角色就是“ROLE_SimulatedProxy”
[2]如果你亲自运行上面的代码,你会发现AMyProjectCharacter的BeginPlay总共执行了12次,为什么呢?
原因是:我们有在服务器三个AMyProjectCharacter,而存在三个客户端,每个客户端有三个AMyProjectCharacter,总共就是
3 + 3*3 = 12
如下面图所示:
这幅图很好诠释了上面的关系吧。
UE4的广播和同步
ue4 的Actor和ActorCompoennt和的同步与广播都建立在上面勾选 bRelicated的前提下
函数广播
这里有三种类型,看蓝图自定义事件的Replicates:
【1】NotReplicated: 函数没有网络通知功能
【2】Multicast: 从Server执行,并广播到各个和服务器连接的客户端(在广播范围内)
其中的WithValidation 代表需要验证才能广播,也就是在 “MulticastRPCFunction_Validate”返回 true 的条件下才能广播下发
UFUNCTION(NetMulticast, unreliable, WithValidation) void MulticastRPCFunction(int a);void MulticastRPCFunction_Implementation(int a) { } bool MulticastRPCFunction_Validate(int a) { return true; }【3】Run on owning client :从服务器执行,只在自己的客户端调用运行。
【4】Run on server: 函数在服务器上执行,经常用于客户端向服务器发送数据,在客户端调用服务器函数执行。
(例如,本地客户端按E键拾取一个物品,按E键触发的回调中在调用Server函数)
(又例如,按W键移动,英雄是在本地客户端计算移动相关属性,然后通过Server函数把位移属性从当前的客户端发送到服务器,进行了同步)
UFUNCTION(Server, unreliable, WithValidation) void ServerPickItem(int itemId); void ServerPickItem_Implementation(int itemId) { } bool ServerPickItem_Validate(int itemId) { return true; }
变量同步
变量同步会自动从服务器同步到各个客户端
蓝图实现:
如上面图的变量:NewVar_0
Relication:
【1】None:表示变量不具备同步功能
【2】Replicated: 表示当进入网络裁剪范围内的时候服务器会同步变量到客户端(如果之前就在网络裁剪范围内,则会与连接的客户端相应变量值比较,如果值不一样,同步下去)。
【3】RepNotify: 表示当进入客户端网络裁剪范围内的时候,服务器会同步变量到客户端,并且触发相应的“Notify”函数(如果之前就在网络裁剪范围内, 会与该客户端相应变量值比较,如果值不一样,则触发“Notify”函数), 如下面所示:
“Replicated”可以说是 “RepNotify”的子集功能,当然同步变量可细分为几种情况,如下所示;
C++实现变量同步
不带通知事件的变量同步
UPROPERTY(Replicated) float a; virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;void AMyProject2Character::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const { Super::GetLifetimeReplicatedProps(OutLifetimeProps); DOREPLIFETIME(AMyProject2Character, a); }带通知事件的变量同步
UPROPERTY(ReplicatedUsing = OnRep_NotifyXXX) float a; UFUNCTION() void OnRep_NotifyXXX(); virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;void AMyProject2Character::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const { Super::GetLifetimeReplicatedProps(OutLifetimeProps); DOREPLIFETIME(AMyProject2Character, a); }上面一切的大前提是: bReplicates = true,也就是已经开启网络复制