首先,我想说我已经阅读了有关该问题的所有相关问题,但在我的方案中没有一个有帮助。
问题:
我正在使用Unity和Leap Motion。当Leap Motion的手满足某些碰撞条件时,我实际上是在实例化一些游戏对象。那些游戏对象基本上就像化学中的原子一样,都是球体。
所以我正在做的是当有人将两个原子彼此接近时,然后它们形成分子。为此我使用预制件实例化一个分子并使原子和键(也实例化为圆柱形)作为分子游戏物体的子元素,使用可配置关节连接到原子上。
所有这一切都在正常工作,但是当某些原子相互重叠尽管它们附着有刚体时,它们会发生。另外,我已经检查过isTrigger
没有检查过它们。
一旦它们重叠,即使我在游戏模式下尝试从检查员更改值,它们也根本不会分开。
以下是截图。
代码比较大,所以我只添加了分子形成的代码。
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;
}
}
答案 0 :(得分:1)
所有这些都能正常工作,但有些情况会发生 尽管原子附着在它们身上,但原子相互重叠。
我仔细看了你的代码并看到了这个:
secondAtomTransform.localRotation = Quaternion.identity;
secondAtomTransform.position = finalAtomTwoPos;
不要这样做。这不是如何正确旋转或移动刚体。由于这只是您的代码的一部分,因此可以使用Transform.position
或Transform.localRotation
来移动您正在移动的任何代码或旋转Rigidbody对象。
应使用Rigidbody.MovePosition
功能移动Rigibody,并使用Rigidbody.MoveRotation
功能旋转。
虽然我希望这可行,但如果问题仍然存在,则将Rigidbody的Interpolate更改为 None 至 Interpolate 。另一件事是将Rigidbody的碰撞检测更改为连续。