参考视频: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才行。
 

















![[极客大挑战 2019]Buy Flag1(BUUCTF)](https://img-blog.csdnimg.cn/e4c32cee534e4932816d3ba0912fcc53.png)

