Contact event never returns true [SOLVED]

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
jaja1
Posts: 43
Joined: Sat Nov 15, 2014 3:27 am

Contact event never returns true [SOLVED]

Post by jaja1 »

Basically I am trying to implement an attack system where a player is attacking a monster (based on input) and the player's collider is in contact with the monster's.
I checked the positions of both colliders in the space and they are close enough. I made the player's collider ridiculously large so that it should always touch the monster's own even from afar, but the event still fails to trigger. Not even the log is called in the delegate method so I know its not the tags that are the issue.
Heres the code:

Code: Select all

//checks for collision between a player and any other entity
        public bool CheckPlayerAttack()
        {
            playerAttacker.extendedCollider.CollisionInformation.Events.CreatingContact -= PlayerAttacked;
            PhysicsLog(applyCollision.ToString());
            return applyCollision;
        }

        //called if the player and monster-entity-requested-to-be-attacked are colliding in the physics map
        void PlayerAttacked(EntityCollidable sender, Collidable other, CollidablePairHandler pair, Contact contact)
        {
            PhysicsLog("player has collided with an entity while calling an attack request");
            if (other.Tag.ToString() == "[MONSTER] [body] " + monsterInstance)
            {
                PhysicsLog("the entity is a monster type based on its tag");
                applyCollision = true;
            }
        }
Any ideas?

EDIT: -= PlayerAttacked was just something I was trying because I really wasn't sure what to do :roll: ....but I previously had += PlayerAttacked and that failed too.
Last edited by jaja1 on Sat Nov 22, 2014 4:35 pm, edited 1 time in total.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Contact event never returns true

Post by Norbo »

Make sure that the objects are in the space, the space is being updated, the objects are definitely colliding, and they are capable of undergoing collision detection.

To elaborate on that last point: two objects can intersect but not generate any contacts if their collision rules are configured to stop collision detection. By default, kinematic and static objects belong to a collision group which does not collide with itself because static and kinematic objects do not move in response to collision. If at least one of the objects in the collision pair is dynamic, the default collision rules will permit collision detection. You can also change collision rules. Check the collision rules documentation for more information.
jaja1
Posts: 43
Joined: Sat Nov 15, 2014 3:27 am

Re: Contact event never returns true

Post by jaja1 »

Alright I checked everything. Now I have a new problem. When I send an attack request even while near the enemy the collision check returns false. Here's my log file:

Code: Select all

(11/21/2014 10:13:45 AM): False
(11/21/2014 10:13:48 AM): player has collided with an entity while calling an attack request
(11/21/2014 10:13:48 AM): player has collided with an entity while calling an attack request
(11/21/2014 10:13:48 AM): player has collided with an entity while calling an attack request
(11/21/2014 10:13:48 AM): player has collided with an entity while calling an attack request
(11/21/2014 10:13:48 AM): player has collided with an entity while calling an attack request
(11/21/2014 10:13:48 AM): player has collided with an entity while calling an attack request
(11/21/2014 10:13:49 AM): player has collided with an entity while calling an attack request
(11/21/2014 10:13:49 AM): player has collided with an entity while calling an attack request
(11/21/2014 10:13:49 AM): player has collided with an entity while calling an attack request
(11/21/2014 10:13:49 AM): player has collided with an entity while calling an attack request
(11/21/2014 10:13:49 AM): player has collided with an entity while calling an attack request
(11/21/2014 10:13:49 AM): player has collided with an entity while calling an attack request
(11/21/2014 10:13:49 AM): player has collided with an entity while calling an attack request
(11/21/2014 10:13:49 AM): player has collided with an entity while calling an attack request
(11/21/2014 10:13:49 AM): player has collided with an entity while calling an attack request
(11/21/2014 10:13:49 AM): player has collided with an entity while calling an attack request
(11/21/2014 10:13:49 AM): player has collided with an entity while calling an attack request
(11/21/2014 10:13:49 AM): player has collided with an entity while calling an attack request
(11/21/2014 10:13:49 AM): player has collided with an entity while calling an attack request
(11/21/2014 10:13:49 AM): player has collided with an entity while calling an attack request
(11/21/2014 10:13:49 AM): player has collided with an entity while calling an attack request
(11/21/2014 10:13:49 AM): player has collided with an entity while calling an attack request
(11/21/2014 10:13:49 AM): player has collided with an entity while calling an attack request

