使用预制件实例化的RigidBody彼此重叠

时间:2017-07-31 11:46:53

标签: c# unity3d leap-motion rigid-bodies

首先,我想说我已经阅读了有关该问题的所有相关问题,但在我的方案中没有一个有帮助。

问题:

我正在使用Unity和Leap Motion。当Leap Motion的手满足某些碰撞条件时,我实际上是在实例化一些游戏对象。那些游戏对象基本上就像化学中的原子一样,都是球体。

所以我正在做的是当有人将两个原子彼此接近时,然后它们形成分子。为此我使用预制件实例化一个分子并使原子和键(也实例化为圆柱形)作为分子游戏物体的子元素,使用可配置关节连接到原子上。

所有这一切都在正常工作,但是当某些原子相互重叠尽管它们附着有刚体时,它们会发生。另外,我已经检查过isTrigger没有检查过它们。 一旦它们重叠,即使我在游戏模式下尝试从检查员更改值,它们也根本不会分开。

以下是截图。

Molecule

代码比较大,所以我只添加了分子形成的代码。

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;

            }
        }

1 个答案:

答案 0 :(得分:1)

  

所有这些都能正常工作,但有些情况会发生   尽管原子附着在它们身上,但原子相互重叠。

我仔细看了你的代码并看到了这个:

secondAtomTransform.localRotation = Quaternion.identity;
secondAtomTransform.position = finalAtomTwoPos;
不要这样做。这不是如何正确旋转或移动刚体。由于这只是您的代码的一部分,因此可以使用Transform.positionTransform.localRotation来移动您正在移动的任何代码或旋转Rigidbody对象。

应使用Rigidbody.MovePosition功能移动Rigibody,并使用Rigidbody.MoveRotation功能旋转。

虽然我希望这可行,但如果问题仍然存在,则将Rigidbody的Interpolate更改为 None Interpolate 。另一件事是将Rigidbody的碰撞检测更改为连续