in my Billiard Game i have a script which does an offline simulation so that i may predict trajectory. it is very similar to the script that comes with BulletUnity Library called OfflineBallSimulation..
in this script the code takes all collision objects in the world, creates copies of the rigidBodies and adds them to an offline World and simulates there.
I would like to add collision callback to the simulation so that i may also get the collision that may first occur in the simualtion. this is difficult because if i want to add the BCollisionCallbackDefaults script i would need a gameObject to add it to. but i cannot add the Created rigidbody to a gameObject due to serialization or something of the sort. it is a difficult task.
so i am asking if there is someway i have not seen which would make this easier..
here is some of my code
Code: Select all
void Simulate()
{
if (!simulationStarted)
{
if (!createdWorld && ballInstantiator.getBallsLoaded())
{
int j = 0;
//This should create a copy of the BPhysicsWorld with the same settings
BPhysicsWorld bw = BPhysicsWorld.Get();
bw.CreatePhysicsWorld(out cw, out CollisionConf, out Dispatcher, out Broadphase, out Solver, out softBodyWorldInfo);
World = (DiscreteDynamicsWorld)cw;
//Copy all existing rigidbodies in scene
// IMPORTANT rigidbodies must be added to the offline world in the same order that they are in the source world
// this is because collisions must be resolved in the same order for the sim to be deterministic
DiscreteDynamicsWorld sourceWorld = (DiscreteDynamicsWorld)bw.world;
BulletSharp.Math.Matrix mm = BulletSharp.Math.Matrix.Identity;
for (int i = 0; i < sourceWorld.NumCollisionObjects; i++)
{
//here we add the RigidBodies from the source World
CollisionObject co = sourceWorld.CollisionObjectArray[i];
if (co != null && co.UserObject is BRigidBody)
{
BRigidBody rb = (BRigidBody)co.UserObject;
float mass = rb.isDynamic() ? rb.mass : 0f;
BCollisionShape existingShape = rb.GetComponent<BCollisionShape>();
CollisionShape shape = null;
if (existingShape is BSphereShape)
{
shape = ((BSphereShape)existingShape).CopyCollisionShape();
// this might need to be put later after rigidbpdy is created
//initialBallPositions[j] = rb.RigidBody.WorldTransform.Origin;
//updatedInitialPositions = true;
print(rb.name);
}
else if (existingShape is BBoxShape)
{
shape = ((BBoxShape)existingShape).CopyCollisionShape();
}
else if (existingShape is BConvexHullShape)
{
shape = ((BConvexHullShape)existingShape).CopyCollisionShape();
}
RigidBody bulletRB = null;
BulletSharp.Math.Vector3 localInertia = new BulletSharp.Math.Vector3();
rb.CreateOrConfigureRigidBody(ref bulletRB, ref localInertia, shape, null);
BulletSharp.Math.Vector3 pos = rb.GetCollisionObject().WorldTransform.Origin;
BulletSharp.Math.Quaternion rot = rb.GetCollisionObject().WorldTransform.GetOrientation();
BulletSharp.Math.Matrix.AffineTransformation(1f, ref rot, ref pos, out mm);
bulletRB.WorldTransform = mm;
World.AddRigidBody(bulletRB, rb.groupsIBelongTo, rb.collisionMask);
if (existingShape is BSphereShape)
{
for(int k = 0; k <= 15; k++)
{
if (bulletRB.WorldTransform.Origin.ToUnity() == ballRB[k].transform.position)
{
hiddenBall[k] = bulletRB;
print(ballRB[k].gameObject.name);
print(k);
}
}
j++;
}
if (rb == ballRB[0])
{
print("This is CueBall RB: " + rb.gameObject.name);
bulletBallRb[0] = bulletRB;
initialBallPositions[0] = rb.RigidBody.WorldTransform.Origin;
//bCollisionCallBack[0] = bulletRB.;
//print("Ball Rb Name: " + ballRb.name);
}
if (rb == ballRB[1])
{
bulletBallRb[1] = bulletRB;
initialBallPositions[1] = rb.RigidBody.WorldTransform.Origin;
//print("Ball Rb Name: " + ballRb.name);
}
if (rb == ballRB[2])
{
bulletBallRb[2] = bulletRB;
initialBallPositions[2] = rb.RigidBody.WorldTransform.Origin;
//print("Ball Rb Name: " + ballRb.name);
}
if (rb == ballRB[3])
{
bulletBallRb[3] = bulletRB;
initialBallPositions[3] = rb.RigidBody.WorldTransform.Origin;
//print("Ball Rb Name: " + ballRb.name);
}
if (rb == ballRB[4])
{
bulletBallRb[4] = bulletRB;
initialBallPositions[4] = rb.RigidBody.WorldTransform.Origin;
//print("Ball Rb Name: " + ballRb.name);
}
if (rb == ballRB[5])
{
bulletBallRb[5] = bulletRB;
initialBallPositions[5] = rb.RigidBody.WorldTransform.Origin;
//print("Ball Rb Name: " + ballRb.name);
}
if (rb == ballRB[6])
{
bulletBallRb[6] = bulletRB;
initialBallPositions[6] = rb.RigidBody.WorldTransform.Origin;
//print("Ball Rb Name: " + ballRb.name);
}
if (rb == ballRB[7])
{
bulletBallRb[7] = bulletRB;
initialBallPositions[7] = rb.RigidBody.WorldTransform.Origin;
//print("Ball Rb Name: " + ballRb.name);
}
if (rb == ballRB[8])
{
bulletBallRb[8] = bulletRB;
initialBallPositions[8] = rb.RigidBody.WorldTransform.Origin;
//print("Ball Rb Name: " + ballRb.name);
}
if (rb == ballRB[9])
{
bulletBallRb[9] = bulletRB;
initialBallPositions[9] = rb.RigidBody.WorldTransform.Origin;
//print("Ball Rb Name: " + ballRb.name);
}
if (rb == ballRB[10])
{
bulletBallRb[10] = bulletRB;
initialBallPositions[10] = rb.RigidBody.WorldTransform.Origin;
//print("Ball Rb Name: " + ballRb.name);
}
if (rb == ballRB[11])
{
bulletBallRb[11] = bulletRB;
initialBallPositions[11] = rb.RigidBody.WorldTransform.Origin;
//print("Ball Rb Name: " + ballRb.name);
}
if (rb == ballRB[12])
{
bulletBallRb[12] = bulletRB;
initialBallPositions[12] = rb.RigidBody.WorldTransform.Origin;
//print("Ball Rb Name: " + ballRb.name);
}
if (rb == ballRB[13])
{
bulletBallRb[13] = bulletRB;
initialBallPositions[13] = rb.RigidBody.WorldTransform.Origin;
//print("Ball Rb Name: " + ballRb.name);
}
if (rb == ballRB[14])
{
bulletBallRb[14] = bulletRB;
initialBallPositions[14] = rb.RigidBody.WorldTransform.Origin;
//print("Ball Rb Name: " + ballRb.name);
}
if (rb == ballRB[15])
{
bulletBallRb[15] = bulletRB;
initialBallPositions[15] = rb.RigidBody.WorldTransform.Origin;
//print("Ball Rb Name: " + ballRb.name);
}
}
}
updatedInitialPositions = true;
createdWorld = true;
print("World Created");
}
simulationStarted = true;
for (int i = 0; i < numberOfSimulationSteps; i++)
{
if (i == 1)
bulletBallRb[0].ApplyImpulse(force.ToBullet(), positionToHit.ToBullet());
int numSteps = World.StepSimulation(1 / 100f, 10, 1f / 100f);
ballPositionsOfflineSim[i] = bulletBallRb[0].WorldTransform.Origin.ToUnity();
if (bCollisionCallBack[0].getObjectBallHit() == "9BallObject (BulletUnity.BRigidBody)")
{
ballPositionsHitOfflineSim[i] = bulletBallRb[9].WorldTransform.Origin.ToUnity();
print("goig to hit 9 ball");
}
if(bCollisionCallBack[0].getHitBall() > 0)
{
print("Simulation: ball hit");
}
//FirstBallPositionsOfflineSim[i] =
}
for (int j = 0; j <= 15; j++)
{
hiddenBall[j].AngularVelocity *= 0;
hiddenBall[j].LinearVelocity *= 0;
hiddenBall[j].Translate(-(hiddenBall[j].WorldTransform.Origin - initialBallPositions[j]));
//print("Original Position: " + initialBallPositions[j] + "; Current Position: " + hiddenBall[j].WorldTransform.Origin + "; Velocity: " + hiddenBall[j].velocity + "; Angular Velocity: " + hiddenBall[j].angularVelocity);
}
lineRenderer[0].SetPositions(ballPositionsOfflineSim.ToArray());
lineRenderer[9].SetPositions(ballPositionsHitOfflineSim.ToArray());
}
}