Esempio n. 1
0
    /// <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);
    }