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 :
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 ie 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).
fafase's comment was the right answer : use LineRenderer
.
hookRender.SetPosition(0, rightHandPosition);
hookRender.SetPosition(1, hookDestination);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.