After I begin to move as you can see the collision works, and the event continues to be fired constantly as long as I am moving (meaning the players weapon collider is moving). I'm not sure if this has to do with the player's body collider interfering with its weapon collider or if its actually detecting contact with the enemy collider. They are all separate entities.

This is the rest of my code:

Code: Select all

 
        //runs once every frame
        public static Timer updateFrame = new Timer(16);
        public static void Update(object sender, EventArgs e)
        {
            VandelliaPhysicsMap.Update();
        }

       //checks for collision between a player and any other entity
        public bool CheckPlayerAttack()
        {
            playerAttacker.extendedCollider.CollisionInformation.Events.ContactCreated += PlayerAttacked;
            PhysicsLog(applyCollision.ToString());
            return applyCollision;
        }

        //called if the player and monster-entity-requested-to-be-attacked are colliding in the physics map
        void PlayerAttacked(EntityCollidable sender, Collidable other, CollidablePairHandler pair, ContactData contact)
        {
            PhysicsLog("player has collided with an entity while calling an attack request");
            PhysicsLog(other.Tag.ToString());
            if (other.Tag.ToString() == "[MONSTER] [body] " + monsterInstance)
            {
                PhysicsLog("the entity is a monster type based on its tag");
                applyCollision = true;
            }
        }
The update function timer is started when the server starts up. I assumed it would be appropriate to update 60 times per second hence why I used a timer that triggers every 16 ticks. I also tried using other contact events, but all of them gave the same result. Some events don't work at all (such as PairCreated and CreatingPair). Also note in my log file the tag on the 'other' entity is not even being logged...why? I know for sure both entities' tags should not be empty and are in the same space. Let me know if there's anything else I'm doing wrong thanks.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Contact event never returns true

Post by Norbo »

A few things:
1) ContactCreated only fires when a contact gets created. If a collision reaches a steady state and contacts aren't being created anymore, it will not fire. It's not a good candidate for querying contact state.
2) Present tense names like CreatingContact are executed on the engine's threads in the middle of the collision handler. So, if multithreading is being used, these "immediate" mode events require great care to avoid shared data access. In other words, unless there is a very strong reason to be running the code within the engine's scope, use the deferred (past-tense names) collision events like ContactCreated instead.
3) Don't add a subscriber to an event multiple times unless you want to receive multiple notifications for the same event. Right now, it looks like it just appends another subscriber whenever that query is called and none are ever removed.
4) The "other" in the collision is not an Entity, it is a Collidable. An Entity has a Collidable (stored in the Entity.CollisionInformation property) that acts as its collision proxy. If you want to check if a particular collidable is associated with an entity, try casting it to an EntityCollidable and using its Entity property. Note that the Tag property of an Entity and the tag property of its associated Collidable are separate. You can set different values in the Entity.Tag and Entity.CollisionInformation.Tag. The EntityConstructionDemo goes into more detail on the Entity-Collidable-Shape distinction.
5) Note that CheckPlayerAttack will only return the previous state of applyCollision. It won't wait for the space update to execute to get up-to-date information. Additionally, in the given code, applyCollision is never set to false. If that is representative, then CheckPlayerAttack would never return false after one collision.
6) Collision state can be directly queried by using the Entity.CollisionInformation.Pairs list. Each pair has a list of contacts, properties representing the involved objects, and a Colliding property which returns true if the pair has any nonnegative depth contacts. Checking this data directly tends to be much more natural than using events to query collision state.
Post Reply