Strange initPersistFields behavior
by Drew Parker · in Torque Game Engine · 02/15/2005 (6:51 pm) · 15 replies
Hi all,
I'm trying to make some finishing touches on a GUI for an upcoming ODE physics update. But I'm getting some really weird behavior from the addField() command in initPersistFields(). My GUI can't update the object it works with, because whenever it tries to access the object's shared field, a script member is created instead.
For instance, if I have an object member exposed to script through initPersistFields() like this:
When I try to change the variable from script, like this:
Sometimes a new script variable called useClamping is created, instead of accessing the object member! I know because I check it will the tree() command when things don't go as expected.
Has anybody ever come across this? Any ideas on how to get around it? Worse thing is, it seems it may be happening randomly. Any help is greatly appreciated!
Thanks,
Drew
I'm trying to make some finishing touches on a GUI for an upcoming ODE physics update. But I'm getting some really weird behavior from the addField() command in initPersistFields(). My GUI can't update the object it works with, because whenever it tries to access the object's shared field, a script member is created instead.
For instance, if I have an object member exposed to script through initPersistFields() like this:
addField("useClamping", TypeBool, Offset(mODEUseClamping, ODEWorld));When I try to change the variable from script, like this:
%world.useClamping = true;
Sometimes a new script variable called useClamping is created, instead of accessing the object member! I know because I check it will the tree() command when things don't go as expected.
Has anybody ever come across this? Any ideas on how to get around it? Worse thing is, it seems it may be happening randomly. Any help is greatly appreciated!
Thanks,
Drew
About the author
#2
I can't really offer much advice without seeing the scripts. Some things that come to mind are that you maybe possibly mispelled useClamping some place?
02/16/2005 (1:47 pm)
Hmm not really sure what is going on. I can assure you this is used extensively throughout the engine and if it was a problem it would have shown up by now in other instances.I can't really offer much advice without seeing the scripts. Some things that come to mind are that you maybe possibly mispelled useClamping some place?
#3
Thanks for the reply. I'm not sure what's going on either, it's something I've used a lot before and never had problems with. I'll double check my spelling to see if I can find any errors. I have a lot of addField() commands in the object, so I was wondering if maybe there's a limit somewhere to how many fields you can have exposed to the engine per object. It's strange how another script variable of the exact same name is created for the object.
This is how I it's setup, to give another example:
In C++
In script, a GUI updates the values when Apply is clicked like this:
What's strange is, it works fine in single-player or a server-host. It doesn't work well on a network only client. The %world variable correctly points to the object it should point at, because other variables do change correctly. Just some near the end don't work. I'll try debugging it, but it's tough since all the driving points are in script.
02/16/2005 (2:22 pm)
Hi Robert,Thanks for the reply. I'm not sure what's going on either, it's something I've used a lot before and never had problems with. I'll double check my spelling to see if I can find any errors. I have a lot of addField() commands in the object, so I was wondering if maybe there's a limit somewhere to how many fields you can have exposed to the engine per object. It's strange how another script variable of the exact same name is created for the object.
This is how I it's setup, to give another example:
In C++
addField("showCollisionMeshes", TypeBool, Offset(gShowCollisionMesh, ODEWorld));
addField("drawServerObjBox", TypeBool, Offset(gDrawServerObjBox, ODEWorld));
addField("drawClientODEBox", TypeBool, Offset(gDrawClientODEBox, ODEWorld));In script, a GUI updates the values when Apply is clicked like this:
%world.showCollisionMeshes = ODE_showCollisionMesh.getValue(); %world.drawServerObjBox = ODE_showServerBox.getValue(); %world.drawClientODEBox = ODE_showClientODEBox.getValue ();
What's strange is, it works fine in single-player or a server-host. It doesn't work well on a network only client. The %world variable correctly points to the object it should point at, because other variables do change correctly. Just some near the end don't work. I'll try debugging it, but it's tough since all the driving points are in script.
#4
If anyone else has come across this before, please let me know. I'll keep looking at the code and see if I can find some sort of silly mistake I'm making that may cause this.
02/18/2005 (10:55 am)
Looks like this problem only occurs when a network client is running, and not in singleplayer or server-host, which is strange. Anyway, I wanted it to work so that when network clients run the ODE resource update we're about to release, people can change the ODE settings for the network client, mainly the visual debug settings, like showing the contact points and the ODE wireframe. It works fine on the server machine. So I guess people might have to use the tree() command to change them manually for now, until we (or someone) can figure out why that kind of thing happens.If anyone else has come across this before, please let me know. I'll keep looking at the code and see if I can find some sort of silly mistake I'm making that may cause this.
#5
This is just a guess of course, but it does seem unusual...
EDIT: In most of the code I've seen in TGE, when a global reference like what you have is in code, and may be executed on both the client and the server, there is normally a gServerxxxx and a gClientxxx, and the appropriate one is selected based on being a client side executable or the server side executable. I think this is also part of why the code "smells suspicious" to me...can't help any more than that though :(
02/18/2005 (2:50 pm)
I can't point to exactly why, but I'm wondering if it has to do with the fact that you appear to be using a global variable in the Offset macro. Since you are transmitting the data across the net to the clients, I'm guessing that you aren't accessing the correct version of the global client side, or possibly boundaries are mucked up...obviously, the global variables won't point to the exact same memory space since you are in two different executables.This is just a guess of course, but it does seem unusual...
EDIT: In most of the code I've seen in TGE, when a global reference like what you have is in code, and may be executed on both the client and the server, there is normally a gServerxxxx and a gClientxxx, and the appropriate one is selected based on being a client side executable or the server side executable. I think this is also part of why the code "smells suspicious" to me...can't help any more than that though :(
#6
That would certainly be a good guess. :) However, the variable name *used* to be global, but now it is a class member, I just haven't had the time yet to rename all the times it's used and take out the g.
02/19/2005 (6:08 am)
Hi Stephen,That would certainly be a good guess. :) However, the variable name *used* to be global, but now it is a class member, I just haven't had the time yet to rename all the times it's used and take out the g.
#7
Are you getting any console spam?
02/19/2005 (4:23 pm)
So... you're trying to access fields on a server object from the client? That doesn't really work. :-/Are you getting any console spam?
#8
Taking another look, what it looks like to me is basically this:
When I work with a ghost object, the class members I change in script because I used the addField command, for instance like this:
But, if I use a method and call that on the ghost object, like this:
I don't know why that is. Of course, doing a %world.erp = 0.3 on the server object (via the addField() command) works (as Robert mentioned above).
I tested this again just now, and it looks like this is what is happenning. Trying to access an addField()'ed member on the ghost object won't work. I'll do some more tests to make sure.
02/19/2005 (4:56 pm)
No console spam that I know of.Taking another look, what it looks like to me is basically this:
When I work with a ghost object, the class members I change in script because I used the addField command, for instance like this:
%world.erp = 0.3;Don't work. It just creates a dynamic script field for the ghost called erp.
But, if I use a method and call that on the ghost object, like this:
%world.setERP (0.3);Then it seems the ghost object's value is updated.
I don't know why that is. Of course, doing a %world.erp = 0.3 on the server object (via the addField() command) works (as Robert mentioned above).
I tested this again just now, and it looks like this is what is happenning. Trying to access an addField()'ed member on the ghost object won't work. I'll do some more tests to make sure.
#9
Running %player.nameTag = "Drew" on the server object changes the field to "Drew".
Running %player.nameTag = "Drew" on the ghost object doesn't change the field.
Of course, this could be listed in the docs somewhere and I totally missed it. :) At least now I know how to fix my problem. Go through and make all the object variables changed through my GUI use get/set consoleMethods(). That way, the GUI will still be able to affect the ghost object in a networked game.
02/19/2005 (5:03 pm)
Ok, I just tested this on the Player object with the nameTag field. Seems to be the case.Running %player.nameTag = "Drew" on the server object changes the field to "Drew".
Running %player.nameTag = "Drew" on the ghost object doesn't change the field.
Of course, this could be listed in the docs somewhere and I totally missed it. :) At least now I know how to fix my problem. Go through and make all the object variables changed through my GUI use get/set consoleMethods(). That way, the GUI will still be able to affect the ghost object in a networked game.
#10
02/21/2005 (8:57 pm)
Something seems very very badly wrong here with your approach. :-/
#11
In what way, and regarding to what? I'm all ears for suggestions. :)
Even if it does turn out my approach is very bad (hopefully not, but always possible), in the course of my approach I have discovered something about the engine that I didn't know before, and it would be nice to discover if this is a bug or expected behavior. I have not seen it anywhere on the site, but that doesn't mean it's not documented, I very well could have overlooked it.
So it would be nice to know if
1. Others have seen this behavior, and
2. If so, is there a way of fixing it, or is the fix to just avoid it?
02/22/2005 (6:30 am)
Hi Ben,In what way, and regarding to what? I'm all ears for suggestions. :)
Even if it does turn out my approach is very bad (hopefully not, but always possible), in the course of my approach I have discovered something about the engine that I didn't know before, and it would be nice to discover if this is a bug or expected behavior. I have not seen it anywhere on the site, but that doesn't mean it's not documented, I very well could have overlooked it.
So it would be nice to know if
1. Others have seen this behavior, and
2. If so, is there a way of fixing it, or is the fix to just avoid it?
#12
The only fields that are going to get updated across the network are ones you have code specifically written to deal with. Which means that you have to register a callback one way or another so that the networking layer will know when it needs to send updates across the wire. Some objects have this behavior for script fields... most don't.
02/23/2005 (9:25 pm)
It seems like your expectation is that fields will automagically get updated from parent to ghost... Or that there is some sort of automatically enforced correlation that happens. I could be wrong. :)The only fields that are going to get updated across the network are ones you have code specifically written to deal with. Which means that you have to register a callback one way or another so that the networking layer will know when it needs to send updates across the wire. Some objects have this behavior for script fields... most don't.
#13
Thanks for the feedback. I think you are right about that, I'd definitely need code to update a ghost variable over the network. :)
But that's actually not my problem from what I can tell. What I'm working with is a ghost-always ghost object. That ghost object is the object I want to interact with, not the server object. I want to change a variable on that ghost object, not the server object. Why? Because I want to toggle a client-side only effect for debugging on a client object. I'm not trying to sync-up variables over the network, nor am I trying to change a variable on the server by interacting with the ghost object. As a client machine, I need to change a field on a ghost object, but when I try to access a member variable through the script, setup via the addField() command, it doesn't work. It instead creates a new script object of the same name. Hence my conclusion posts with the "drew" example a few posts up.
See what I'm saying? It seems addField() doesn't work for ghostObjects. There could be of course reasons for this that I am unaware that are totally valid. But I didn't realize it, so as I discovered that, I thought I would post my findings for others who may come across this problem.
Now of course, I could also be wrong. :) But I'd say I'm 91% sure that my problem is not one of expecting fields from parent to ghost will get automatically updated. It's some other problem. ;)
02/24/2005 (2:53 pm)
Hey Ben,Thanks for the feedback. I think you are right about that, I'd definitely need code to update a ghost variable over the network. :)
But that's actually not my problem from what I can tell. What I'm working with is a ghost-always ghost object. That ghost object is the object I want to interact with, not the server object. I want to change a variable on that ghost object, not the server object. Why? Because I want to toggle a client-side only effect for debugging on a client object. I'm not trying to sync-up variables over the network, nor am I trying to change a variable on the server by interacting with the ghost object. As a client machine, I need to change a field on a ghost object, but when I try to access a member variable through the script, setup via the addField() command, it doesn't work. It instead creates a new script object of the same name. Hence my conclusion posts with the "drew" example a few posts up.
See what I'm saying? It seems addField() doesn't work for ghostObjects. There could be of course reasons for this that I am unaware that are totally valid. But I didn't realize it, so as I discovered that, I thought I would post my findings for others who may come across this problem.
Now of course, I could also be wrong. :) But I'd say I'm 91% sure that my problem is not one of expecting fields from parent to ghost will get automatically updated. It's some other problem. ;)
#14
Then, have your code check for the value of this variable prior to doing your specialized processing/debugging.
02/24/2005 (4:01 pm)
My suggestion would be to post a NetEvent to only the clients that require it, and capture the event, saving it into a (script accessable) global variable client side.Then, have your code check for the value of this variable prior to doing your specialized processing/debugging.
#15
Thanks for the suggestion, I never even thought about trying a NetEvent. Actually, I haven't worked with them yet so I could still do to learn about them.
That's what I really like about these forums and the GG community. People help out each other, and you can be introduced to things you never would have thought of. It's really valueable to have a place where you can bounce ideas off people, or get feedback on a problem you are having.
Thanks for all that responded!
02/25/2005 (7:13 am)
Hi Stephen,Thanks for the suggestion, I never even thought about trying a NetEvent. Actually, I haven't worked with them yet so I could still do to learn about them.
That's what I really like about these forums and the GG community. People help out each other, and you can be introduced to things you never would have thought of. It's really valueable to have a place where you can bounce ideas off people, or get feedback on a problem you are having.
Thanks for all that responded!
Torque 3D Owner Drew Parker