Objective c Box2D-b2body GetUserData始终返回null

Objective c Box2D-b2body GetUserData始终返回null,objective-c,box2d,Objective C,Box2d,我试图根据box2d中b2body的位置和旋转来调整精灵的位置和旋转 在我创建了body im之后,将userData属性设置为我的body对象的属性,该对象包含精灵和位置等。问题是,在勾选方法b->GetUserData中,从未检索到我放入其中的对象。你能看出下面的错误吗 以下是我的添加播放器方法: -(void) addPlayerShip { CCSpriteSheet *sheet = [CCSpriteSheet spriteSheetWithFile:@"PlayerShip

我试图根据box2d中b2body的位置和旋转来调整精灵的位置和旋转

在我创建了body im之后,将userData属性设置为我的body对象的属性,该对象包含精灵和位置等。问题是,在勾选方法b->GetUserData中,从未检索到我放入其中的对象。你能看出下面的错误吗

以下是我的添加播放器方法:

-(void) addPlayerShip
{
    CCSpriteSheet *sheet = [CCSpriteSheet spriteSheetWithFile:@"PlayerShip.png" capacity:1];

    //Get sprite sheet
    CCSprite *sprite = [CCSprite spriteWithSpriteSheet:sheet rect:CGRectMake(0,0,64,64)];
    [sheet addChild:sprite];

    CGSize screenSize = [CCDirector sharedDirector].winSize;

    sprite.position = ccp( screenSize.width/2, screenSize.height/2);

    [self addChild:sheet];

    // Define the dynamic body.
    b2BodyDef bodyDef;
    bodyDef.type = b2_dynamicBody;
    bodyDef.position.Set(sprite.position.x/PTM_RATIO, sprite.position.y /PTM_RATIO);
    bodyDef.angularVelocity=0;

    b2Body *body = world->CreateBody(&bodyDef);

    b2PolygonShape dynamicTriangle;

    dynamicTriangle.m_vertexCount=3;
    dynamicTriangle.m_vertices[0].Set(0,-1);
    dynamicTriangle.m_vertices[1].Set(1,1);
    dynamicTriangle.m_vertices[2].Set(-1,1);

    // Define the dynamic body fixture.
    b2FixtureDef fixtureDef;
    fixtureDef.shape = &dynamicTriangle;
    fixtureDef.density = 1.0f;
    fixtureDef.friction = 0.0f;
    fixtureDef.restitution=0.0f;

    b2Fixture *fixture = body->CreateFixture(&fixtureDef);

    b2Vec2 *vector = new b2Vec2;

    BodyObject *bodyObject = [[BodyObject alloc] initWithBody:body 
                                                   andFixture:fixture 
                                                  andVelocity:vector 
                                                    andSprite:sprite];


    bodyDef.userData = bodyObject;
}
以及在b->GetUserData上始终返回null的tick方法

-(void) tick: (ccTime) dt
{
    int32 velocityIterations = 8;
    int32 positionIterations = 1;

    world->Step(dt, velocityIterations, positionIterations);

    //Iterate over the bodies in the physics world
    for (b2Body* b = world->GetBodyList(); b; b = b->GetNext())
    {
        if (b->GetUserData() != NULL) {
            //Synchronize the Sprites position and rotation with the corresponding body
            GameObject *myObject = (GameObject*)b->GetUserData();
            myObject.Sprite.position = CGPointMake( b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO);
            myObject.Sprite.rotation = -1 * CC_RADIANS_TO_DEGREES(b->GetAngle());
        }   
    }
}
最后是bodyObject

#import "BodyObject.h"


@implementation BodyObject

@synthesize Body;
@synthesize Fixture;

-(id) initWithBody:(b2Body*) body 
        andFixture:(b2Fixture*) fixture 
       andVelocity:(b2Vec2*) velocity 
         andSprite:(CCSprite*) sprite
{
    self = [super initWithSprite:(CCSprite*)sprite 
                     andVelocity:(b2Vec2*)velocity];

    self.Body=body;
    self.Fixture=fixture;

    return self;
}

@end
我是c目标的新手,所以如果我做错了什么,请告诉我

编辑: 我在这里尝试了另一段代码,我似乎能够做得更进一步

if I set bodyDef.UserData = sprite; 
排队后

bodyDef.position.Set(sprite.position.x/PTM_RATIO, sprite.position.y /PTM_RATIO); 
然后GetUserData返回精灵。但是,如果我在addPlayerShip方法的末尾将用户数据设置为精灵,那么它将再次返回ns null。精灵/身体对象是否在某个地方被处理?

在调用CreateBody()之后,您将用户数据分配给bodyDef,因此它永远不会被添加到实际身体中

b2BodyDef是一个结构,它保存用于创建实体的设置。调用CreateBody()后,对该结构的更改将无效

通过移动bodyDef.UserData=sprite,您自己找到了解决方案;调用CreateBody()之前的某个位置的行。这是放置它的正确位置。如果您认为出于某种原因(其他变量?)需要在函数末尾使用它,那么您需要重构代码,以避免出现这种情况

我将更改此行(以及BodyObject类):

这样,您就可以在不需要box2d元素的情况下(即在定义它们之前)对其进行实例化,然后在创建这些元素后使用属性来分配这些值。通过这种方式,您可以将此对象作为主体的用户数据传递,创建主体,然后使用
[bodyObject setBody:body]分配b2Body*

不要忘记确保身体和固定装置属性是只读的

最终的代码可能如下所示:

-(void) addPlayerShip
{
    CCSpriteSheet *sheet = [CCSpriteSheet spriteSheetWithFile:@"PlayerShip.png" capacity:1];

    //Get sprite sheet
    CCSprite *sprite = [CCSprite spriteWithSpriteSheet:sheet rect:CGRectMake(0,0,64,64)];
    [sheet addChild:sprite];

    CGSize screenSize = [CCDirector sharedDirector].winSize;

    sprite.position = ccp( screenSize.width/2, screenSize.height/2);

    [self addChild:sheet];

    b2Vec2 *vector = new b2Vec2;

    BodyObject *bodyObject = [[BodyObject alloc] initWithSprite:sprite 
                                                   andVelocity:vector];

    //MOVES THE BODY DEFINITION AFTER THE BODYOBJECT DEFINITION
    // Define the dynamic body.
    b2BodyDef bodyDef;
    bodyDef.type = b2_dynamicBody;
    bodyDef.position.Set(sprite.position.x/PTM_RATIO, sprite.position.y /PTM_RATIO);
    bodyDef.angularVelocity=0;
    bodyDef.userData = bodyObject;

    b2Body *body = world->CreateBody(&bodyDef);

    b2PolygonShape dynamicTriangle;

    dynamicTriangle.m_vertexCount=3;
    dynamicTriangle.m_vertices[0].Set(0,-1);
    dynamicTriangle.m_vertices[1].Set(1,1);
    dynamicTriangle.m_vertices[2].Set(-1,1);

    // Define the dynamic body fixture.
    b2FixtureDef fixtureDef;
    fixtureDef.shape = &dynamicTriangle;
    fixtureDef.density = 1.0f;
    fixtureDef.friction = 0.0f;
    fixtureDef.restitution=0.0f;

    b2Fixture *fixture = body->CreateFixture(&fixtureDef);

    [bodyObject setBody:body];
    [bodyObject setFixture:fixture];
}
#import "BodyObject.h"


@implementation BodyObject

@synthesize Body;
@synthesize Fixture;

-(id) initWithSprite:(CCSprite*) sprite 
       andVelocity:(b2Vec2*) velocity 
{
    self = [super initWithSprite:(CCSprite*)sprite 
                     andVelocity:(b2Vec2*)velocity];

    return self;
}

@end
bodyObject类的外观如下所示:

-(void) addPlayerShip
{
    CCSpriteSheet *sheet = [CCSpriteSheet spriteSheetWithFile:@"PlayerShip.png" capacity:1];

    //Get sprite sheet
    CCSprite *sprite = [CCSprite spriteWithSpriteSheet:sheet rect:CGRectMake(0,0,64,64)];
    [sheet addChild:sprite];

    CGSize screenSize = [CCDirector sharedDirector].winSize;

    sprite.position = ccp( screenSize.width/2, screenSize.height/2);

    [self addChild:sheet];

    b2Vec2 *vector = new b2Vec2;

    BodyObject *bodyObject = [[BodyObject alloc] initWithSprite:sprite 
                                                   andVelocity:vector];

    //MOVES THE BODY DEFINITION AFTER THE BODYOBJECT DEFINITION
    // Define the dynamic body.
    b2BodyDef bodyDef;
    bodyDef.type = b2_dynamicBody;
    bodyDef.position.Set(sprite.position.x/PTM_RATIO, sprite.position.y /PTM_RATIO);
    bodyDef.angularVelocity=0;
    bodyDef.userData = bodyObject;

    b2Body *body = world->CreateBody(&bodyDef);

    b2PolygonShape dynamicTriangle;

    dynamicTriangle.m_vertexCount=3;
    dynamicTriangle.m_vertices[0].Set(0,-1);
    dynamicTriangle.m_vertices[1].Set(1,1);
    dynamicTriangle.m_vertices[2].Set(-1,1);

    // Define the dynamic body fixture.
    b2FixtureDef fixtureDef;
    fixtureDef.shape = &dynamicTriangle;
    fixtureDef.density = 1.0f;
    fixtureDef.friction = 0.0f;
    fixtureDef.restitution=0.0f;

    b2Fixture *fixture = body->CreateFixture(&fixtureDef);

    [bodyObject setBody:body];
    [bodyObject setFixture:fixture];
}
#import "BodyObject.h"


@implementation BodyObject

@synthesize Body;
@synthesize Fixture;

-(id) initWithSprite:(CCSprite*) sprite 
       andVelocity:(b2Vec2*) velocity 
{
    self = [super initWithSprite:(CCSprite*)sprite 
                     andVelocity:(b2Vec2*)velocity];

    return self;
}

@end

如果任何人有相同的问题,则GetUserData()返回null,即使您设置了UserData。
那么请不要犯我的错误,假设b2World.QueryShape()在回调中提供了实体。不,它给你固定装置。您必须fixture.GetBody().GetUserData()(我的案例是:javascript中的box2dweb;这是我在谷歌上搜索的问题,我想其他人也会这么做)

嗨,Badgerr,这很有意义。我不知道BodyDef是一个结构。我可以假设fixture def也是一个结构吗?如何区分objective-c和box2d中的类和结构?或者只是参考文档的一种情况所以,如果它是一个结构,我需要先设置所有属性,以后不能更改它们,如果它是一个类,以后使用它们也是一样的吗?我稍后再试试,我可能今晚才有时间,但这看起来像是解决方案,所以当我让它工作时,我会标记为答案。谢谢你的详细解释。你不必设置所有的值。b2BodyDef有一个设置默认值的构造函数。在这个特定实例中,类和结构之间的区别并不太重要。为了达到这个目的,他们也会采取同样的行动。查看b2BodyDef的定义或box2d文档,将显示哪些是用class定义的,哪些是用struct定义的。请记住,b2*def结构是定义,因此在将任何成员传递到Create*()函数后更改这些成员将不会产生任何效果。感谢bardgerr,这很有效。我已经更改了BodyObject和GameObject类,以接受一个精灵作为唯一的参数。我注意到您正在使用[bodyObject setFixture];设置属性。这是objective-c推荐的方式吗(我习惯于.Net)。我也尝试过同样的bodydef,但它似乎不支持它。我以后会尝试你的方法来设置属性,如果set方法不存在,我想它可能是一个结构,也可能不是一个类(或者在属性上有私有setter)。你的类中的Body和Fixture值被定义为@property,当你@synthesis它们时,它会自动为你生成getter和setter。hi@badgerr,请参考此链接,