Callback errors, strange behavior
-
- Posts: 5
- Joined: Tue Nov 09, 2010 4:34 am
- Contact:
Callback errors, strange behavior
I have some strange behavior with the collision callbacks....
I am trying to replace object A with object B when object A passes through a sensor. I have tried setting up post step callbacks, however the weird thing is, it triggers another "COLLISION_SEPERATE" moment. The poststep callback creates a new body with the coordinates of object A, and recreates the shape based on object B specs (stored outside). Then another collision occurs with "COLLISION_SEPERATE", without ever a matching COLLISION_BEGIN. Another callback occurs and it crashes trying to work with an already released object.
Any ideas?! Anybody tried replacing one object with another?
I am trying to replace object A with object B when object A passes through a sensor. I have tried setting up post step callbacks, however the weird thing is, it triggers another "COLLISION_SEPERATE" moment. The poststep callback creates a new body with the coordinates of object A, and recreates the shape based on object B specs (stored outside). Then another collision occurs with "COLLISION_SEPERATE", without ever a matching COLLISION_BEGIN. Another callback occurs and it crashes trying to work with an already released object.
Any ideas?! Anybody tried replacing one object with another?
- slembcke
- Site Admin
- Posts: 4166
- Joined: Tue Aug 14, 2007 7:13 pm
- Contact:
Re: Callback errors, strange behavior
Not quite sure I follow. It might be the case where you need to be very careful about the ordering of your calls.
The relevant parts of cpSpaceStep() work like this:
1) All collisions are detected, begin and pre-solve are called on each pair as collisions are found.
2) The cached collisions are checked, separate is called for any collision that happened last step but not this step.
3) Collisions are solved.
4) Run the post-solve callbacks.
5) Run the post-step callbacks.
Additionally, when you remove an object from the space, it immediately calls separate callbacks for all the shapes it was touching. This means that when you remove the object within the post-step callback it's calling the separate callback which you might not have been expecting.
Posting some code snippets might help.
The relevant parts of cpSpaceStep() work like this:
1) All collisions are detected, begin and pre-solve are called on each pair as collisions are found.
2) The cached collisions are checked, separate is called for any collision that happened last step but not this step.
3) Collisions are solved.
4) Run the post-solve callbacks.
5) Run the post-step callbacks.
Additionally, when you remove an object from the space, it immediately calls separate callbacks for all the shapes it was touching. This means that when you remove the object within the post-step callback it's calling the separate callback which you might not have been expecting.
Posting some code snippets might help.
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
-
- Posts: 5
- Joined: Tue Nov 09, 2010 4:34 am
- Contact:
Re: Callback errors, strange behavior
Aha! Yes the collision_seperate call i did not expect. The problem is I want to schedule the shape removal from the collision_seperate case, so it gets called again and crashes. I have added a check for shape->body->shape == nil, which solves the problem, but is there a better way to handle this? Or could some functionality be added to chipmunk?
In my program, widgets (collision types 1,2,3,...) move around and collide with triggerZones (collision type 9999). All those collisions are routed through one function, which uses performselector() to call the appropriate function on a triggerZone's owner.
triggerZone interface:
The routing function:
In my program, widgets (collision types 1,2,3,...) move around and collide with triggerZones (collision type 9999). All those collisions are routed through one function, which uses performselector() to call the appropriate function on a triggerZone's owner.
triggerZone interface:
Code: Select all
@interface TriggerZone : NSObject {
CGFloat zoneWidth;
CGFloat zoneHeight;
cpVect triggerZoneOffset;
id owner;
SEL sensorFuncBegin;
SEL sensorFuncPresolve;
SEL sensorFuncPostsolve;
SEL sensorFuncSeperate;
int zoneID;
}
Code: Select all
// all triggerzone<->widget collisions route through here
- (BOOL) handleTriggerZoneCollision:(CollisionMoment)moment arbiter:(cpArbiter*)arb space:(cpSpace*)space
{
//NSLog(@"Routing triggerzone collision...");
CP_ARBITER_GET_SHAPES(arb, triggerSensorShape, widgetShape);
WidgetTemplate *widget = widgetShape->body->data;
TriggerZone *triggerZone = triggerSensorShape->body->data;
NSLog(@"Routing triggerzone collision... widget has position %f,%f arb timestamp=%d zoneID=%d widget has type=%d key=%@", widgetShape->body->p.x, widgetShape->body->p.y, arb->stamp, triggerZone.zoneID, widget.collision_type, widget.key);
switch(moment)
{
case COLLISION_BEGIN:
NSLog(@"COLLISION_BEGIN");
if (triggerZone.sensorFuncBegin != nil) {
[triggerZone.owner performSelector:triggerZone.sensorFuncBegin withObject:widgetShape];
}
break;
case COLLISION_PRESOLVE:
NSLog(@"COLLISION PRESOLVE");
if (triggerZone.sensorFuncPresolve != nil) {
[triggerZone.owner performSelector:triggerZone.sensorFuncPresolve withObject:widgetShape];
}
break;
case COLLISION_POSTSOLVE:
NSLog(@"POSTSOLVE");
if (triggerZone.sensorFuncPostsolve != nil) {
[triggerZone.owner performSelector:triggerZone.sensorFuncPostsolve withObject:widgetShape];
}
break;
case COLLISION_SEPARATE: // why is this called twice?!
NSLog(@"COLLISION SEPERATE");
if (triggerZone.sensorFuncSeperate != nil && widgetShape->body->space != NULL) {
[triggerZone.owner performSelector:triggerZone.sensorFuncSeperate withObject:widgetShape];
}
break;
}
return YES;
}
- slembcke
- Site Admin
- Posts: 4166
- Joined: Tue Aug 14, 2007 7:13 pm
- Contact:
Re: Callback errors, strange behavior
It sounds like you need to be setting a boolean on your widgets. Removing objects from separate callbacks can get sticky as you've seen. There isn't really a consistent thing that Chipmunk can do to cover all the possibilities to fix the situation.
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
-
- Posts: 5
- Joined: Tue Nov 09, 2010 4:34 am
- Contact:
Re: Callback errors, strange behavior
It seems the space==null check is not enough. I still get crashes after 5-10 widgets pass through the transformer. I don't currently track each gameobject so i am considering adding that to the code.
After thinking about what happens in a collision_seperate...
Is this supposed to happen?
After thinking about what happens in a collision_seperate...
Yet if the shape removal was trigger from a collision_seperate, it -shouldn't- have been touching any shapes... at least any that matter. (the triggerzone)Additionally, when you remove an object from the space, it immediately calls separate callbacks for all the shapes it was touching. This means that when you remove the object within the post-step callback it's calling the separate callback which you might not have been expecting.
Is this supposed to happen?
- slembcke
- Site Admin
- Posts: 4166
- Joined: Tue Aug 14, 2007 7:13 pm
- Contact:
Re: Callback errors, strange behavior
Are you sure it's only touching one shape or sensor at a time? It would be a pretty serious bug if Chipmunk was calling separate for the same shape pair more than once. Keep in mind that the collision events work on the level of shapes. If a body has multiple shapes each shape gets it's own events, even if they are marked with the same collision_type.
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
-
- Posts: 5
- Joined: Tue Nov 09, 2010 4:34 am
- Contact:
Re: Callback errors, strange behavior
Currently the setup is very simple.... I drop the widget in from above. (Widgets have 1 shape) It falls onto a conveyor belt shape, which generates no collisions and uses surface velocity to move the widget. A transformer has one triggerzone.
Heres a log of just before the crash.
I'm trying to step through the chipmunk code but I don't really understand whats going on.
Heres a log of just before the crash.
Code: Select all
2010-11-10 10:36:25.337 cocosFactory[24715:207] Routing triggerzone collision... widget has position 140.693130,255.399933 arb timestamp=1551 zoneID=0 widget has type=1 key=red
2010-11-10 10:36:25.338 cocosFactory[24715:207] COLLISION SEPERATE
2010-11-10 10:36:25.340 cocosFactory[24715:207] transformer event for shape
2010-11-10 10:36:25.342 cocosFactory[24715:207] postStepRemoveAndAdd
2010-11-10 10:36:25.343 cocosFactory[24715:207] Routing triggerzone collision... widget has position 140.693130,255.399933 arb timestamp=1551 zoneID=0 widget has type=1 key=red
2010-11-10 10:36:25.344 cocosFactory[24715:207] COLLISION SEPERATE
2010-11-10 10:36:25.346 cocosFactory[24715:207] transformer event for shape
- slembcke
- Site Admin
- Posts: 4166
- Joined: Tue Aug 14, 2007 7:13 pm
- Contact:
Re: Callback errors, strange behavior
You should also log the values of the triggerSensorShape and widgetShape pointers. They should be different.
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
- slembcke
- Site Admin
- Posts: 4166
- Joined: Tue Aug 14, 2007 7:13 pm
- Contact:
Re: Callback errors, strange behavior
Actually, that got me thinking that there are actually two code paths that call separate, and it looks like there is a bug in one of them after all.
Search for contactSetFilterRemovedShape in cpSpace.c. Change this line:
To This:
I didn't make a test case to try it out, but I'm pretty certain that should fix the problem. Let me know if it works and I'll commit it to trunk and release it with 5.3.3.
After calling separate, the arbiter (collision pair) goes into a cached state where it might exist for a few frames longer if the collision happens again. Removing a shape was calling the separate callback on all arbiters for that shape, even cached ones which had already called separate.
Search for contactSetFilterRemovedShape in cpSpace.c. Change this line:
Code: Select all
arb->handler->separate(arb, context->space, arb->handler->data);
Code: Select all
if(arb->state != cpArbiterStateCached){
arb->handler->separate(arb, context->space, arb->handler->data);
}
After calling separate, the arbiter (collision pair) goes into a cached state where it might exist for a few frames longer if the collision happens again. Removing a shape was calling the separate callback on all arbiters for that shape, even cached ones which had already called separate.
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
-
- Posts: 5
- Joined: Tue Nov 09, 2010 4:34 am
- Contact:
Re: Callback errors, strange behavior
Woohoo! Yeah that solved the problem. I no longer get the duplicate collision_seperate.
Who is online
Users browsing this forum: No registered users and 34 guests