参考视频:https://www.youtube.com/watch?v=GcZQ2o6LpDI
1.自定义事件的方式实现rpc
run on server
修改角色的最大速度,方框1,让客户端先行,速度直接改变;然后方框2,告知服务器,自己的速度已经改变了。
这里的startxxxx和stopxxxx的replicates为run on server。
这样可以防止客户端行走抖动的问题。
这里的是使用事件的方式,rpc是不能有返回值的,正好自定义事件也没有返回值,利用了这一点。
下面我们自己模拟一个例子:
玩家点击p键,在自己所在的位置位置初生成一个Cube,这个Cube的蓝图如下,这里的Replicates是没有勾选的。
1、Not Replicated的事件
当我们在client1上按p键之后,只有client1上有cube,其他client2和server0上是看不到cube的。
2、Run on Server类型的事件:
我们将事件的类型改为:Run on Server后
我们还是在Client1上点击p键,结果此时cube只在服务器server0上生成了。
这是为啥呢?
虽然我们Client1是调用了服务器上的方法,但是此时Cube的蓝图并未标记为可复制,我们改下试试:
此时可以看到Client1、Client2以及Server0上都生成了Cube了。这是我们想要的结果。
3、Multicast类型的事件
如果将MyCreateCube事件改为Multicast类型之后,在Client1上点击p键,依然在Client2和Server0是看不到Cube的。
而此时我们应该怎么做呢?
创建一个事件CallServerCreateCube,它的类型为Run on Server,然后由它调用MyCreateCube,而MyCreateCube是Multicast类型的,他会在Server,以及所有相关的Client上执行。此时就可以在Client1上按p键,Client2和Server0上看到此Cube了。
4、Run on owing Client这个目前不知道啥意思
是不是选择一组Client进行进行执行,我觉得是这个意思。
一般情况下,由客户端发起调用的rpc,其类型为Run on Server;而Multicast是由服务器发起调用。
下面来看下如何使用C++代码实现:
首先是绑定键盘p事件的响应:
为了简单起见,我们的Cube就不用代码实现,就直接用蓝图序列化的方式:
void CreateCube();
UPROPERTY(EditAnywhere, Category = "Class Types")
TSubclassOf<AActor> CubeClass;
直接序列化我们制作好的Cube蓝图Actor即可。
然后具体实现:
void ADedicatedServerDemoCharacter::CreateCube()
{
UE_LOG(LogTemp, Error, TEXT("CreateCube"));
FVector location = this->GetActorLocation();
FRotator rotator = this->GetActorRotation();
GetWorld()->SpawnActor<AActor>(CubeClass, location, rotator);
}
我们在Client1上,按键盘p,此时其他端是看不到Cube的。
此时咋做呢?
UFUNCTION(Server, Reliable)
void CreateCube();
void CreateCube_Implementation();
具体实现:
void ADedicatedServerDemoCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent)
{
// Set up action bindings
if (UEnhancedInputComponent* EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(PlayerInputComponent))
{
PlayerInputComponent->BindAction("Create", IE_Pressed, this, &ADedicatedServerDemoCharacter::CreateCube);
}
}
void ADedicatedServerDemoCharacter::CreateCube_Implementation()
{
UE_LOG(LogTemp, Error, TEXT("CreateCube_Implementation"));
FVector location = this->GetActorLocation();
FRotator rotator = this->GetActorRotation();
GetWorld()->SpawnActor<AActor>(CubeClass, location, rotator);
}
注意这里键盘绑定的还是CreateCube,而CreateCube_Implementation是其具体的实现。
其中CreateCube被标记为:UFUNCTION(Server, Reliable)
效果如下:
同样的如果是multicast的函数,只能是由server调用。
参考:https://www.youtube.com/watch?v=yuBcDji2b3Q
比说这样:
这里我们添加了一个键盘回调函数,在其中就是调用:Multicast_CreateCube
结果在Client1中按p之后,只有Client1能看到这个Cube,其他两个端:Client2和Server0都看不到;而如果我们在Server0中按键p之后,Client1、Client2和Server0自己都是可以看到这个Cube的。
这也就证实了,Multicast函数只能由服务器调用,客户端可以调用,但是只能在本地生效。
那解决方式如下:
PressKeyP函数中,调用server的rpc,其具体实现中,又调用Multicast_CreateCube,这样就可以了,也就是不论客户端还是服务器,都是统一调用server端的rpc CreateCube_Implementation。
CreateCube_Implementation中又调用Multicast_CreateCube的函数。
还有一种方式:
这里使用:HasAuthority来判断是客户端执行,还是服务端执行。如果是服务端执行,则直接可以调用Multicast函数;如果是客户端执行,则需要调用服务器的rpc才行。