/// <summary> /// Shoot the specified start and target. /// </summary> /// <param name="chainsHolder">chain objects holder</param> /// <param name="start">Start location where the silk is shoot </param> /// <param name="target">The target location that the silk finally hangs on</param> /// <returns>true if silking succeeeded, false otherwise</returns> public bool Shoot(GameObject chainsHolder, Transform start, Transform target, int chainsNumber, Material silkMaterial) { _savedChainsHolder = chainsHolder; Vector2 startPos = start.position; Vector2 targetPos = target.position; float distance = Vector2.Distance(startPos, targetPos); if (distance < 0.1f) { Debug.LogWarning("too close to shoot a silk"); return(false); } _lineRenderer = chainsHolder.GetComponent <LineRenderer> (); if (!_lineRenderer) { _lineRenderer = chainsHolder.AddComponent <LineRenderer> (); } float chainLength = distance / chainsNumber; Debug.Log("chain length: " + chainLength); Vector2 chainBoxColliderSize = new Vector2(chainLength, _lineWidth); float angle = Utils.AngleFromX(start.position - target.position); float angleRadian = angle * Mathf.Deg2Rad; Vector2 chainOffset = new Vector2(chainLength * Mathf.Cos(angleRadian), chainLength * Mathf.Sin(angleRadian)); Vector2 currentPos = targetPos + 0.5f * chainOffset; Quaternion rotation = Quaternion.AngleAxis(angle, Vector3.forward); // chain objects in reverse order for (int i = 0; i < chainsNumber; i++) { GameObject obj = new GameObject("Chain" + i); ChainController chainController = obj.AddComponent <ChainController>(); chainController.SetSilk(this); Rigidbody2D rb2D = obj.AddComponent <Rigidbody2D>(); //rb2D.mass = 1f; BoxCollider2D box = obj.AddComponent <BoxCollider2D>(); box.size = chainBoxColliderSize; HingeJoint2D joint = obj.AddComponent <HingeJoint2D>(); if (i == 0) { // joint.anchor is always in its local space joint.anchor = new Vector2(-0.5f * chainLength, 0); // joint.connectedAnchor in world space since not connected to other // rigidbody for the first hinge joint.connectedAnchor = targetPos; } else { // connect to parent rigid body if not the first chain joint.connectedBody = _chains[i - 1].GetComponent <Rigidbody2D>(); // joint.anchor is always in my own local space joint.anchor = new Vector2(-0.5f * chainLength, 0); // joint.connectedBody now in other object’s local space joint.connectedAnchor = new Vector2(0.5f * chainLength, 0); } obj.transform.SetParent(chainsHolder.transform); obj.transform.position = currentPos; obj.transform.rotation = rotation; obj.transform.localScale = Vector3.one; _chains.Add(obj); currentPos += chainOffset; } _lineRenderer.SetVertexCount(chainsNumber); _lineRenderer.SetWidth(_lineWidth, _lineWidth); _lineRenderer.material = silkMaterial; for (int i = 0; i < chainsNumber; i++) { _lineRenderer.SetPosition(i, _chains[i].transform.position); } _state = State.Completed; return(true); }