[UE4] RPC and OnRep in the development of online games (2)

What are the issues left from the previous article?

As mentioned at the end of the previous article, in order to prevent the Server from calling Server RPC, we use !HasAuthority() / !GetWorld()->IsServer() / GetLocalRole() <ROLE_Authority to ensure that Server_OnFire() is only called on the Client and then through RPC Passed to Server for execution.

And we do not have two projectiles each time the Client fires (one is Spawn in OnFire(), the other is called by Server RPC, Server_OnFire() is executed on the Server side, and the Server side will pass the original Copy the checked Replicates back to Client), delete Spawn in On_Fire(), delete Spawn in On_Fire() instead of canceling Replicates because we want to keep the transfer from Server to Client, which is too convoluted. Let's see what happened to the two projectiles that appeared in the Client.
Insert picture description here
After deleting the Spawn in On_Fire(), it is like this: In
Insert picture description here
this way, Fire once in the Client, and one projectile in both the Client and the Server, which is no problem from the perspective of Client operation.

But when we directly Fire in the Server, since the Spawn in On_Fire() has been deleted, the Server will not spawn a projectile (that is, the gun will not fire bullets).
Insert picture description here
Source: Mobile Games http://www.lyouxi.com/Mobile Games

In addition to this problem, it is also necessary to consider how to forward the information that is passed from Client A to Server and needs to be forwarded to other Clients when there are multiple Clients.

Multicast

There are many ways to solve the problem. Multicast RPC is used here, and the Replicates are unchecked. Instead, we let the information sent from the Server be completed in the form of Multicast RPC.

In order to assist understanding, before detailing the details of each part, first put the diagram of the entire process, the process is carried out in numerical order:
Insert picture description here
Source: Mobile Games http://www.lyouxi.com/Mobile Games

Add the Multicast RPC statement in the role header file, similar to Server RPC:

UFUNCTION(NetMulticast, Reliable, WithValidation)
void Multi_OnFire(FVector Location, FRotator Rotation);
bool Multi_OnFire_Validate(FVector Location, FRotator Rotation);
void Multi_OnFire_Implementation(FVector Location, FRotator Rotation);

We overturned the previous article (deleting Spawn in OnFire()) and changed our thinking: the generation of projectiles, sound effects, and shooting animations are still placed in OnFire(), so that first of all, it is ensured that no matter the current location is Client It is also a server, and the current window can produce projectiles, sound effects, and shooting animations when shooting. Then think of ways to prevent multicasting from causing repeated production of projectiles, sound effects, and shooting animations.

Put a projectile, sound effect, and gun animation generation logic in OnFire(), and add a judgment: if the current location is the Server side, call Multicast RPC:

void MultiplayerCharacter::OnFire()
{
    
    
    // 投射物、音效、开枪动画的生成仍放在OnFire()中
    // 生成音效
    // ...
    // 生成动画
    // ...
    // 生成投射物
    FActorSpawnParameters ActorSpawnParams;
    ActorSpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButDontSpawnIfColliding;
    GetWorld()->SpawnActor<AMultiplayerProjectile>(ProjectileClass, Location, Rotation, ActorSpawnParams);
    // 原本只有这部分判断,为 Client 端则调用 Server_OnFire
    if(!HasAuthority())
    {
    
    
        Server_OnFire(SpawnLocation, SpawnRotation); 
    }
    // 添加判断,如果当前执行 OnFire() 的位置是Server,调用 Multi_OnFire()
    else
    {
    
    
        // Server 端开火要多播到各个 Client
        Multi_OnFire(SpawnLocation, SpawnRotation);
    }
}

We want to distribute the information from Client to Server to each Client, so Multi_OnFire() is called in Server_OnFire_Implementation():

void MultiplayerCharacter::Server_OnFire_Implementation(FVector Location, FRotator Rotation)
{
    
    
    // 某个 Client 同步到 Server 的信息也要从 Server 多播到各个 Client
    Multi_OnFire(Location, Rotation)}

So far, has it been discovered that regardless of whether the Fire location is on the Client or Server, animations, sound effects and bullets will be generated at that location, and then Multi_OnFire() will be executed on the Server.

So what needs to be done later is to multicast to each location, except that Shooter itself no longer generates animation, sound effects, and bullets, and generates a copy for other locations.

Preventing multicasting from causing repeated generation of projectiles, sound effects, and shooting animations is here: put the logic of firing bullets, generating gun recoil animations, and shooting sound effects into Multi_OnFire_Implementation() ; but! Multicast is for each of N Clients and Servers. The individual doing RPC Call does not need to generate a projectile, sound effects, and shooting animation. Here, if(!IsLocallyController()) is used for judgment (IsLocallyController() Is used to determine whether you are the current Shooter):

void MultiplayerCharacter::Multi_OnFire_Implementation(FVector Location, FRotator Rotation)
{
    
    
    if(!IsLocallyControlled())
    {
    
    
        // 产生音效
        // ...
        // 产生动画
        // ...
        // 产生投射物
        FActorSpawnParameters ActorSpawnParams;
        ActorSpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButDontSpawnIfColliding;
        GetWorld()->SpawnActor<AMultiplayerProjectile>(ProjectileClass, Location, Rotation, ActorSpawnParams);
    }
}

Guess you like

Origin blog.csdn.net/weixin_52308504/article/details/112991643
Recommended