#Unspawn behaviour

60 messages · Page 1 of 1 (latest)

dire moth
#

I discovered & reported this (https://github.com/MirrorNetworking/Mirror/issues/4066) while debugging my object pooling. I took a closer look at the client behaviour when calling NetworkServer.Unspawn(object) and discovered that it actually destroys the object on the client. Curious why the client destroys while the server sets object.active = false (allowing it to effectively only be pooled on the server)?

#

Also noticed that the ObjectHideMessage also results in the client calling DestroyObject()

quick pine
dire moth
#

oh I see, so there's an expectation to link in custom spawn, unspawn handlers on the client. Namely to use: NetworkClient.RegisterPrefab(prefab, SpawnHandler, UnspawnHandler);

dire moth
#

Would it make sense to also have generic spawn/unspawn handlers instead of specific ones for each assetId? And then let the custom code worry about the type of asset and how to spean each?

#

Also by default: the server uses .setActive(false) while the client uses Destroy(). I was expecting the behaviour to be identical on both sides and was wondering why it was decided to have this difference between them (I'm mainly curious)?

Server:
Sends ObjectDestroy message to client
https://github.com/MirrorNetworking/Mirror/blob/master/Assets/Mirror/Core/NetworkServer.cs#L1863
Then disables the object (.setActive(false))
https://github.com/MirrorNetworking/Mirror/blob/master/Assets/Mirror/Core/NetworkServer.cs#L1897

Client:
ObjectDestory is bound to Destroy
https://github.com/MirrorNetworking/Mirror/blob/master/Assets/Mirror/Core/NetworkClient.cs#L525
Destroy(object) is called
https://github.com/MirrorNetworking/Mirror/blob/master/Assets/Mirror/Core/NetworkClient.cs#L1930

quick pine
dire moth
#

Yep, was curious why that was chosen as the client behaviour? would it not be more consistent for the client to also keep the object (regardless of if its runtime spawned or scene)?

#

IMO it would be a bit easier to reason about what happens under the hood if both sides did the same thing when Uspawn is called.

quick pine
#

We can't leave tens of thousands of objects on the client like that, as could happen in interest mgmt. Clients are treated as hostile, so you'd want the client to have as little information as possible. Having it know about disabled objects would be a cheat vector...think spawn or resource camping as an example.

dire moth
#

That's true! But then wouldn't that be the deciding factor for whether you'd want to call Destroy() or Unspawn()? If the information about inactive objects must not leak, go for Destroy() otherwise use Unspawn with a pooling solution integrated

quick pine
dire moth
#

Agreed. What I'm getting at is: to discard a non pooled object wouldn't one always call NetServer.Destroy(). While to discard a pooled object, never call NetServer.Destroy() always call NetServer.Unspawn()?
(and hence expect the server and client to do the exact same discard action on both client and server, either both destroy the object or both return it to pool and set it as inactive)

quick pine
dire moth
#

Oh I think that's what's missing from my mental model of it

#

What other usecases is it for?

quick pine
#

moving NPC's on the server after they've been killed to be respawned elsewhere. Hiding doors or other resources pending reveal per player action, proximity, or other event. Hiding interactive things so they're only spawned for brief time at intervals. Hiding imposter trees in favor or real trees when being harvested. And that's just what comes to mind in the moment.

dire moth
#

Ooh, I see what you mean. Form the server's perspective it may be perfectly fine to have stuff inactive (hidden) ready to be re-revealed later while the client should not know about them at all.

#

I have been definitely biased by my own need of Unspawn 🥲

I pool single use objects (mines, very low fire rate bullets, etc.) stuff that isn't hidden but rather reused later for a different shot, so both client and server can keep track of the hidden instances for reuse in my case

#

Cool, good to hear the reasoning behind it

quick pine
dire moth
#

That's a good shout, high fire rate projectiles I only spawn locally (not networked) but i'm using a whole rigidbody and collider on a game object for that. Will look at the ParticleSystem.Emit for an alternative. The projectile i pool is a slow moving homing bullet that i want to be server authoritative, the fire rate is around every 4 seconds

#

So for the latter I think that having it networked is a necessity si that the following the target part looks the same on all mirrors

quick pine
#

Particles can move toward a target too.

dire moth
#

Indeed, but what about the server authoritative part?

quick pine
#

same thing...look here (ignore the age...still works afaik).

dire moth
#

Hmm, if I could load a single particle with an ID, then this would work pretty well fishHmm

quick pine
#

id for what...the shooter? emitter is the shooter, collision gives the victim.

#

.Emit is for a single particle (mesh)

dire moth
#

yep got that, id for each bullet - i use those to allow both client and server to report where the bullet hit and to try to validate if i believe the client or not

quick pine
#

Believe the client about what? Client is just VFX. Only the server records hits

dire moth
#

True if I use lag compensation, but I do not use that yet (plan to). So at the moment my prototype just blindly believes the hit reports coming from the client

quick pine
#

lag compression is irrelevant. Server decides hits, never clients.

dire moth
#

For full fairness, yes. but for the client experience, that's very frustrating to fire at a "ghost" position, to believe that you should be getting hits and then in reality there being no hits

#

This happend to Sea of Thieves as well AFAIK, they released with server authoritative hit registration, and people noticed it

#

This is temporary though, i don't plan to believe client reported hits but am doing that at the moment just to prevent that frustration of missed hits on the server

#

I'm looking into enabling lag compensation to get rid of this consideration

quick pine
#

You do understand that there's no way to speed up msg packets between client and server, right? There's no magic there. RTT is what it is. Make the colliders a bit fatter on the server so very near misses count as hits. Delay the client VFX by 1/2 RTT so they'll be really close to what server is doing. Both use the same pos and direction for the shot, and therefore the same result.

dire moth
#

Yes, I'm aware. I've just decided to temporarily trust the client to ensure that the lack of lag compensation doesn't affect the experience.

So as a consequence I do collect too much information for sure: i.e. each bullet has a guid, origin, direction

#

When eventually I'll just need origin, direction and time of shot

quick pine
dire moth
#

Well give me a bit more of your mental model of how that happens 😄

#

the server is the authority, but my client controls their turret with authority (for smooth results) so when it fires, it sends a message to the server

#

at this point, the orientation of the turret on the server may be slightly older than the client's, no?

#

also, the position from which the client shot is in the past from the servers persoective when the fire message arrives

quick pine
# dire moth the server is the authority, but my client controls their turret with authority ...

you have NetworkTransform (any flavor) on the turret, so other clients see it moving. Server sees that too. CmdShoot is processed alongside the NT update arriving, so server has the turret pos and aiming direction. Server tells all clients (except shooter because shooter already does their VFX "predictively" with 1/2 RTT delay) to show VFX of the shot with direction...they'll start it from the end of the turret barrel but run it in the correct direction. Server then runs it's own shot and determines hits. Clients (including shooter) can show explosion secondary particle effect on contact with whatever.

dire moth
#

Problem: The turret is mounted on a server authoritative NetworkTrasform

#

the client only controls the orientation locally

quick pine
#

Client should move their own tank, not server, as well as aim their turret. See PlayerTest example with the Tank player prefab.

dire moth
#

the server is the one sending NT updates to everyone else. The client is not in control of that in my setup. So the CmdShoot has happened on an older position by the time it arrives

dire moth
#

so the pilot has move authority, while the gunner does not

quick pine
#

Then it doesn't matter

#

other client is moving the plane...so what? all that matters for the shot is where the turret is in the world.

dire moth
#

Where it is in the world at the time of the shot

quick pine
#

Which server knows

dire moth
#

Shot originates at T0
plane travels at 30m/s in a straight line, movement is server authoritative.

Shot command arrives at the server at T60(ms)
the plane's position on the server at T60 would be further ahead (1.8M at this speed) than when the player has clicked fire if the plane movement is server authoritative, would't it?

#

without the ability for the server to look in the recent past that is

#

so effectively like this the shot is spawned 1.8 meters ahead along the plane's forward axis. That would be 1.8M away from the true shot origin

dire moth
#

In any case, once i get to polish the approach to this bit I can report back findings.