Game Development Community

Ghosting and Scoping

by Ivan Mandzhukov · in Torque 3D Professional · 10/12/2010 (10:36 am) · 7 replies

Hi,
These days I am working on objects that are dynamically created runtime on the C++ side.
In onAdd() I create the object this way:

mObj = new Object;
ObjectData *p = dynamic_cast<ObjectData *>(Sim::findObject("MyDatablock"));  

mObj->onNewDataBlock(p);
mObj->setPosition(Point3F(-37,113,20)); 

mObj->addToScene();
mObj->onAdd();

This is my destructor ,I delete the object this way:

mObj->unregisterObject();
mObj->~Object();
delete mObj;

if(mObj) 
  mObj = NULL;


First of all this object was never scoped to the client,there for I call addToScene() for a second time to create my object on the client side.

When I scope the object, the ghosting is really problematic.I found also that objects without visible mesh process incorrectly.

The final problem is those objects are called registerObject() automatically,but unregisterObject is never called and this will crash T3D on exit.Therefore I call it manually.

Currently I bypass the ghosting with global variables - The first object writes,the second object reads,but this is an ugly solution so far.

So I have some questions:
What is the order of ghosts in T3D ? It seems the order is wrong.
How T3D process ghosts ? It seems the processing is not satisfactorily when I create objects from c++.

Thanks

#1
10/12/2010 (4:55 pm)
I'm not sure if it is linked, but I remembered having read something about ghost process in the bug list where there was an issue with the ordering.
#2
10/12/2010 (5:01 pm)
your object must inherit from NetObject to have ghosting. if it is a netObject, it will automatically ghost when you call addToScene or its onAdd function.
#3
10/12/2010 (6:01 pm)
@Devin
I inherit from NetObject.
I did a few tests :
When objects are created from torquescript ,they process as usual.
When they are created in c++, their processing (and ghosting) is wrong.
#4
10/12/2010 (10:49 pm)
The ghosting order has always been in reverse (even before T3D was T3D and even before the engine was renamed Torque). You cannot count on objects being created in the same order on server and client -- and even if they were created in the same order, you couldn't count on them being ghosted to the client anyway (except for if they're always in scope).

Just looking at the code that you're using to create objects and it's looking like you're going about it somewhat wrong. Creating the object and setting its datablock are fine, but adding it to the scene and so on, well... that should be done in the object itself.

The following code is what I normally use to create a networked object of the type required (assuming, of course, it derives from NetObject or GameBase or whatever):

// Create the new object.
MyObjectClass* pObject = new MyObjectClass;

// Set the object datablock.
pObject->onNewDataBlock(pDataBlock, false);

// If the object couldn't be registered successfully...
if (!pObject->registerObject())
{
    // Delete the object and clear the pointer.
    delete pObject;
    pObject = 0;
}

... and deleting that very same object, provided you've still got a pointer to it, is equally simple. You don't manually call unregisterObject and you don't use the delete operator. Instead, you use the ::deleteObject method on the object itself. This will clean the object up properly.

pObject->deleteObject();
pObject = NULL;

The thing you have to bear in mind with object creation is whether or not you're creating it on the server or the client. Oftentimes you simply don't need to create an object on the server. Things like particle effects, sounds, and so on, you can often have generated by other client-side ghosts. For example, particle effects and decals for footsteps can be created by the player ghosts, thereby preventing the need for them to be transmitted over the network.

As for ghosting and scoping, well.... Objects on the server are only ghosted to the client if they're in scope -- usually within the visible distance of the local client's current control object position. The order they come through in is determined by when they were created, what their update priority is to the client, and what else is happening on the network.

If you've got a lot of objects sending network updates and you create a lower priority object, you're not going to see it on the client until all the higher priority objects (such as players and projectiles) are done with their updates.

The exception to this is, of course, scopealways objects which are always in scope and so always ghosted to the clients. In fact, I'm pretty sure they have a separate update before to the priority-based packing that happens with other more-dynamic objects.
#5
10/13/2010 (7:15 am)
Is the object appearing on the server ok? you can see it often using the mission editor (F11) and group-selecting where you think it is, youll see it appear even if its not visible to the client when in listen server mode. Im worried its not scoping to the client because there is some problem with its presence in the world on the server.
#6
10/13/2010 (8:15 am)
Just FYI. If you're wanting your object to be ghostable to clients then you need to set the appropriate netflag (usually in the constructor) as shown below.

// Constructor.
MyObjectClass::MyObjectClass()
{
    mNetFlags.set(Ghostable);
}

You can also use the netflags to set the object to scopealways -- so it'll always be ghosted to every client -- like so:

// Constructor.
MyObjectClass::MyObjectClass()
{
    mNetFlags.set(Ghostable | ScopeAlways);
}
#7
10/13/2010 (8:52 am)
@Devin
The object is visible, scoped and ghosted
unpackdata(),client processtick(),interpolateTick(),advanceTime() - all the client side stuff is called and processed

Daniel,thanks for the tips.
I know I should not call onAdd() and addToScene() manually but without it objects are added on server only.
I have some results - I think I call addToScene() twice and this is the reason I get several server processticks compared to a single processtick of the main object.