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,也就是已经开启网络复制
资料:
有关Network的蓝图资料:
【1】http://api.unrealengine.com/CHN/Gameplay/Networking/Actors/RPCs/index.html
【2】http://api.unrealengine.com/INT/Gameplay/Networking/Blueprints/index.html
UE4官方的 "ContentExample" 里有个关于Network的使用蓝图的示例,强烈推荐看看
有关Network的C++资料:
【1】http://api.unrealengine.com/INT/Gameplay/Networking/Actors/Properties/index.html