I have 2 players standing next to each other. The relevency distance (net cull distance) is default which is about 150m. Player 1 fires a projectile at a target 500m away. They both see the explosion. Player 2 now runs and stands next to the target. Player 1 fires and player 2 sees no sign of the projectile. Even though the documentation says… “or the Pawn is the Instigator of some action like noise or damage, it is relevant” and my projectile is a pawn and I set the always relevent check box.
The only way I get this to work correctly is to increase the players net cull distance to > 500m. I dont want to do this because in most cases the players dont need to be relevent to each other at such a distance.
Is there any other way to make this work correctly. Is it a bug that the projectile is not relevent even though it is instigating noise and damage and set to aways relevent?
Not a multiplayer expert here, but i heard it before. Someone knowledgebale correct me - but as i get it: If that player is not relevant then his projectiles (and their actions) are also not relevant. In a shooting game where the projectile travels a long distance this is a problem, but try to imagine if it was not a projectile but a bottle of whiskey he drinks and burps, then it would not be relevant. The game just doesn’t make a differene i think. Problem here is that the projectile belongs to an irrelevant actor. AT least from my understanding that’s the problem. Kinda parent child problem.
Thanks for response.
In my case the projectile is an actor that gets spawned. So even though it belongs to the player it is also an actor. So I would have thought making it “Always Relevent” should have allowed everyone to see it. Also the doc say that if an actor is making sound or causing damage it is relevent. Seems to be broken…?
I take it you use a multicast event to spawn the projectile? If yes that there is your answer. Multicast events are not fired on a player that is not within relevancy distance. When the player suddenly moves within the relevancy distance the multicast has already fired and will not fire again, so basically the player that was outside of the netcull distance has missed the event.
If you want the multicast event to always fire on each player you have to set the player actors to “always relevant”. Now it really depends on what type of game you are creating, but in a large open world game this is a bad idea of course. But if you are creating a smaller arena type game it’s fine to leave the players to always relevant.
An other way to spawn a projectile is to use an RPC (run on server) event which spawns a projectile on the server, then just set the projectile to replicate and it should work.
The best way is still to use a multicast and spawn fake projectile on the clients and the real projectile on the server.
The way we do it in our game is by spawning a projectile using an RPC event, then once spawned within the projectile we use a multicast event to spawn fake projectile on all clients, save a reference and then turn of replication of the projectile actor as it travels on the server. When the server projectile hits something we turn on replication again, use a multicast event to access the references of all the fake projectile and remove them. This saves us a lot of bandwith and makes for very accurate client / server projectiles as all the projectile travel at exactly the same conditions.
Thanks for the detailed answer - I will experiment a bit with this.
The way I did it was to spawn the projectile on the player PC and then got the server to call a multicast event on all the other players so that they would see it.
The projectile is an actor so I thought that if I make it always relevent then it should be so but it apears to get the relevency of the actor that spawned it.
If the projectile has the “always relevant” setting to true, then it will always spawn when the server spawns it, not when a client spawns it. The client can spawn things but they are not replicated to the server nor other clients. This is how a fake projectile works, it’s a clientside only version of the projectile purely for cosmetic reasons. The server spawns the real projectile, the one which does all the collision calculating and stuff it needs to do should it hit a player.
Doing it this way what happens when a player has lag? He fires projectile but only sees it fire when the server sends the multicast out?
The projectile has a starting point (vector3), a direction (also a vector3) and a travel speed (float). All these variables are use to spawn the projectile, whether it’s spawned on the server or using a multicast to spawn them on the clients (fake ones) they all use the exact same variables so their trajectory can never be different, the only thing that can happen is that due to lag a client’s projectile might appear to be behind / slower than the server’s projectile. To fix this you could force a reposition from the original server projectile every 1 second.
Thanks for the advice. I figured out a different way to do this but on closer investigation I think that the way you are doing it will result in the least data being sent on the network
Hi
So I implemented your method of doing this but have a small problem. When I turn off replication on the server, the projectile that was created on the clients while replication was turned on is still visible on the clients. Now when the fake projectile makes a turn you can see the ‘replicated’ projectile which is now orphaned carries on straight. Do you make that one invisible before turning off replication?
Yup, I forgot to mention that but yes you have to turn off the visibility and collision on the clients as well.
Yes I noticed - thanks
@WixZ
I have implemented as per your suggestion and all works well… but if the server projectile collides with something that the client did not, I have not managed to work out how to destroy the client projectile. You mentioned you save a reference to it. Could you perhaps explain how you did that?
Hey. Yes, that’s right. You have to save a reference of each “fake projectile” on the server projectile. You do this by creating an array variable of the type of projectile. Then when you spawn the fake ones, put a reference of each one inside the array (use add). Now the array should contain all the references of all the fake projectiles created. All you have to do then is when the server projectile hits something, use the array of fake projectile references and loop through it with a for each loop. Inside the for each loop you destroy each fake projectile. When the for each loop is completed you destroy the server projectile.
Thanks - I will try that. I have an extra complexity. When my player fires the missile he creates a fake one which runs on the client. This one is not created from the server. I do this just in case there is a lag between the player and server. I will also need to create a reference to this one. Do you also do this?
What puzzles me is how does the server projectile get a reference to the projectiles that are spawned on clients as a result of a multicast?
If you are using a multicast it’s pretty simple really. All you have to do is save the reference after the multicast. This will save the reference on the particular casted user’s version of the projectile. When you want to acces it again, you use another multicast and get the reference of the casted user’s version, which will allow you acces to said reference after which you can do whatever you want with it, such as delete it.
So basically use a multicast to spawn the fake ones, inside you multicast logic you save a reference of the casted player’s fake projectile. Then later on when you want to destroy the projectiles, you use another multicast and loop through the references you saved from the spawn multicast and check if you get any valid ones, if you do, use the found valid reference and delete it.
Thanks - I have finally got it all to work.
You are very welcome.