Hello.
I’m making a Multiplayer FPS game and I’ve just started making the part of the Weapons and of the shots.
Having a Client and a Server, this is what happens when both shoot in the game:
Calmly, let’s analyze this together.
Part 1: The Server shoots
The Server shoots the first shot: only the Server can see it. The Server shoots the second shot: now also the Client can see it.
Part 2: The Client shoots
The Client shoots the first shot: only the Server can see it. The Client shoots the second shot: now also the Client can see it.
As you notice, the Client looks a bit retarded (no, not offending him)
I’ve uploaded a video on YouTube that shows better the issue:
As you can see at 1:01, the Server sees the Client’s shots in the correct location!
New information that will probably make easier to find the issue: I am printing a DebugMessage everytime someone shoots.
The DebugMessage contains the X and Y coordinates of the HitResult.
After shooting multiple times both on the Server and on the Client, I notice that the HitResult on the client is always 0!
I think this has something to do with network lag.
When you call that Multicast, the Client hasn’t updated the HitResult variable yet. That’s why it always lags behind 1 shot, and why some people use OnRep_Notify instead of a Multicast, especially if that multicast uses a recently updated variable.
If you don’t want to use OnRep_Notify, you will have to actually pass that HitResult through the Multicast, instead of it being a replicated variable.
I’m mainly a Blueprints guy but if I had to guess what that would look like in C++ it would be this:
In the OnRep_HitResult function, do the DrawDebugPoint. The function will only be called when the variable is updated. And this way, the client should know what the updated hit result is before it tries to draw the point.
Oh, according to https://wiki.unrealengine.com/Replication#UPROPERTY_Replication_Rule, the OnRep doesn’t get called on the server. So you will have to have the server call it’s own DrawDebugPoint in your StartFire function. Make sure only the server calls the DrawDebugPoint in your StartFire function so the Client doesn’t draw two points.
Yeah, I’d also consider myself a noob at UE networking. I’m almost considering switching over to Photon and getting out of UE’s built-in networking, because I would at least have a more available customer support.
I do this consistently whenever I change a replicated variable on the server: change the value and call OnRep manually. Its most convenient when you have logic that has to be run on both server and client.
I have a Crosshair in my game, and I want every shot to go there (at the center of the screen). In fact, if you see the screenshots below, this doesn’t happen
void AWeapon::OnRep_HitResult()
{
// Storing the Location and Rotation of the Character
FRotator PlayerRotation = MyOwner->GetControlRotation();
FVector RotXVector = PlayerRotation.Vector();
// START PLUG 77 is the Camera's Z value)
FVector StartPlug = FVector(MyOwner->GetActorLocation().X, MyOwner->GetActorLocation().Y, MyOwner->GetActorLocation().Z + 77);
// END PLUG
int32 distance = 2500; // Maximum distance of the trace
FVector EndPlug = (RotXVector * distance) + StartPlug;
// Draws the red debug line
DrawDebugLine(GetWorld(), StartPlug, EndPlug, FColor(255, 0, 0), true, -1, 0, 0.7f);
}
where MyOwner is simply the Actor Owner of the Weapon, which is Replicated using RepNotify
Instead of doing the raycast from MyOwner (the pawn), you can do it from your Follow Camera. The follow camera should be a component of MyOwner, so I think you can just change it all your MyOwner references to MyOwner->FollowCamera. I’m not sure if that is the right syntax since I don’t code much in C++ (I’m more of a C# guy since I use that at work).
I did as you suggested: start the raycast from the camera. This is the code
// Storing the Location and Rotation of the Character
FRotator PlayerRotation = MyOwner->MainCamera->GetComponentRotation();
FVector RotXVector = PlayerRotation.Vector();
// START PLUG - HERE I GET THE PLAYER'S CAMERA!
FVector StartPlug = FVector(MyOwner->MainCamera->GetComponentLocation().X,
MyOwner->MainCamera->GetComponentLocation().Y,
MyOwner->MainCamera->GetComponentLocation().Z);
// END PLUG
int32 distance = 2500; // Maximum distance of the trace
FVector EndPlug = (RotXVector * distance) + StartPlug;
// Draws the red debug line
DrawDebugLine(GetWorld(), StartPlug, EndPlug, FColor(255, 0, 0), true, -1, 0, 0.7f);
The problem is that both the client and server see their own RayCast well, but not the other ones:
The Server here sees the client that shot a RayCast in front of him (not even in front of him, since the RayCast seems to start form the EAR of the character!)
Instead, the Character didn’t shot there, he shot on the ground.
It’s like the camera positition/rotation are not replicated.
By the way, all I want to do is to address the shot to the Crosshair (center of the screen) wherever the shot come from (Weapon Socket, etc…)
Oh it doesn’t matter, I satisfied even with a theoretical explanation =)
Yeah sorry I know more about 3rd person than 1st person.
If you want to do the cast from your weapon to the center of your screen, the start would be from MyOwner then I guess. But then end would be the follow camera World Transform plus the distance you want to go.
As an example here is my raycast that just does 10000 units in front of the 3rd person camera (it is also in Blueprints):
I kind of used the LineTrace detailed out on this page, except I don’t use the Find Look At Rotation and those other transforms. But I think those would be useful to you if you wanted to figure out the transform from your weapon.
Okay, that helped, but there seems to be a replication problem.
**
Both client and server can see their OWN RayCast well.
But they can’t see well the other’s RayCast**
I shoot at the ground with the Server, but the Client sees the Server shooting in front of him
Of course both the Client and the Server can see the RayCast. In the picture above, the Server shoots on the ground and the Client sees Server’s raycast as If he shot in front of him.
So it’s a problem of location/position/direction of the Camera.
Note that this happens for both the players. So it’s not a problem of the Client himself. Also the Server sees Client’s RayCast badly.