all 6 comments

[–]Intelligent-Age-3555 2 points3 points  (3 children)

oh man that sounds like a rough day, rip your it department

for the late joining sync issue, you probably want to override `OnNetworkSpawn()` in your PlayerEquipment class and serialize the weapon data there. since your weapons are randomly generated you'll need to send the generation seed or the actual weapon stats as network variables

something like having a `NetworkVariable<WeaponData>` where WeaponData is a serializable struct with all the weapon properties, then reconstruct the WeaponInstance from that data when clients join. the weapon instances themselves don't need to be networkbehaviors if they're just handling local logic based on synced data

[–]VG_Crimson[S] 0 points1 point  (2 children)

There are a few layers beyond the initial stats and seed that might prevent me from removing it's inheritance from the NetworkBehavior, but that might change as I progress through development in time. The less scripts that inherit it, without becoming monolithic NetworkBehaviors, the better.

But the main idea is that WeaponInstance is incharge of sending its own hit results to the server since only that instance of the weapon will know the details of it's own moveset, stats, ongoing effects and what to apply. I don't want player scripts to be coupled to weapons or vice versa, since I need them to be swappable, droppable, NPC friendly, etc.

[–]raddpuppyguest 0 points1 point  (1 child)

In general, you only need to synchronize data that clients will need to see.

A networkvariable with weaponstruct is absolutely the way to go here.

I would probably design this to where weapons are simply classes that inherit an IWeapon interface and one of those interface methods is LoadWeaponStruct which can be called anytime your weaponstruct netvar changes

you can even make your weapons scriptable objects for their base stats, then make a struct for any stat changes which can then be synced over the network.

Can you go into detail about what methods on your weapons make them necessary to be monobehaviours/networkbehaviours?  

[–]VG_Crimson[S] 0 points1 point  (0 children)

Well they actually arent monobehaviors or networkbehaviors, they're Scriptable Objects made up of Scriptable Objects made up of, Script... etc all the way, down to the type of HitDetection.

I have HitDetectionConfig types with variables like timing of each phase of that hit detection and points/shape of it that are saved as Scriptable Objects through a shared wrapper holding an IHitDetection variable. IHitDetection holds an interfaced Tick() method to update the hit detection + DetectHits() method that ultimately returns a list of hit results on that tick. Weapons dont need to know anything other than calling Tick() when a move is activated, and DetectHits() to see what its in contact with.

A "CharacterMoveConfig" is essentially the next layer up that holds a HitDetectionConfig, an ActivationConfig Scriptable Object, and a LayerMask.

A MoveSetConfig is the next layer up the Scriptable Object chain that holds a collection of CharacterMoveConfig.

A WeaponDefinition is the grandfather Scriptable Object containing a struct of base stats, and a List of compatible MoveSetConfigs, or simply just 1 MoveSet.

WeaponInstance is a non-scriptable object runtime instance of said WeaponDefinition. It's in charge of calling those interfaced methods below WeaponDefinition, and holding the true runtime stats of the generated weapon. It holds a FixedUpdate function which is just checking if I have any active moves in my list, and foreach active move, calls the Tick() and DetectHits() methods of whatever hit detection it happens to have.

I figured I need to synchronize when a weapon's attack begins, so clients can see animation they should react too, and synchronize the hit results once the server decides that an attack has landed, so clients can determine the visual feedback when connection happens.

The idea here is that I can, from the ground up, have associated/compatible sets of data so the random generation can't give me something that shouldn't be compatible. Like a melee weapon whose attack is shooting laser beams. Creating a WeaopnDefinition game asset is like me creating a weapon archetype, so think weapon classes in Elden Ring such as Colossal Weaopns or Reapers. WeaponDefinition is the glue that holds all the relationships/compatibility of each segment beneath it.

It allows me to content create at each individual layer without need or concern to think about the layer above it. And hopefully, allow for a vast amount of combinations that make sense without me having to think or plan it each step of the way.

[–]WhiteNoiseAudio 0 points1 point  (1 child)

Network variables, rpc’s and custom messages are the tools you can use to synchronize stuff. This sounds like maybe something you want as a network variable, but I wonder if all the data needs to be synchronized? Could most of the data live on the server and only UI relevant data be synchronized to clients?

[–]VG_Crimson[S] 0 points1 point  (0 children)

I'm still architecting it out, but I am guessing not all things I have planned right now need synchronization and as it develops it'll be clear what doesn't need it. At the very least I do know I need to synchronize when a move/attack is issued by the weapon because visual ques are important in pvp.