Extending/overriding code in asset?

I need to customize logic of code from an asset purchased from the store. I need to make changes to properly support FishNet/multiplayer. I’ve spent days researching ways to get it to work without changing the assets code, but I see no alternatives. I’m looking for input/advice on the best approach to do this.

Unfortunately it seems like my only choice is directly edit the code in the asset - I can’t subclass/override methods without updating references to the new versions, so there’s no way to do this without editing the existing code.

I can no longer update the asset without also re-copying in all of my changes. Is there some solution I haven’t considered?

Without seeing the code and the kind of change you need to make? Almost impossible, you can at best hope to get generic tips on how to approach this (ie subclass, extension method, reflection, etc). We don’t even know what that asset is … a character controller?

But it would leave by the wayside the option of not having to modify the original code. Perhaps you have been fixated on a particular solution where all it would take is another wrapper script, or an extra game object in the hierarchy, or similar. :wink:

If it is indeed a character controller, make it work locally. You have a GameObject that moves around. Now you need this on the actual network player though but for some reason you can’t add the controller to the player prefab. What can you do?
Well, use the two separate objects. The controlled object has no visualization and the network player simply updates its transform to match that of the controlled object ideally reacting to an event “OnAfterMotionUpdate” to ensure it does update after motion, to avoid 1-frame delays or delayed network sync.

Plenty of ways but we need more details. :wink:

1 Like

The asset is MapMagic2 and my goal is get the terrain and world objects to generate in a FishNet multiplayer game.

The terrain has to be generated client-side using a seed shared by the server, that’s no problem. World objects (rocks, trees, etc) need to be generated server-side because they’re NetworkObjects that need to be synchronized between clients. One player can pick up a rock, cut down a tree, the others need to see that change. The server also has to be in charge of saving that state.

The problem is that MM2 generates those objects with the terrain, so it’s done client side. It instantiates objects itself, so there’s no room for my code to do it instead. I’d need to modify the asset code to instantiate the objects server-side and pass them to ServerManager.Spawn.

Except MM2 was written to generate both terrain/objects at the same time, but terrain can’t be generated server-side because a) it’s unnecessary and b) it throws errors as MM2 has render/shader/etc code that errors in server-only builds.

On top of that MM2 organizes world objects by having a parent object for each tile but it’s a dynamically-created object not a prefab, so FishNet isn’t aware of it, can’t spawn it, and can’t attach objects to it, so even if world objects are spawned by the server they end up in the root scene - not a huge deal but is a mess for development.

My only choices seem to be:

  • Modify the asset code to generate terrain/objects in a network-aware way
  • Not let any of the world objects be network aware and use an ID system to despawn/move them
  • Write my own generation code that reads the output of the MM2 graphs

Yes to network synchronized but no to them having to be NetworkObjects. In fact I would avoid doing so due to the overhead of spawning and maintaining this many networked objects - since rocks and trees sounds like you may have 100+ of these.

Instead check if the object generation is truly deterministic. If so, all you need to do is to find a way to uniquely index them. For instance, assuming that GetComponentsInChildren is deterministic (I think it is but not 100% sure) this would give you an indexable list of trees that is the same for all clients. Then you can send a TreeChoppedDownServerRpc(int treeIndex) to inform everyone that the tree fell.

If the falling tree has physics, it should not matter if the tree lays at a different place and angle for each client. If it does matter I would use an animation instead.

Manually managing network objects also has the added benefit that you are not restricted by any parenting requirements (eg network objects always spawning in the root by default).

Okay that sounds like you have no choice but to modify the asset’s code. Actually it sounds like you may even need to apply all three of the proposed solutions to parts of the project.

To be clear about the shader error, that’s only if I try to render the terrain server-side, which I would only need to do if I wanted to also render world objects server-side.

If I’m only rendering them both client-side and using an ID approach, the server wouldn’t need to generate either so it’d be fine. Clients would need to tell the server about objects destroyed due to player activity, the server would need to communicate that to all other clients, save it to a savefile, and tell clients which objects not to generate next time that terrain is loaded, but that’s doable.

I was worried that would be a less-than-ideal approach but if your recommendation is not to have them be NetworkObjects, maybe the id system isn’t as bad.