Game Development Community

Any way to speed up setHidden(false)?

by Rex Hiebert · in Torque 3D Professional · 08/17/2009 (1:03 pm) · 11 replies

I have a scene that has a ground level and raised platforms. There is a need to hide the raised platforms whenever the user desires. All of the platforms are in a SimGroup. When the user hits the button to hide them, I call callOnChildren and pass it setHidden and True or False. When hiding the objects, they blink out in an instant. But when they are turned back on, you can see it redraw each one in order over 1.5 to 2 seconds.

At first, I had the TS code looping and setting setHidden on each object. I thought the issue was with it being in script. Then I found the callOnChildren method which would do the loop in compiled code instead of script. But it has the same issue.

Is there a way to speed this up? Or is there a way to lock updates until all objects have been unhidden?

Thanks!

#1
08/17/2009 (2:02 pm)
It's a network issue. What the setHidden(true) call does is to tell the clients that object was deleted. So "hiding" objects is pretty fast. When you do setHidden(false), the ghost is re-created on the client, and a lot of information like position, rotation, datablock, etc, must be re-sent to the client. Since there's a limit of how much information can be sent in each updated, unsent packets get queued for the next tick, which causes the delay you're seeing.

An easy workaround is increasing the value of pref::Net::PacketSize (defaults to 200, maximum of 1023) until the problem goes away. If you're still having problems, I suggest using something less network-intensive than setHidden() to hide/show them. If they are StaticShapes (not TSStatics), you can try using setAllMeshesHidden() instead, which only sends a few bits. However, I don't think this will disable collisions, and an alternative is to actually reposition the platforms to somewhere they can't be seen.
#2
08/17/2009 (9:02 pm)
> an alternative is to actually reposition the platforms to somewhere they can't be seen.

although if you position them in another zone, they can leave network scope, which will again cause the client-side ghosts to be deleted. but probably just underground a bit would be fine.
#3
08/18/2009 (11:17 am)
Ah, that makes sense. I didn't realize it was causing that much network traffic. I don't know that I can move the platforms as they will have other objects placed on them by the user. But hiding them may cause the same problems if the client side is deleting them. I haven't gotten to that part yet. Looks like I need to pay more attention to the networking code.

This effect only needs to be client side but it would need to be hidden from collisions as well.
#4
08/18/2009 (11:25 am)
You could modify the setAllMeshesHidden() so it also disables/enables the collisions. Another way would be switching the StaticShapes' datablocks by one that uses an invisible model without collision. Datablock switching should use very little network bandwidth.
#5
08/18/2009 (11:32 am)
This is an interesting issue I was unaware of. Isn't there a function to send batch commands over the network, or an array of meshes to hide instead of sending a packet with as many setHidden commands it can hold and then sending more until all the desired setHidden commands are sent? If not I may have to add something like that. Perhaps a setHiddenGroup which takes a simgroup.

Shouldn't the removal of ghosts from zones and recreation work similar to this already? If not that's really bad for network traffic. That would mean each time you enter a zone the network is flooded with commands to redraw what is in that zone.
#6
08/18/2009 (11:38 am)
Yeah, that's a drawback of the scoping mechanism. Maybe it would be better to remove ghosts only for players, items and vehicles, since the packets for creation are very similar to standard updates, and keep the ghosts for mostly static objects like StaticShapes and TSStatics around anyway, since they aren't consuming bandwidth when they're not doing anything.
#7
08/18/2009 (11:52 am)
Right now there are about 20 platforms that I am hiding. Eventually, there may be 100-200 objects stacked on those platforms. At least, that's the plan if the engine can support it. Seeing the slowdown with 20 items makes me wonder how it will handle 100-200.

I do want this to be multiplayer at some point but the visibility of the platforms and the objects on them can be specific to the client. The client needs to be able to see the lower level and place objects there which is why the platforms need to hide and not collide. I hope that makes sense.

I haven't looked at setAllMeshesHidden(). Is this called on a per object level or on the SimSet/SimGroup?
#8
08/18/2009 (1:19 pm)
setAllMeshesHidden() is done per object. Also, since collisions are handled on the server, you cannot disable them on client-side only.

Since you'll use lots of this the best approach is having a dedicated flag for completely hiding objects and excluding them from collisions, which takes minimal bandwidth and having a way to batch hide/unhiding commands (probably adding the ghosts to a client-side simset would do the job).
#9
08/18/2009 (1:40 pm)
great thread, folks.
rex, i'm not sure i understand the scenario.
you have a platform with a bunch of objects stacked on it,
and you want to physically and visually hide the platform for a particular client ?
what happens to the things stacked on it, do they also hide ?
what happens on the server-side when the player moves where the platform is ?

i'm going to assume this is a single-player game.
you could add a byte or so to SimObject named "vanishedMask", and in both the collision and rendering code, if a given simObject and the player share any bits in the vanishedMask, don't collide or render. you would use this by giving all your platforms and stacked objects a mask of say 1. this will be mostly static, and be ghosted once. your player initially has a mask of 0. when you want to hide stuff, set the player's mask to 1. the server will stop colliding, and the player's vanishedMask will ghost down over the wire and instantly stop rendering and colliding with all the objects there as well.
the advantage here is that when you want to hide or reveal all the objects, you're only setting a single value in the player, rather than a value in each of 100s of networked objects, and so the effect will be simultaneous, without the nondeterministic delay inherent in the ghosting mechanism.
the reason for using a mask rather than just a boolean is so that you can different sets of objects w/ this behaviour. eg platform group A and platform group B.

it might be clearer in code.
this is obviously just a pseudo-code sketch.

class SimObject
   U32 mVanishMask
   
---
   
SimObject::packUpdate()
   if (writeBit(mask & VANISHMASKNETMASK))
      writeU32(mVanishMask)
   
---

SimObject::render(Player* forThisPlayer)
   if ((forThisPlayer->mVanishMask & mVanishMask) != 0)
      return;  // don't render
   
---

SimObject::collide(Player* withThisPlayer) // this will be by far the trickiest part
   if ((withThisPlayer->mVanishMask & mVanishMask) != 0)
      return;  // don't collide
#10
08/18/2009 (3:09 pm)
The player won't be an issue. This will work more like an RTS game. The mouse pointer will be on screen, the player will select objects to move to the platforms. If they want to place something on the upper platform, they will select the object and then place it on the platform with a visible guide that follows the mouse pointer across the platforms. If they want to place the item on the lower level, the upper platforms will need to be hidden (along with any objects placed on them) so that they can see what is on the lower level and point/click to place.

The collisions I am concerned about are the ones used to decide where to place an object. If the top platforms are hidden, I want the "hits" to happen only on the ground level or (non-hidden) items on the ground.

I eventually want this to be multiplayer but the other players may be just spectators. This is more of a training tool and not a game.

A vanish mask may work. I'll have to take a look at it but it's a little slow going as i am still new to Torque.
#11
08/18/2009 (3:17 pm)
Yes, in your case you can safely disable collisions on the client, since you'll only use them for mouse events (as long as you do your mouse event raycasts in the client).