Hi, I’ve been working on a custom weapon system that works with multiple player rigs; one rig for first person arms that only the player can see and a full-body rig that only other players can see.
The weapons have 3 classes, one called “BP_WeaponBASE_Main” which is in charge of shooting, reloading, etc. Its like the manager, and its the weapon that attaches to the first person arms, so only the owning player can see it. The second Weapon class is called “BP_WeaponBASE_TP”, with TP standing for “Third Person”, as the name implies this one is more cosmetic and only to be seen by other players, it mimics the animations and effects of the main gun. Last but not least is “BP_WeaponBASE_Item” it is a physics actor in the world which is in charge of detecting if it has been interacted with or not.
The weapon item is dragged into the world and when it is interacted with it calls an event in the players BP that spawns 2 actors of classes “BP_WeaponBASE_Main” & “BP_WeaponBASE_TP”, it spawns them and attaches them to their respective skeletons and sockets.
The problem arises when I try to drop the weapons attached to the players skeletons, or more specifically destroy them and spawn an item version of the weapon on the floor below the player.
and I’m not really sure why it isn’t working, my best guess is that its because of UE5’s garbage collection system for destroying actors but idk how to fix it. The effect I want is to spawn a weapon item class in front of the player and then have both the weapon main and third person actors be detached and destroyed. but they aren’t being detached nor destroyed. I’ve put some pictures of the drop weapon code below.
(rep-notify weapon to drop (the de-spawn actor events handled detaching and destroying the actors within the blueprints, I have already tried to destroy the actor without them, they were just a Hail Mary attempt to try something out. pay no mind to them))
I’m interested to see what is happening in the De- Spawn Actor node. I would start with breakpoints in that node and make sure that the variable you are passing is valid. Also setting the variables to null after despawning could cause issues since they are replicated. So they might be set to null on other instances before getting the chance to despawn. You shouldn’t need to set them anyways since it is an object pointer, if the object it is referencing is destroyed then it will automatically be set to null.
As for setting the variables to null, I found it would help logically as you don’t have a weapon equipped anymore. I mostly did that so I wouldn’t get confused, but since it does it by default on destroy ill remove them. one thing to note is that it does destroy them, and executes the code after; the “weapon type equipped” enum is used in the animation blueprints to determine their state machines, an it always changes to unarmed, yet the weapon actors remain.
This looks fine and I assume that break point is getting hit. If that’s the case, then I’m thinking that the guns are actually getting destroyed and something else is happening. Can you confirm that the guns present after this are not BP_WeaponBASE_Item? Also, add this to you gun classes to see if they are actually getting destroyed.
Hey it looks like you’re using rep notify to spawn actors, why not set the actors as replicated and spawn them on the server. That way all players will see the actors spawn and not get state desync issues that might be causing your problem!
Or if the actor is just cosmetic then the rep notify is fine, you then need to make sure the destroy is called for everyone and I wouldn’t set them as replicated in that case.
Hmm. I did some testing and it seems like they aren’t being destroyed… I made a simple print debug where if I press a key it prints the names of the Weapon equipped, the third person weapon, and for good measure any weapons inside the weapon inventory array, and it doesn’t seem like its doing any of it, but that’s weird, because the players animation state gets set to unarmed and that is only called in at the end of all of that…
Ill send a video of exactly what’s happening when playing for additional info
For reference of what I’m doing in the vid:
I show off some of the code to show how the prints work and then I show the only 2 places where the weapon type equipped is set. it is only ever set to unarmed at the end the drop weapon notify…
I pick up the weapon and then print out the 2 weapon classes that are now equipped, I drop the weapon and it displays what one was dropped, but when I re-print the 2 weapon classes it still says they are there. but note that my guy has changed to his unarmed state…
Wow, I’m not sure entirely why but making the player drop them without the server side worked, but there’s now two other issues being that I still have the weapon for other players and I cant equip other weapons, will try doing it on a multicast to see if that works.
The primary weapon (FP) should be replicated. Server spawns and attaches.
The primary weapon class begin play should check proxy (IF Auton or Sim) and locally spawn and attach the TP variant… store a reference to it in the main weapon class.
Server doesn’t need a TP variant.
On drop server detaches and destroys.
On Autons/Sims use the END PLAY event to handle destroying the TP Variant.
What is an “Auton” or a “Sim”? I cant find anything on what they are. I’m not too experienced with UE5’s multiplayer faculties if its to do with that, this is my first project made to learn replication & multiplayer.
Hmm… ok well if you could provide some reference code when you get to your desk next that’d be awesome. Also, you have any documentations I could read over to help inform me on this subject? I cant say I’ve heard of these before so anything helps. for now though I’ve got to log of, I’m UK based so it’s currently 11PM for me.
Thanks.
Instead of writing a function or macro that you execute whenever you need to know the role, you can have a simple function that sets the proxy role on begin play. Then reference the variable or have helper functions.
You can now easily determine the role of a class (pawn, controller) just by referencing the variable and using short chain logic in your code.
For actors attached/owned you can use an interface function to return the owning pawn/controller proxy role. Simply create a interface class and add it to your character… should do one on the controller as well. Then create functions to return the data as needed.
For your particular project you’d then use the switch (proxy role) and have the Client and Sim spawn a local TP variant, attach it etc.
When the server destroys the Authority weapon that command will get replicated down to all clients… Owner and the copies of you on other simulations. You will need to use the End Play event to handle destroying the TP variant. End play executes just before garbage collection.
Note the Bind Event to On End Play in the last pic.
Hey, big thanks for the explanation, but I’m still a bit confused for setting this up in my project, so please allow me to ask a question:
When I’ve established that an actor is of either Server, Client or Sim, what can I do with that information? like how does it change the outcome of destroying an actor in the game. I see that in your 4th code snippet you do 3 “initialise” events based on the actor’s proxy role, what do they do and how are they different to each-other? more on that, how would I destroy an actor differently if it was a server, or a client , or a sim etc…
How come things like run on server and multicast aren’t used here? most of my other code for spawning the weapons and looting armour works just by telling the server what is happening, and if I need to update other clients on what’s happening (e.g. a clothing item being added) ill run it on a multicast through the server. Would that work too?
Sorry if these questions don’t make much sense, I’m not super experienced with UE, let-alone its networking systems as I only really stared using it during the summer.
Replication is handled by the Replication SubSystem. This is data and events from Server → Client. By simply ticking Replicates in the default settings of the actor and having the server spawn said actor it will be replicated when it’s relevant.
The same applies to variables in a class. The class must be set to replicate, then all variables that are set to replicate will do so when they change and are relevant to the given client.
To clarify, Replicated variables only replicate from server down to clients. Changing a value on a variable client-side will not replicate it to the server. Replicated vars are server change only.
Remote Procedure Calls (RPCs) & Multicasts are communication events similar to Interfaces and dispatchers but over the network. While Replication is always Server to Client. RPCs can go both ways. client to server, server to client. Multicasts are always server to client(s) events…including execution on the server itself.
Dedicated server perspective…
Servers do not play audio, render anything, nor have UI etc. Servers are 100% data. No GPU or Audio device.
Looking at the character class itself Simulated proxies have no need for Cameras, interactive elements, code etc. They technically should be stripped down on spawn to increase performance on the client. They’re simple husks that do what the server says. They do not need input for movement or any other character class custom logic. Just the variables the animation class is going to need.
With Controllers (sims don’t get one), clients are the only proxy that has UI, so the servers copy shouldn’t be executing the creation of widgets etc. They don’t have viewports.
Client proxy controllers are the only ones that need to implement IMC for enhanced input. Servers do not use input.
Using a proxy role to determine what each proxy does/has is a performance boost and gives you granular control.
For weapons you do a similar process on Begin play. If the owner is a simulated proxy, then the gun in hand is a husk. There’s no need for heavy logic. It’ll only ever do a muzzle flash, play audio, and a few animations. If using projectiles in a client-fakey setup then it will pool a projectile, but it doesn’t need a lot of code for that. Just an event calling the bullet pool to teleport the bullet to what the server says and let it rip. That data would be sent via multicast → sims only.
Continuing with weapons. Servers code will be a bit different from the clients. Should be using actor components for the weapon firing logic. So you’d have Server AC’s and Client AC’s.
Overall you’re having the server Spawn the main weapon class and attach it to itself. Said class is Replicated.
In the weapons Begin Play you define its role (Server, Client, Sim)… Server Role would go onto adding server components.
Replication subsystem will tell your client to spawn a gun and it will auto attach just as the servers does. It’s role will be client and then add client components.
All other clients will get the replicated main weapon class attached to sims. The weapon will define its role as a Sim and then add its components and spawn the TP variant, attach it etc.
Here you’d have the Sims code make the FP variant mesh Owner Only See and the TP variant Owner No See.
Key here is to have the Sims code set a reference to the TP variant and create a Bind on End Play Event.
When the main weapon eventually gets dropped the Sims copy of the gun now has a way to destroy the TP variant that only exists on its simulation.
No, All game play relevant actions should be handled by the server directly.
You ask the server to do something, it checks if it can and takes action accordingly.
For looting you should be using an interaction system where you interact locally, say to pick up something. If you get a good trace you then RPC the server to interact. If it gets a good trace it then handles looting the item for you. Updates inventory, spawns any replicated items, etc.
Clients do not “Tell” the server to do anything. They “ask” the server to try, IT checks if it can, and then tries.
Multiplayer 101 is never trusting a client for anything.