コード例 #1
0
    //create rope instantly
    public void CreateRope(GameObject objectsHolder, GameObject chainObject, Transform pointA, Transform pointB, bool lockFirstChain, bool lockLastChain, bool connectToA, bool connectToB, bool hideEndObjects, bool useLineRenderer, Material ropeMat, float ropeWidth)
    {
        objHolder = objectsHolder.transform;

        //reset variables
        int        remainChainCount = 0;
        int        chainIndex       = 0;
        Quaternion newRotation;
        bool       connected = false;
        Transform  tempChain = null;

        //calculate how many chains is needed from pointA to pointB
        remainChainCount = (int)(Vector3.Distance(pointA.position, pointB.position) / (chainObject.renderer.bounds.extents.x * 1.9f));

        //while rope isn't connected to end point
        while (!connected)
        {
            Transform chain;

            if (ropePool != null)
            {
                chain = ropePool.Create().transform;                    //use pooling system
            }
            else
            {
                chain = ((GameObject)GameObject.Instantiate(chainObject)).transform;                    //create chain using standard Instantiate function
            }
            //if useLineRenderer is true, disable chain's renderer
            if (useLineRenderer)
            {
                chain.renderer.enabled = false;
            }
            else
            {
                chain.renderer.enabled = true;
            }

            //positioning and naming chains
            if (!tempChain)            //if this is first chain
            {
                chain.position = pointA.position;
                chain.name     = "chain 1";

                chain.collider2D.isTrigger = true;

                //if hideEndObjects is true, disable chain's renderer
                if (hideEndObjects)
                {
                    chain.renderer.enabled = false;
                }

                //if connecToA is true, connect pointA to chain
                if (connectToA)
                {
                    var             joints    = pointA.GetComponentsInChildren <DistanceJoint2D>();     //get all DistanceJoint2D component from pointA
                    DistanceJoint2D distJoint = new DistanceJoint2D();

                    //iterate through all joints and get free one
                    foreach (var joint in joints)
                    {
                        if (!joint.connectedBody)
                        {
                            distJoint = joint;
                        }
                    }

                    distJoint.distance             = 0.01f;
                    distJoint.connectedBody        = chain.rigidbody2D;
                    pointA.rigidbody2D.isKinematic = true;
                }
                else
                {
                    chain.rigidbody2D.isKinematic = lockFirstChain;
                }
            }
            else             //if this isn't first chain
            {
                //position newly created chain next to last chain
                chain.position = tempChain.position + ((pointB.position - tempChain.position) / remainChainCount);
                chain.name     = "chain " + (1 + chainIndex);
            }

            //rotate chain object to look at end position
            newRotation    = Quaternion.LookRotation(pointA.position - pointB.position, Vector3.up);
            newRotation.x  = 0;
            newRotation.y  = 0;
            chain.rotation = newRotation;

            //if at least 1 chain is created
            if (tempChain)
            {
                //get last created chain's HingeJoint2D component and connect it to newly created object
                var tempChainHinge = tempChain.GetComponent <HingeJoint2D>();
                var midPos         = tempChain.position + ((chain.position - tempChain.position).normalized * (chainObject.renderer.bounds.extents.x));
                tempChainHinge.anchor          = tempChain.transform.InverseTransformPoint(midPos);
                tempChainHinge.connectedAnchor = chain.transform.InverseTransformPoint(midPos);
                tempChainHinge.connectedBody   = chain.rigidbody2D;
                tempChainHinge.enabled         = true;

                //if this is second chain
                if (chainIndex == 1)
                {
                    //add second hingejoint component to second chain object and connect to first chain
                    //it's necessary to swing rope freely around both ends
                    var chainHinge = chain.gameObject.AddComponent <HingeJoint2D>();
                    chainHinge.connectedBody = tempChain.rigidbody2D;

                    //set anchor position
                    if (!connectToA)
                    {
                        chainHinge.anchor          = new Vector2(-tempChainHinge.anchor.x, -tempChainHinge.anchor.y);
                        chainHinge.connectedAnchor = new Vector2(-tempChainHinge.connectedAnchor.x, -tempChainHinge.connectedAnchor.y);
                    }
                    else
                    {
                        chainHinge.anchor = chainHinge.transform.InverseTransformPoint(tempChain.position);
                    }

                    GameObject.DestroyImmediate(tempChainHinge);
                }
            }

            //calculate how many chain is needed from last chain position to end position
            remainChainCount = (int)(Vector3.Distance(chain.position, pointB.position) / (chainObject.renderer.bounds.extents.x * 1.9f));

            //if it's last chain, make it isKinematic(physics won't affect it)
            if (remainChainCount < 1)
            {
                if (!tempChain.GetComponent <HingeJoint2D>())
                {
                    Debug.LogWarning("Distance from pointA to pointB is very small, increase distance");
                    chain.parent = objectsHolder.transform;
                    break;
                }

                //don't limit angle
                var tempChainJoint = tempChain.GetComponent <HingeJoint2D>();
                tempChainJoint.useLimits = false;

                //set anchor position
                if (connectToB)
                {
                    tempChainJoint.connectedAnchor = Vector2.zero;
                    tempChainJoint.anchor          = tempChain.transform.InverseTransformPoint(chain.position);
                }

                chain.collider2D.isTrigger = true;

                //if hideEndObjects is true, disable chain's renderer
                if (hideEndObjects)
                {
                    chain.renderer.enabled = false;
                }

                //if connectToB is true, connect pointB to last chain
                if (connectToB)
                {
                    var             joints    = pointB.GetComponentsInChildren <DistanceJoint2D>();     //get all DistanceJoint2D from pointB
                    DistanceJoint2D distJoint = new DistanceJoint2D();

                    //iterate through joints and return free one
                    foreach (var joint in joints)
                    {
                        if (!joint.connectedBody)
                        {
                            distJoint = joint;
                        }
                    }

                    distJoint.distance             = 0.01f;
                    distJoint.connectedBody        = chain.rigidbody2D;
                    pointB.rigidbody2D.isKinematic = true;
                }
                else if (lockLastChain)
                {
                    chain.rigidbody2D.isKinematic = true;
                }

                GameObject.DestroyImmediate(chain.GetComponent <HingeJoint2D>());                 //remove HingeJoint2D component for last chain

                //if useLineRenderer is true, add UseLineRenderer.cs to rope parent, set it material and width
                if (useLineRenderer)
                {
                    var useLinerend = objectsHolder.AddComponent <UseLineRenderer>();
                    useLinerend.ropeMaterial = ropeMat;
                    useLinerend.width        = ropeWidth;
                }

                connected = true;
            }

            chain.parent = objectsHolder.transform; //child this chain into objectsHolder gameobject in hierarchy window

            tempChain = chain;                      //save just instantiated chain in tempChain variable

            chainIndex++;
        }
    }