T3D 1.1 Beta 2 - When shooting close, effects might not aperar - RESOLVED
by Marcus L · in Torque 3D Professional · 08/05/2010 (1:59 pm) · 56 replies
Build: 1.1 Beta 2
Platform: Windows 7 64x
Target: In-game
Issues: If you shoot at a sloped collision shape (for example a terrain slope) that is close to the player, no explosion effect will appear. This does also happens if you shoot a TSStatic at a specific distance.
Steps to Repeat:
1. Launch the game - DeathBall Desert
2. Pick up the RocketLauncher
3. Move to a slope in the terrain
4. Aim down
5. Shoot
Suggested Fix: I have no solution, but i did experience this in 1.1a & 1.1b2 and i fixed it by delaying the projectile by one tick. Not a real fix tho. EDIT: Current fix at comment #27. Does also require increased $pref::Net::PacketRateToClient, suggested size is "32".
EDIT2: There was also an additional bug introduced here due to the introduction of setHidden, fix is at comment #52.
Thanks,
Marcus L.
Platform: Windows 7 64x
Target: In-game
Issues: If you shoot at a sloped collision shape (for example a terrain slope) that is close to the player, no explosion effect will appear. This does also happens if you shoot a TSStatic at a specific distance.
Steps to Repeat:
1. Launch the game - DeathBall Desert
2. Pick up the RocketLauncher
3. Move to a slope in the terrain
4. Aim down
5. Shoot
Suggested Fix: I have no solution, but i did experience this in 1.1a & 1.1b2 and i fixed it by delaying the projectile by one tick. Not a real fix tho. EDIT: Current fix at comment #27. Does also require increased $pref::Net::PacketRateToClient, suggested size is "32".
EDIT2: There was also an additional bug introduced here due to the introduction of setHidden, fix is at comment #52.
Thanks,
Marcus L.
#22
If this is so, then if you push your terrain to start outside its boundaries (as seen when normally starting at 0 0 0) it will produce the same issue. Ie. if your terrain is 1024x1024 with a square size of 1 then make it start at 1024:1024.
Also, make sure that all points in your terrain are above world space 0 z. Perhaps thanks to the same reason, collision does not seem to work when you have (some?) negative z coordinates in your terrain. Weird. Granted, I still need to check this with Beta 2. These are just ideas for when hunting this bug down.
08/06/2010 (12:35 pm)
I recall an issue where terrain coordinates had to be converted from object coords into world coords to be of use. I think it was with my layer based traversing resource. Either way - this could be one pointer.If this is so, then if you push your terrain to start outside its boundaries (as seen when normally starting at 0 0 0) it will produce the same issue. Ie. if your terrain is 1024x1024 with a square size of 1 then make it start at 1024:1024.
Also, make sure that all points in your terrain are above world space 0 z. Perhaps thanks to the same reason, collision does not seem to work when you have (some?) negative z coordinates in your terrain. Weird. Granted, I still need to check this with Beta 2. These are just ideas for when hunting this bug down.
#23
I have yet to check this but if I have a statc mesh (say a bridge or building) and I have placed it similarly then I am assuming that they too will not register the explosions or decals client side.
@Steve
I do recall that most engines center or start terrains at the origin point as a rule. :) I've been around too long but never really been on the coding side of things :) As you pointed out, I am new to the Torque World :) But I've messed with level building since the days of Doom :)
edit:
I just tested with the stock 'station' mesh placed at about "760 725 1.5" in the 'empty room' mission and sure enough I got no decal or such. I also tested the 'station' mesh in the 'empty terrain' mission and found no such problems, even placing the mesh at "1100 1100 250". I imagine the ground plane is simply a programically generated surface that tiles as you move across it, and whatever mechanism used for the decals and such are based off some default area in that case. I'm not a very experienced C++ guy so I could be way offbase.
08/06/2010 (2:38 pm)
I checked the ground plane as well in the empty room mission. I moved it's location to "700 700 0" and put the spawn sphere over the same spot and I got the same results as moving a terrain or a mesh out from the origin.I have yet to check this but if I have a statc mesh (say a bridge or building) and I have placed it similarly then I am assuming that they too will not register the explosions or decals client side.
@Steve
I do recall that most engines center or start terrains at the origin point as a rule. :) I've been around too long but never really been on the coding side of things :) As you pointed out, I am new to the Torque World :) But I've messed with level building since the days of Doom :)
edit:
I just tested with the stock 'station' mesh placed at about "760 725 1.5" in the 'empty room' mission and sure enough I got no decal or such. I also tested the 'station' mesh in the 'empty terrain' mission and found no such problems, even placing the mesh at "1100 1100 250". I imagine the ground plane is simply a programically generated surface that tiles as you move across it, and whatever mechanism used for the decals and such are based off some default area in that case. I'm not a very experienced C++ guy so I could be way offbase.
#24
Edit: doesn't happen all the time, maybe after every 4-5 shots at close range.
Edit: Edit: plus I'm sure we had this problem in a very early beta, not 100% sure though.
08/06/2010 (3:05 pm)
Just to confirm what Aaron is saying, I don't think this is just related to terrains. I have just shot a dts object with visible collision on, and it did the same. So a collision bug?Edit: doesn't happen all the time, maybe after every 4-5 shots at close range.
Edit: Edit: plus I'm sure we had this problem in a very early beta, not 100% sure though.
#25
08/06/2010 (3:12 pm)
Yup, it does happen to all sort of collidable stuff.Quote:So a collision bug?Nah, i think it is more of a server-client bug, if you see in projectile.cpp under Projectile::simulate( F32 dt ), there sould be a comment that says:
// It is possible that during the processTick the server may have decided that a hit // has occurred while the client prediction has decided that a hit has not occurred...Which has something to do with ExplosionMask, but I'm not an networking expert so I'm not 100% sure that it is related.
#26
I believe we are seeing 2 distinct behaviors that appear the same but have different causes:
-Lost client side effects due to missed ticks
-Lost client side effects due to being 'out of scope' in some way.
The first is definitely not a bug, just a missing feature (client side prediction).
08/06/2010 (3:19 pm)
Could this be related to the buggy terrain tiling code that was recently disabled because it had issues with lighting and such? I believe we are seeing 2 distinct behaviors that appear the same but have different causes:
-Lost client side effects due to missed ticks
-Lost client side effects due to being 'out of scope' in some way.
The first is definitely not a bug, just a missing feature (client side prediction).
#27
With the map as downloaded I confirmed the same results. Unlike the original issue with packet rates I was going on about, this was consistant; every rocket fired at my feet caused server explosion with no client ghost.
After I saw the posts where you guys found it was related to the position of the object itself, I scaled the maze object up to 30x and moved it to (0,0,0) so I could test if it was related to the Player's coordinates. Each corner exhibited the effect, while the single-coordinate edges did not (nor did the center).
In the process of this testing, I got irritated with the vis limit set to 1000, so I cranked it up to 5000. Suddenly I couldn't reproduce the issue. Toggling it back and forth while standing on the scaled up maze obj at around (2500,2500,0), at 1000 the explosions always fail to appear. At 5000 they always appear. There's definitely a scoping issue here, but it's something less than obvious.
I'll update this if I figure anything else out.
[Edited] Oookay, now I'm extra confused. I thought it might be an interpolation issue, with the first tick being interpolated incorrectly due to a bad back delta set in initialupdate packet.
Now I have something even stranger. Apparently when I load the level as-is and fire at the ground, the explosion happens on the server before the initialUpdate packet goes out.
When I change the visibility range to 2000, suddenly the initialUpdate packet is coming in before the explosion goes off on the server. Just added some basic console output to each event, and can see the order.
Stranger yet, I'm reading the mCurrTick value from the client during initialupdate unpack. At 1000 vis, this packet doesn't get sent until the second tick of the object (tick 1). At 2000 vis, it always goes out during tick 0 (first tick).
Update with possible code solution:
This ended up being way simpler than everything else I considered. It was a solution so simple I'd already thought of it and skipped it. Projectile uses its own internal code for all its physics and position handling, so after each simulate call it has to manually set its own transform for the sake of the rest of the engine being able to call getTransform on it. Only it doesn't do this during onAdd... it just sets mCurrPosition from the "initialPosition" script value and moves on. The result is that, when the server goes to ghost the object during Tick 0 (before the first call to simulate()) it checks its transform and finds it to be at world origin (0,0,0). If your camera object is outside visible range of world origin at the time, it won't ghost you the projectile. You get it during tick 1 (second tick) because during Tick 0 simulate was called and it called setTransform. Aaanyway, the solution (I think).
Put this in your code pipes and... uh... well just try this and see if it fixes the problem.
In projectile.cpp, function
Projectile::onAdd(), I added this right after the call "addToScene();" (near the end of the function):
I figured it made sense that the object shouldn't set its own transform before being added to the scene. Not sure if that matters, but anyway this seems to have fixed the problem, at least in the few minutes of testing I did since rebuilding.
I was still able to stick my gun through walls and fire through them in some cases... but that's another issue related to having a muzzle point outside the Player's bounding box and no good handling for weapon pushback.
08/06/2010 (9:26 pm)
This post is an edited mess. If for some reason you want to read the process I went through to get to the solution, I left most of it intact just for my own reference. Skip to the bold if you want a code fix. =)With the map as downloaded I confirmed the same results. Unlike the original issue with packet rates I was going on about, this was consistant; every rocket fired at my feet caused server explosion with no client ghost.
After I saw the posts where you guys found it was related to the position of the object itself, I scaled the maze object up to 30x and moved it to (0,0,0) so I could test if it was related to the Player's coordinates. Each corner exhibited the effect, while the single-coordinate edges did not (nor did the center).
In the process of this testing, I got irritated with the vis limit set to 1000, so I cranked it up to 5000. Suddenly I couldn't reproduce the issue. Toggling it back and forth while standing on the scaled up maze obj at around (2500,2500,0), at 1000 the explosions always fail to appear. At 5000 they always appear. There's definitely a scoping issue here, but it's something less than obvious.
I'll update this if I figure anything else out.
[Edited] Oookay, now I'm extra confused. I thought it might be an interpolation issue, with the first tick being interpolated incorrectly due to a bad back delta set in initialupdate packet.
Now I have something even stranger. Apparently when I load the level as-is and fire at the ground, the explosion happens on the server before the initialUpdate packet goes out.
When I change the visibility range to 2000, suddenly the initialUpdate packet is coming in before the explosion goes off on the server. Just added some basic console output to each event, and can see the order.
Stranger yet, I'm reading the mCurrTick value from the client during initialupdate unpack. At 1000 vis, this packet doesn't get sent until the second tick of the object (tick 1). At 2000 vis, it always goes out during tick 0 (first tick).
Update with possible code solution:
This ended up being way simpler than everything else I considered. It was a solution so simple I'd already thought of it and skipped it. Projectile uses its own internal code for all its physics and position handling, so after each simulate call it has to manually set its own transform for the sake of the rest of the engine being able to call getTransform on it. Only it doesn't do this during onAdd... it just sets mCurrPosition from the "initialPosition" script value and moves on. The result is that, when the server goes to ghost the object during Tick 0 (before the first call to simulate()) it checks its transform and finds it to be at world origin (0,0,0). If your camera object is outside visible range of world origin at the time, it won't ghost you the projectile. You get it during tick 1 (second tick) because during Tick 0 simulate was called and it called setTransform. Aaanyway, the solution (I think).
Put this in your code pipes and... uh... well just try this and see if it fixes the problem.
In projectile.cpp, function
Projectile::onAdd(), I added this right after the call "addToScene();" (near the end of the function):
MatrixF xform( true ); xform.setColumn( 3, mCurrPosition ); setTransform( xform );
I figured it made sense that the object shouldn't set its own transform before being added to the scene. Not sure if that matters, but anyway this seems to have fixed the problem, at least in the few minutes of testing I did since rebuilding.
I was still able to stick my gun through walls and fire through them in some cases... but that's another issue related to having a muzzle point outside the Player's bounding box and no good handling for weapon pushback.
#28
That post does make sense :)
If I read that correctly then:
The projectile is being set to a world origin of (0,0,0) by the "initialPosition" script on the first tick before the server calls getTransform().
The server only ghosts it to the client if the camera is in view range of (0,0,0) on that tick.
Your fix is to update the projectiles location in "addToScene();" so that the projectile will not pop at (0,0,0) on the first tick but rather at mCurrPosition.
?
:) I hope I understood that correctly ;) and I'll try that fix later if I get the time.
08/07/2010 (12:37 am)
@HenryThat post does make sense :)
If I read that correctly then:
The projectile is being set to a world origin of (0,0,0) by the "initialPosition" script on the first tick before the server calls getTransform().
The server only ghosts it to the client if the camera is in view range of (0,0,0) on that tick.
Your fix is to update the projectiles location in "addToScene();" so that the projectile will not pop at (0,0,0) on the first tick but rather at mCurrPosition.
?
:) I hope I understood that correctly ;) and I'll try that fix later if I get the time.
#29
You got the gist of it. Just to make it extra clear, this is what I think is happening in more detail:
The thing about Projectile is that it has two position variables.
1) The first is its sceneGraph transform, all objects in the scene have to use this method to set and get their transform (position & rotation in matrix form).
2) The Point3F variable mCurrPosition. This is the variable Projectile uses internally when doing its calls to simulate() and basically everything else.
When you create a projectile -- in scripts/server/weapon.cs -- you use the script-side field "initialPosition" to set where it spawns. That script field links to mCurrPosition in the engine.
At this point the server calls Projectile::onAdd(), which adds the object to the scene (addToScene() is called from here, but isn't actually a function in Projectile (it's part of the more generic SceneObject), I was just using that line to reference where the code bit should be added).
Anyway by now mCurrPosition has been set but if some other part of the engine calls getTransform() to see where the Projectile obj is it'll get (0,0,0) because the transform has never been set explicitly by Projectile.
In theory that doesn't matter because you'd expect the next thing to happen would be a call to processTick and then simulate() to do the first physics tick, and simulate calls setTransform() at the end.
Problem is that immediately after onAdd(), the server goes and checks for new ghosts to tell the clients about. Everything at this level gets treated as a generic NetObject, so if it wants to check its position, it's going to use getTransform() and get (0,0,0). So if your camera can't currently "see" the world origin, the server won't bother to tell you about this new projectile.
After this it goes and runs the first call to processTick(), then simulate(), and calls setTransform(). Next tick the projectile will be considered "in scope" b/c getTransform() now returns a valid position. At this point, if you fired at your feet, the projectile has already exploded and it's too late.
Anyway, yeah, my solution is to copy the call to setTransform() from the end of simulate() and pop that into the end of Projectile::onAdd() to make sure there's never a chance for getTransform() to return a blank (0,0,0).
Just for anyone who's curious, I always wondered where ghosting happened. Apparently it's in sim\netGhost.cpp. NetConnection::ghostWritePacket seems like a good place to start tracing things if you're interested in how the server decides what to ghost to which clients at what times. I got tired of trying to trace this whole setup, but still good to know where these things happen. =)
08/07/2010 (1:33 am)
@AaronYou got the gist of it. Just to make it extra clear, this is what I think is happening in more detail:
The thing about Projectile is that it has two position variables.
1) The first is its sceneGraph transform, all objects in the scene have to use this method to set and get their transform (position & rotation in matrix form).
2) The Point3F variable mCurrPosition. This is the variable Projectile uses internally when doing its calls to simulate() and basically everything else.
When you create a projectile -- in scripts/server/weapon.cs -- you use the script-side field "initialPosition" to set where it spawns. That script field links to mCurrPosition in the engine.
At this point the server calls Projectile::onAdd(), which adds the object to the scene (addToScene() is called from here, but isn't actually a function in Projectile (it's part of the more generic SceneObject), I was just using that line to reference where the code bit should be added).
Anyway by now mCurrPosition has been set but if some other part of the engine calls getTransform() to see where the Projectile obj is it'll get (0,0,0) because the transform has never been set explicitly by Projectile.
In theory that doesn't matter because you'd expect the next thing to happen would be a call to processTick and then simulate() to do the first physics tick, and simulate calls setTransform() at the end.
Problem is that immediately after onAdd(), the server goes and checks for new ghosts to tell the clients about. Everything at this level gets treated as a generic NetObject, so if it wants to check its position, it's going to use getTransform() and get (0,0,0). So if your camera can't currently "see" the world origin, the server won't bother to tell you about this new projectile.
After this it goes and runs the first call to processTick(), then simulate(), and calls setTransform(). Next tick the projectile will be considered "in scope" b/c getTransform() now returns a valid position. At this point, if you fired at your feet, the projectile has already exploded and it's too late.
Anyway, yeah, my solution is to copy the call to setTransform() from the end of simulate() and pop that into the end of Projectile::onAdd() to make sure there's never a chance for getTransform() to return a blank (0,0,0).
Just for anyone who's curious, I always wondered where ghosting happened. Apparently it's in sim\netGhost.cpp. NetConnection::ghostWritePacket seems like a good place to start tracing things if you're interested in how the server decides what to ghost to which clients at what times. I got tired of trying to trace this whole setup, but still good to know where these things happen. =)
#30
08/07/2010 (9:22 am)
Henry Todd, I believe you have finally solved a problem which has been plaguing torque since, well forever. nice work!
#31
It looks like anything under 1500 gives this issue at the maze's default position - which is about 1500 from origin in LOS!
Also, has anyone noticed that the lighting changes depending on view distance? (you probably won't with my maze - as I didn't include the textures, but if you stick some on in the material editor, you'll see what I'm talking about).
Well done Mr Todd.
08/07/2010 (12:45 pm)
Gah! I missed the viewDistance link - even though I'd altered it to 10K when moving my maze to a new position ...It looks like anything under 1500 gives this issue at the maze's default position - which is about 1500 from origin in LOS!
Also, has anyone noticed that the lighting changes depending on view distance? (you probably won't with my maze - as I didn't include the textures, but if you stick some on in the material editor, you'll see what I'm talking about).
Well done Mr Todd.
#32
08/07/2010 (1:22 pm)
hmm didn't work for me, still getting the problem. Here's where I added it... (projectile.cpp)// Setup our bounding box
if (bool(mDataBlock->projectileShape) == true)
mObjBox = mDataBlock->projectileShape->bounds;
else
mObjBox = Box3F(Point3F(0, 0, 0), Point3F(0, 0, 0));
resetWorldBox();
addToScene();
MatrixF xform( true ); // henry todd fix
xform.setColumn( 3, mCurrPosition ); // henry todd fix
setTransform( xform ); // henry todd fix
if ( PHYSICSMGR )
mPhysicsWorld = PHYSICSMGR->getWorld( isServerObject() ? "server" : "client" );
return true;
}
#33
Seems to work great, Henry - even with visdistance set to a mere 10! :)
08/07/2010 (1:37 pm)
Julian, try before it gets added to the scene, not just after.// Setup our bounding box
if (bool(mDataBlock->projectileShape) == true)
mObjBox = mDataBlock->projectileShape->bounds;
else
mObjBox = Box3F(Point3F(0, 0, 0), Point3F(0, 0, 0));
MatrixF xform( true );//yorks start - bug fix for non-rendering projectiles
xform.setColumn( 3, mCurrPosition );
setTransform( xform );//yorks end
resetWorldBox();
addToScene();Seems to work great, Henry - even with visdistance set to a mere 10! :)
#34
Projectile::onAdd(), I added this right after the call "addToScene();" (near the end of the function): - might want to change it a bit :)
08/07/2010 (1:52 pm)
@Steve - no didn't work.Projectile::onAdd(), I added this right after the call "addToScene();" (near the end of the function): - might want to change it a bit :)
#35
Henry, not to be inpolite or whatever, but have you got the crouching to work yet? I don't want to spam you with PMs you know :D.
08/07/2010 (2:00 pm)
Thanks Henry, worked perfectly, but only if i change $pref::Net::PacketRateToClient = "32". Not sure what the cons are for changing the PacketRate, but after what you explained earlier it seems to be ok.Henry, not to be inpolite or whatever, but have you got the crouching to work yet? I don't want to spam you with PMs you know :D.
#36
08/07/2010 (2:07 pm)
Actually Julian, placing it after addToScene works for me too.
#37
08/07/2010 (2:19 pm)
Doesn't work for me Steve... I'll apply the same as Marcus and see if it works. Although hopefully applying 32 will not cause me too many bandwidth issues :)
#38
I already have set $pref::Net::PacketRateToClient = "32" since I believe there is a valid sync issue with short lived projectiles and not getting a packet to the client every tick.
Always glad to see a nice simple solution to a frustrating problem :)
08/07/2010 (2:34 pm)
Indeed that fix works nicely for me as well.I already have set $pref::Net::PacketRateToClient = "32" since I believe there is a valid sync issue with short lived projectiles and not getting a packet to the client every tick.
Always glad to see a nice simple solution to a frustrating problem :)
#39
08/07/2010 (2:36 pm)
Just gotta remember not to clear down the prefs batch file, but doesn't that store info about your graphics card, so when the end user gets a prefs file already it may cause issues? Probably worth putting the $pref::Net::PacketRateToClient = "32" in core/scripts/client/defaults.cs as scripts/client/prefs.cs could easily get wiped, and when you come to package up the game, you don't want anything about your own graphics card in there.
#40
08/07/2010 (2:47 pm)
For me, it's still there, after applying both fixes.. if you try shooting from the ground up and move your weapon higher each time, there is an area where no projectile makes an impact and no decals show.
Associate Steve Acaster
[YorkshireRifles.com]
But guess what! You did just give me an idea.
Remember those old Torque maps ... the ones where the terrain was always at "-1024 -1024 0" (or soemthing like that anyhow) rather than "0 0 0"?
no ... cos your IDtag says you joined in april 2010
... but anyway, back in the TGE/A days ... I always wondered why they didn't just stick the terrain/mesh at "0 0 0", but got into the habit of copying what I saw ... but since have got out of that habit ...
... so just as a test I moved my mesh in that same map from "+1000 + 1000 +500" (or whatever it) was to "-1024 -1024 0" ... and no problems!
[edit]
And just moving it to "0 0 0" works fine too.
On the "old Torque maps" used to be "-1024 etc", I always figured it was becaue torque placed the corner of the terrain at it's position rather than the centre --- and so the centre of the map/terrain was always at "0 0 0".
[edit part deux]
So, just as another test, I have this 2000 unit/metre map placed at "0 0 0", collision good near the corner at 0 0 0, no visible projectiles at the other corners. Moving it to "-1024 -1024 0" - so the centre is over 0 0 0 - and projectiles are rendering on all 4 four corners okay.