//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++; } }