UE4网络基础

12 篇文章 2 订阅

UE4 NetWorking

Actor’s Role

​ 参与网络复制的actor在replicates过程中主要扮演两种重要的角色,RoleRemoteRoleRemoteRole代表了该actor的对应端(即Server对应Client,Client对应Server)。

这两个属性可以告诉你:

  • 谁有这个actor的主控权(Authority)
  • 这个actor是否参与replicated
  • 复制模式

同时Role的属性还可以分化为:

  • ROLE_Authority
  • ROLE_SimulatedProxy
  • ROLE_AutonomousProxy

其中Role属性是ROLE_Authority,就表明这个运行中的实例掌管此actor(决定其是否被复制)。

RoleROLE_Authority,RemoteRoleROLE_SimulatedProxyROLE_AutonomousProxy,就说明这个引擎实例负责将此actor复制到远程连接。

目前只有服务器能向已连接的客户端同步Actor(客户端永远不能向服务器同步)。只有服务器才能看见actor的Role

在这里插入图片描述

​ 服务器不会在每次更新时复制actor,这会消耗大量带宽和CPU资源,实际上服务器会按照AActor::NetUpdateFrequency属性所指的频度来复制actor。所以在actor的更新间隙中,会有一些数据被传递到客户端。这会导致actor呈现断续不连贯的动作。为了弥补这个缺陷,客户端将在更新的间隙中模拟actor。模拟分为如下两种网络同步方式:

  • ROLE_SimulatedProxy

这是标准的模拟途径,通常是上次获得的速率对移动进行推算。服务器为特定的actor发送更新时,客户端将向这新的方位调整其位置,然后利用更新的间隙,根据由服务器发送的最近的速率值来继续移动actor。这个角色表示他是一个远程机器上的一个复制器,没有权利来改变一个对象的状态,也不能调用RPC。

  • ROLE_AutonomusProxy

这种模拟通常只用于PlayerController所拥有的actor。说明此actor会接收玩家控制的输入,所以在进行推算时,我们会有更多一些的信息,而且能使用真人输入内容来补足缺失的信息。可以通过RPC来改变actor的状态。

Actor’s Owningship

​ Actor的Own指的其实是一个连接的实例或PlayerController。每个连接实例会Own一个PlayerController。决定一个actor是否被Owning,就是向上查询它的Ownership结构树,找到最上层的拥有者,如果是PlayerController

则它就被这个PlayerController以及它的连接所拥有。

例如:

  • 一个Pawn被一个PlayerController Possess的时候它就Owned,UnPosses时,OwningShip就丢失了。

如果需要设置某个actor的OwningShip,我们可以通过函数SetOwner()让它被某个PlayerController拥有。

OwningShip的重要性:

  • RPC需要确定哪个客户端将执行运行于客户端的RPC
  • Actor复制与连接的相关性(Relevancy)
  • 在涉及Owner时的Actor属性的复制条件

在这里插入图片描述

Actor‘s Replicates

​ Actor是实现replicate的主要推动者。Server将保留一份Actor列表并定期更新Client,Client保留Server中每个actor的近似副本。

​ Actor主要通过两种方式进行更新:

  • 属性更新(发生变化时随时更新)
  • RPC(Remote Process Calls)(在被执行时调用)

Component’s Replicates

​ 组件replicates中涉及两大类,一种是静态类组件,另一种是动态类。

  • 静态类通常是组件所属actor的身上的静态组件,一般是staticmesh、particle等。这些组件在actor生成在server和client上时,也会同时生成,与组件本身是否为replicates无关。

  • 动态类组件是在服务器上生成的组件种,也就是我们熟知的component,其创建和删除会复制到client。它们运行的方式和actor类似,即需要通过replicates的方式存在于client。

要进行组件的replicate,只需要设置他的SetIsReplicated(true)函数就行,如果这个组件是某个actor的子对象。就应该在其actor的构造函数中设置该属性。

ACharacter::ACharacter(){
	CharacterMovementComponent = CreateDefaultSubobject<UMovementComp_Character>(TEXT("CharacterMovementComponent"));
    if(CharacterMovementComponent){
        //...
        CharacterMovementComponent->SetIsReplicated(true);
    }
}

Replicating actor

Blueprint设置:
在这里插入图片描述

设置Replicates属性为true。

C++设置:

Actor构造函数中SetIsReplicated(true)

Replicating properties

​ 与actor一样,变量也能进行replicates。游戏逻辑中的关键变量只能在server上进行修改(血量、经验值、弹药等)防止玩家作弊。

​ 变量的replicates方法有两种。一种是Replicates,另一种是Rep_NotifyRep_Notify拥有Replicates的所有功能,同时它还有一个回调函数,每当函数关联的变量更新时,该函数会调用并在server和client上运行。

Blueprint中的设置:

  • Replicates
    在这里插入图片描述

C++中的设置:

​ C++中设置属性为Replicates需要注意的是,拥有这个属性的actor需要设置为Replicates。

并且在宏中设置这个属性的Replicated关键字:

UPROPERTY(Replicated)
float CurHealth;

其次需要重载:

#include"Net/UnrealNetWork.h"
void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override

