I use a stripped down character controller for each of my enemies. It works great. The enemies interact with the static mesh, I can shoot them, I keep track of who is hit and I deactivate them when they die, I can even push them around with my player character controller. They also never occupy the same space.
You can see this behavior in this video: http://youtu.be/slfhOZLJMC4
The problem is I want to be more accurate with my shooting. I want to know if they were shot in the head, torso, leg etc. To that end, I have added a sphere at each of the major bones. The problems I am getting are logical. They are interacting with each other and the controller cylinder. I made them unaffected by gravity to get them to behave somewhat better and allow the enemy to rest on the terrain.
In this video you can see the spheres attached to the major bones: http://youtu.be/6YlwKCCnTnI
I need the spheres to not interact with each other or any other object, but I want to be able to RayCast against them. I also need to know which sphere is associated with which enemy. I currently store the enemy class in the controller tag. Presumably I will need to store a reference in each sphere tag.
Any help would be very much appreciated.
How to shoot an enemy's head
How to shoot an enemy's head
BEPUphysics rules my world
http://cloneofduty.com
http://cloneofduty.com
Re: How to shoot an enemy's head
Collision rules will do the trick. You could put them all in a collision group which interacts with nothing (not even itself). There's a CollisionFilteringDemo showing their use. Collision rules do not affect ray casting, so they'll all still be hit.I need the spheres to not interact with each other or any other object, but I want to be able to RayCast against them.
The spheres also might as well be kinematic since they're just being teleported around and can't interact with anything. That will prevent gravity or other forces from moving them.
Performance-wise, having dozens of entities associated with every character may be a bit expensive. Even though they don't collide with anything, they will pollute the broad phase. If it becomes a problem, the body objects could be kept out of the space and tested only when the character controller body gets hit. You do lose the acceleration structure with this approach, but you could build your own little micro-acceleration structure for the body bones (or just brute force it- a couple dozen objects will run pretty fast, especially if bounding box pretesting avoids most of them).
Re: How to shoot an enemy's head
Just looking at the CollisionFilteringDemo:
The firstStackGroup and secondStackGroup are CollisionGroups, they are then paired with a rule of CollisionRule.NoBroadPhase. This means group 1 will not collide with group 2.
To make each entity ignore all other entities do I need to change the Personal collision rules to NoBroadPhase as shown below? It seems to work.
I will try it with 24 enemies. If it performs badly I will do as you suggested and only add them to the space when the controller cylinder is hit. Presumably I will need to use the alternative RayCast method that returns multiple hits?
The firstStackGroup and secondStackGroup are CollisionGroups, they are then paired with a rule of CollisionRule.NoBroadPhase. This means group 1 will not collide with group 2.
To make each entity ignore all other entities do I need to change the Personal collision rules to NoBroadPhase as shown below? It seems to work.
Code: Select all
toAdd.CollisionInformation.CollisionRules.Personal = CollisionRule.NoBroadPhase;
BEPUphysics rules my world
http://cloneofduty.com
http://cloneofduty.com
Re: How to shoot an enemy's head
That would indeed work fine (with less setup than the collision groups I mentioned; the personal rule just slipped my mindTo make each entity ignore all other entities do I need to change the Personal collision rules to NoBroadPhase as shown below? It seems to work.

The spheres do not need to be added to the space on hit. The set of spheres associated with a character can be kept outside of the space and tested directly using their individual entity.CollisionInformation.RayCast methods. You could also check the bounding boxes for overlap prior to the ray cast as a cheap early-out, though this is only really useful once you're dealing with shapes more expensive than a sphere.I will try it with 24 enemies. If it performs badly I will do as you suggested and only add them to the space when the controller cylinder is hit. Presumably I will need to use the alternative RayCast method that returns multiple hits?
Adding the spheres on hit is an option, though it's not clear that this would be better- adding objects to the Space isn't completely free, and the direct testing approach above will be pretty fast.
Re: How to shoot an enemy's head
Please excuse my ignorance. You are saying that I do not even need to add the spheres to the space at all. Instead, I can first of all check to see if the controller is hit and then loop through each sphere and test them individually to see if the ray would hit them.
If that is the case how would I do that? I see the method takes Ray, MaximumLength and outs a RayHit. I am not sure how to create the Ray and would this return true if hit?
By the way, I did run a test of 24 enemies, all with spheres attached. It ran fine, after an initial slow down during initialisation.
I was also wondering about bullets passing through one enemy into another, such as when using a sniper rifle. Also, I may hit the enemy controller, but miss the spheres, such as a shot that narrowly misses the head, the bullet might then continue and hit another enemy in the distance.
I have just check source and it's an XNA Ray we are talking about
If that is the case how would I do that? I see the method takes Ray, MaximumLength and outs a RayHit. I am not sure how to create the Ray and would this return true if hit?
By the way, I did run a test of 24 enemies, all with spheres attached. It ran fine, after an initial slow down during initialisation.
I was also wondering about bullets passing through one enemy into another, such as when using a sniper rifle. Also, I may hit the enemy controller, but miss the spheres, such as a shot that narrowly misses the head, the bullet might then continue and hit another enemy in the distance.
I have just check source and it's an XNA Ray we are talking about

BEPUphysics rules my world
http://cloneofduty.com
http://cloneofduty.com
Re: How to shoot an enemy's head
If you went this route, the positions/orientations of the entities would be set as usual, they just wouldn't belong to the space. Since they aren't in the space, they can't be found by using the Space.RayCast. The character controller's body can be detected by the Space.RayCast however. You can store the sphere objects in a gameplay object in the entity's tag or something along those lines.Instead, I can first of all check to see if the controller is hit and then loop through each sphere and test them individually to see if the ray would hit them.
If that is the case how would I do that?
It is indeed a regular ol' XNA ray as you saw, and the Space.RayCast does indeed return true if it hits any object.I am not sure how to create the Ray and would this return true if hit?
Great- if it's good enough, it's good enough. No need for extra complexityBy the way, I did run a test of 24 enemies, all with spheres attached. It ran fine, after an initial slow down during initialisation.

There is a Space.RayCast which outputs multiple RayCastResults. It also optionally supports a filter to avoid testing unwanted objects.I was also wondering about bullets passing through one enemy into another, such as when using a sniper rifle. Also, I may hit the enemy controller, but miss the spheres, such as a shot that narrowly misses the head, the bullet might then continue and hit another enemy in the distance.
Re: How to shoot an enemy's head
I got it working. Thank you very much!
However, the ray cast against the spheres would only work if they were added to the space.
Here's a video showing it working: http://youtu.be/0DZaVcgOKpU
However, the ray cast against the spheres would only work if they were added to the space.
Here's a video showing it working: http://youtu.be/0DZaVcgOKpU
BEPUphysics rules my world
http://cloneofduty.com
http://cloneofduty.com
Re: How to shoot an enemy's head
Very nice 

Re: How to shoot an enemy's head
Hi Norbo, I made a code change that I thought others may find useful.
It sorts the RayCastResults. The closest hit is first in the list. It's no big deal, but useful for me as I want bullets to penetrate through enemies and stop when hitting the static mesh.
The usage is the same as before. I also worked out a clear() was needed as the list kept getting added to.
Cheers! 
It sorts the RayCastResults. The closest hit is first in the list. It's no big deal, but useful for me as I want bullets to penetrate through enemies and stop when hitting the static mesh.
Code: Select all
using System;
using BEPUphysics.BroadPhaseSystems;
namespace BEPUphysics
{
///<summary>
/// Contains information about a ray cast hit.
///</summary>
public struct RayCastResult : IComparable<RayCastResult>
{
///<summary>
/// Position, normal, and t paramater of the hit.
///</summary>
public RayHit HitData;
/// <summary>
/// Object hit by the ray.
/// </summary>
public BroadPhaseEntry HitObject;
///<summary>
/// Constructs a new ray cast result.
///</summary>
///<param name="hitData">Ray cast hit data.</param>
///<param name="hitObject">Object hit by the ray.</param>
public RayCastResult(RayHit hitData, BroadPhaseEntry hitObject)
{
HitData = hitData;
HitObject = hitObject;
}
public int CompareTo(RayCastResult rayCastResult)
{
// Sort
return this.HitData.T.CompareTo(rayCastResult.HitData.T);
}
}
}
Code: Select all
// Create a class variable
List<RayCastResult> rayCastResults = new List<RayCastResult>();
//In your loop
rayCastResults.Clear();
if (space.RayCast(ray, Weapons[WeaponsIndex].Range, rayCastFilter, rayCastResults))
{
rayCastResults.Sort();
// Whatever
}

BEPUphysics rules my world
http://cloneofduty.com
http://cloneofduty.com