First of all I want to say that I have already read all the related question for the problem but none of them has helped in my scenario.
Problem:
I am working with Unity and Leap Motion. I am actually instantiating some game object when some collision conditions are met by Leap Motion hands. Those game objects are basically atoms as in chemistry and are spheres.
So what I am doing is when someone rings two atoms closer to each other then they form molecule. For this I instantiate a molecule using prefab and make both atoms and bonds(also instantiated are cylinder in shape) as a child of the molecule game objects which are attached to atoms using configurable joints.
All of this is working properly but their occurs some cases when some atoms overlap each other despite having rigid body attached to them. Also I have checked that isTrigger
is not checked on any of them.
Also once they overlap, they do not separate at all even if I try changing value from inspector while being in play mode.
Here is the screenshot of the same.
Code is relatively big so I am only adding code for molecule formation.
private void createBonds(MoleculeData moleculeData, Molecule molecule)
{
// local coords are --> in Unity Y is going up, Z is left & X is coming out of screen..
// we will always keep Y of all atoms equal to each other and move them only in XZ space/plane
// for eg if the angle between two atoms needs to be 90 degree then one atom needs to be farther on X axis and other on Z axis
// basically rcos(angle) & rsin(angle) to get projection in x & z axis
// x = rsin(angle) & z = rcos(angle)
List<Transform> allObjects = new List<Transform>();
int numBonds = moleculeData.bonds.Count;
float startAngle = 0;
var centerAtomTransform = moleculeData.centralAtom.gameObject.transform;
allObjects.Add(centerAtomTransform);
moleculeData.centralAtom.parentMolecule = molecule;
centerAtomTransform.localRotation = Quaternion.identity;
centerAtomTransform.gameObject.GetComponent<Rigidbody>().constraints = RigidbodyConstraints.FreezeAll;
float radiusSphere = moleculeData.centralAtom.gameObject.GetComponent<SphereCollider>().radius;
float scale = centerAtomTransform.localScale.x; // we are assuming all scales are equal (which currently are)
float actualRadiusOfSphere = radiusSphere * scale;
List<Bond> allBondsFormed = new List<Bond>();
if (moleculeData.structure == StructureType.StraightLine || moleculeData.structure == StructureType.FlatTriangle || moleculeData.structure == StructureType.Triangle)
{
float anglePhi = 0; // this is polar angle from positive y-axis
List<Vector3> positionsOnSphereBoundary = new List<Vector3>();
for (int i = 0; i < numBonds; i++)
{
float xPointOnSphereBoundary = actualRadiusOfSphere * Mathf.Sin(Mathf.Deg2Rad * startAngle) + Mathf.Sin(Mathf.Deg2Rad * anglePhi);
float yPointOnSphereBoundary = actualRadiusOfSphere * Mathf.Cos(Mathf.Deg2Rad * anglePhi);
float zPointOnSphereBoundary = actualRadiusOfSphere * Mathf.Cos(Mathf.Deg2Rad * startAngle) + Mathf.Sin(Mathf.Deg2Rad * anglePhi);
var positionOnSphereBoundary = new Vector3(centerAtomTransform.position.x + xPointOnSphereBoundary, centerAtomTransform.position.y + yPointOnSphereBoundary, centerAtomTransform.position.z + zPointOnSphereBoundary);
positionsOnSphereBoundary.Add(positionOnSphereBoundary);
startAngle += (float)moleculeData.bondAngle;
}
for (int i = 0; i < positionsOnSphereBoundary.Count; i++)
{
var directionVectorFromAtom2ToAtom1 = centerAtomTransform.position - positionsOnSphereBoundary.ElementAt(i);
directionVectorFromAtom2ToAtom1.Normalize();
var bondProp = moleculeData.bonds.ElementAt(i);
if (bondProp.bondLength == 0.0)
{
bondProp.bondLength = .08f;
}
var finalAtomTwoPos = positionsOnSphereBoundary.ElementAt(i) + directionVectorFromAtom2ToAtom1 * bondProp.bondLength;
Transform secondAtomTransform = null;
Atom secondAtom = null;
if (bondProp.connectedAtomOne != moleculeData.centralAtom)
{
secondAtomTransform = bondProp.connectedAtomOne.gameObject.transform;
secondAtom = bondProp.connectedAtomOne;
}
else if (bondProp.connectedAtomTwo != moleculeData.centralAtom)
{
secondAtomTransform = bondProp.connectedAtomTwo.gameObject.transform;
secondAtom = bondProp.connectedAtomTwo;
}
else
{
throw new System.Exception("Shall not occur??");
}
secondAtomTransform.gameObject.GetComponent<Rigidbody>().constraints = RigidbodyConstraints.FreezeAll;
secondAtomTransform.localRotation = Quaternion.identity;
secondAtomTransform.position = finalAtomTwoPos;
#region BondStickInit
var bondStick = (bondProp.subType == SubBondType.Triple) ? Instantiate(tripleBondStickPrefab) : (bondProp.subType == SubBondType.Double) ? Instantiate(doubleBondStickPrefab) : Instantiate(bondStickPrefab); //Intantiate a bond stick between the atoms
bondStick.GetComponent<Rigidbody>().constraints = RigidbodyConstraints.FreezeAll;
var bond = bondStick.GetComponent<Bond>(); //Get the bond component of the bondstick
bond.SetAtoms(moleculeData.centralAtom, secondAtom); //Add atoms to the bondstick
bond.InitBondStick(moleculeData.centralAtom.transform, secondAtom.transform, bondProp.bondLength, actualRadiusOfSphere); //Initialize the bond stick
bond.SetBondType(bondProp.type, bondProp.subType);
allObjects.Add(bondStick.transform);
allObjects.Add(secondAtomTransform);
allBondsFormed.Add(bond);
#endregion
secondAtom.parentMolecule = molecule;
moleculeData.centralAtom.AddConnectedAtom(secondAtom);
secondAtom.AddConnectedAtom(moleculeData.centralAtom);
molecule.AddAtoms(moleculeData.centralAtom, secondAtom);
molecule.AddBond(bond);
//update reactive spots, since we added new bond
moleculeData.centralAtom.RemoveReactiveSpots(bond);
secondAtom.RemoveReactiveSpots(bond);
secondAtomTransform.gameObject.GetComponent<Rigidbody>().constraints = RigidbodyConstraints.None;
}
}