0

I'd like, at each frame, to move, scale and rotate a given cylinder so that it behaves like a 'rope' between two points.

I have this code at the moment, but it doesn't work at all like intended :

hook.transform.position = (rightHandPosition + hookDestination)/2;

hook.transform.localScale = new Vector3(0.5F, Vector3.Magnitude(hookDestination - rightHandPosition), 0.5F);

hook.transform.rotation = Quaternion.Euler(hookDestination - rightHandPosition);

As you can guess the two points are rightHandPosition and hookDestination. For now, the cylinder spawns at 'random' locations, with 'random' rotations and enormous scales.

How can I fix it ?

"Full" script :

public class FirstPersonController : MonoBehaviour {

    public GameObject hook;
    bool isHooked = false;
    Vector3 hookDestination;
    Vector3 rightHandPosition;

    void Start() {
        hook.renderer.enabled = false;
        rightHandPosition = hook.transform.position;
    }

    // Update is called once per frame
    void Update () {
        if (isHooked) {
            hook.transform.position = (rightHandPosition + hookDestination)/2;
            hook.transform.localScale = new Vector3(0.5F, Vector3.Magnitude(hookDestination - rightHandPosition), 0.5F);
            hook.transform.rotation = Quaternion.Euler(hookDestination - rightHandPosition);
        }

        if (isHooked && !Input.GetMouseButton(1)) {
            isHooked = false;
            hook.renderer.enabled = false;
        }

        if (Input.GetMouseButtonDown (1) && !isHooked) {
            Ray ray = GameObject.FindGameObjectWithTag ("MainCamera").camera.ViewportPointToRay (new Vector3 (0.5F, 0.5F, 0));
            RaycastHit hit;
            if (Physics.Raycast (ray, out hit) && hit.distance < 5000000 && hit.collider.tag != "Player") {
                isHooked = true;
                hookDestination = hit.point;
                hook.renderer.enabled = true;
            }
        }
    }
}

A screenshot of the scene :

hook behavior (bug)

Mat
  • 952
  • 2
  • 11
  • 28
  • full script and an image of gameview will be helpful – Burak Karasoy Dec 05 '15 at 22:41
  • I haven't tested this, but try: `Quaternion.SetLookRotation(hookDestination - rightHandPosition)` and maybe `transform.localRotation` instead of `rotation`. And I second @BurakKarasoy 's comment. – The Oddler Dec 05 '15 at 22:41
  • @TheOddler : doesn't work (there seems to be no rotation applied at all). I updated my original post with a bigger part of my script and a screenshot :) – Mat Dec 05 '15 at 23:02
  • @fafase : now that's an interesting option ! I'll try with that and let you know how it goes. However, I'd still like to find the bug in my original script, just for my personnal knowledge :) – Mat Dec 06 '15 at 11:58

2 Answers2

0

fafase's comment was the right answer : use LineRenderer.

hookRender.SetPosition(0, rightHandPosition);
hookRender.SetPosition(1, hookDestination);
Mat
  • 952
  • 2
  • 11
  • 28
0

Let us assume that cubeStart is the starting point and cubeEnd is the end point. And "cylinder" is your cylinder, then

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AlignCyl : MonoBehaviour {


    GameObject cubeStart;
    GameObject cubeEnd;
    GameObject cylinder;

    Vector3 endV; 
    Vector3 startV;
    Vector3 rotAxisV;
    Vector3 dirV;
    Vector3 cylDefaultOrientation = new Vector3(0,1,0);

    float dist;

    // Use this for initialization
    void Start () {

         cubeStart = GameObject.Find("CubeStart");
         cubeEnd   = GameObject.Find("CubeEnd");

         cylinder  = GameObject.Find("Cylinder");

        endV   = cubeEnd.transform.position;
        startV = cubeStart.transform.position;


    }

    // Update is called once per frame
    void Update () {

        // Position
        cylinder.transform.position = (endV + startV)/2.0F;

        // Rotation
        dirV = Vector3.Normalize(endV - startV);

        rotAxisV = dirV + cylDefaultOrientation;

        rotAxisV = Vector3.Normalize(rotAxisV);

        cylinder.transform.rotation = new Quaternion(rotAxisV.x, rotAxisV.y, rotAxisV.z, 0);

        // Scale        
        dist = Vector3.Distance(endV, startV);

        cylinder.transform.localScale = new Vector3(1, dist/2, 1);

    }
}

Tested with Unity3D 2018.1 My concept about rotation is based on quaternions solely.

x=rotAxis.x * sin(angle/2)  = rotAxis.x;
y=rotAxis.y * sin(angle/2) = rotAxis.y;
z=rotAxis.z * sin(angle/2) = rotAxis.z;
w = cos(angle/2) = 0;

where rotAxis is the sum of 2 vectors i.e. the default cylinder orientation and the wanted orientation. Angle is 180 degrees because we want the cylinder to rotate around the rotAxis by 180 degrees. It is the definition of quaternion rotation (rotation around an axis).

Dimitrios Ververidis
  • 1,118
  • 1
  • 9
  • 33