​ 这个函数负责于任何需要被复制的属性,允许我们定义这个属性将会如何有条件的被复制。

在CPP文件中需要添加所有我们需要被复制的属性:

void AAttachComponent::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
	Super::GetLifetimeReplicatedProps(OutLifetimeProps);
	
	DOREPLIFETIME(AAttachComponent,CurHealth);
	// ... other properties
}

关于如何有条件的复制属性可以查看官方文档Conditional Property Replication | Unreal Engine Documentation

  • Rep_Notify

蓝图中设定一个变量为Rep_Notify
在这里插入图片描述

随后可以看见自动创建的OnRep_Deactivate函数
在这里插入图片描述

随后在该函数中添加,当关联的变量进行更行时,你需要的执行的逻辑。

​ 随后在游戏逻辑处修改该变量。你会发现server和client上该变量的变化以及OnRep_Deactivate函数的执行。

C++中的设置:

​ UPROPERTY宏中添加ReplicatedUsing关键字,填上对应的回调函数(需要用UFUNCTION修饰)名字。

UPROPERTY(ReplicatedUsing = OnRep_DeactivatedTimer)
bool bDeactivate;

UFUNCTION()
void OnRep_DeactivatedTimer();

其次同样需要在GetLifetimeReplicatedProps函数中添加这个属性。

RPC

RPC(remote process calls)远程过程调用,类似于函数调用,不过不一定是在本地执行。即:

  • 客户端调用服务端执行
  • 服务端调用客户端执行

​ RPC函数用于client和server在连接的情况下的信息交换。最主要的作用是执行一些不可靠的暂时性/修饰性的gameplay事件。包括了播放音效、生成粒子或产生其他临时效果之类的事件,它们对于actor的正常运作并不重要。在此之前,这些类型的事件往往要通过actor属性进行复制。

​ 同时我们还需要了解actor‘s owningship,因为它决定了大多数RPC在哪运行。

需要注意RPC函数不可以有返回值,默认是"不可靠得",但可以使用Reliable关键字使其可靠。

对于RPC函数,一共有三种,分别是Server,Client,Multicast

  • Server:客户端调用,运行在服务器
  • Client:服务器调用,运行在客户端
  • Multicast:服务器调用,会通知其与其服务器所有相连接的客户端。客户端调用只会执行在本地。

所有客户端和服务端都同时拥有一个actor的实例,服务器的ROLE为ROLE_Authority,而客户端有两种一种为ROLE_SimulatedProxy,这种角色只能接收服务器给它的同步信息,而不能像服务器发送信息。而ROLE_AutonomusProxy即可以接收服务器给它的同步信息,还可以调用Server函数,让服务器执行自己的预设的逻辑。

RPC注意事项:
- 它们必须从Actor上调用
- Actor必须被复制
- 如果RPC是从服务器调用执行在客户端,则只有实际拥有这个Actor的客户端才会执行函数
- 如果RPC是从客户端调用执行在服务器,客户端就必须拥有调用RPC的Actor
- 多播RPC
  - 如果它从服务器调用,服务器将在本地和所有已连接的客户端上执行
  - 如果它从客户端调用,则只能在本地而非服务器上执行

RPC 函数的声明

UFUNCTION(Server)
void ServerRPCFunction();

UFUNCTION(Client)
void ClientRPCFunction();

UFUNCTION(NetMulticast)
void MulticastRPCFunction();

​ 添加关键字Reliable/Unreliable使其变为可信/不可信函数,可信意味着一定会执行成功,但并不是每个RPC函数都适合声明为Reliable,如果Reliable函数过多可能会影响带宽。

// .h
UFUNCTION(Client,Reliable)
void ClientRPCFunction();
// .cpp
void ClientRPCFunction_Implementation();

​ 添加WithValidation关键字可以检测变量是否为合理的,从而控制Client、Server的连接。

UFUNCTION(Server,WithValidation)
void SomeRPCFunction(int32 AddHealth);

需要实现_Validate函数:

void SomeRPCFunction_Validate(int32 AddHealth){
	if(AddHealth>MAX_ADD_HEALTH){
        return false;	// 会断开调用者的链接
    }
    return true;		// 应用此次调用
}

void SomeRPCFunction_Implementation(int32 AddHealth){
	Health += AddHealth;
}

RPC Invoked from a server

Actor ownershipNot replicatedNetMulticastServerClient
Client-owned actorRuns on serverRuns on server and all clientsRuns on serverRuns on actor’s owning client
Server-owned actorRuns on serverRuns on server and all clientsRuns on serverRuns on server
Unowned actorRuns on serverRuns on server and all clientsRuns on serverRuns on serve

RPC Invoked from a client

Actor ownershipNot replicatedNetMulticastServerClient
Owned by invoking clientRuns on invoking clientRuns on invoking clientRuns on serverRuns on invoking client
Owned by a different clientRuns on invoking clientRuns on invoking clientDroppedRuns on invoking client
Server-owned actorRuns on invoking clientRuns on invoking clientDroppedRuns on invoking client
Unowned actorRuns on invoking clientRuns on invoking clientDroppedRuns on invoking client
  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值