How to rotate an object around one end of line till its lies on the line

From the image below, I would like to rotate a game object C around a point A of a line (made using a line renderer) by an angle d to position p1 till C is on the same line joining points A and B over a given period of time. Preferably using a coroutine. Please note that the angle d is not known. How can I achieve this?

Try the following script :

using UnityEngine;
using System.Collections;

public class RotateScript : MonoBehaviour
{
public float rotationSpeed;

public void StartAlign( Vector3 pointA, Vector3 pointB )
{
StartCoroutine( Align(pointA, pointB) );
}

private IEnumerator Align( Vector3 pointA, Vector3 pointB )
{
// Compute the rotation axis
Vector3 axis = Vector3.Cross( pointB - pointA, transform.position - pointA );

// Compute the rotation angle
float totalAngle = -Vector3.SignedAngle(pointB - pointA, transform.position - pointA, axis );
float sign = totalAngle < 0 ? -1 : 1;
float angle = 0;

// Rotates smoothly the object
for ( float cumulativeAngle = 0 ; sign * cumulativeAngle < sign * totalAngle ; cumulativeAngle += angle )
{
angle = sign * Mathf.Min( sign * (totalAngle - cumulativeAngle), Time.deltaTime * rotationSpeed );
transform.RotateAround( pointA, axis, angle );
yield return null;
}
}

}


If your pointC must be a vector, try the following script:

using UnityEngine;
using System.Collections;

public class RotateScript : MonoBehaviour
{
public float rotationSpeed;

// This is an example function to show how StartAlign must be called
// The last parameter must be a function taking a Vector3 as only parameter
public void Foo()
{
StartAlign( pointC, pointA, pointB, OnPointCChanged );
}

public void StartAlign( Vector3 pointC, Vector3 pointA, Vector3 pointB, System.Action<Vector3> SetNewPointCPosition )
{
StartCoroutine( Align( pointC, pointA, pointB, SetNewPointCPosition ) );
}

private IEnumerator Align( Vector3 pointC, Vector3 pointA, Vector3 pointB, System.Action<Vector3> SetNewPointCPosition )
{
// Compute the rotation axis
Vector3 direction = pointC - pointA;
Vector3 axis = Vector3.Cross( pointB - pointA, direction );

Quaternion startRotation = Quaternion.identity;
Quaternion endRotation = Quaternion.FromToRotation( direction, pointB - pointA );

Debug.Break();

// Rotates smoothly the object
for ( float time = 0 ; time < 1 / rotationSpeed ; time += Time.deltaTime )
{
Quaternion rotation = Quaternion.Slerp( startRotation, endRotation, time * rotationSpeed );
Vector3 d = rotation * direction;
SetNewPointCPosition( d + pointA );

yield return null;
}
}

private void OnPointCChanged( Vector3 newPosition )
{
Debug.Log( newPosition );
}
}

• I am not too sure how to get the transform for A and B. – SuperHyperMegaSomething Dec 12 '17 at 15:26
• You have to attach this script to the objectC, and then drag & drop the objects A and B into the public fields, in the inspector. – Hellium Dec 12 '17 at 15:32
• Okay, maybe I didn't explain it well enough. C is an object but A and B are the end points of a line made with a line renderer. – SuperHyperMegaSomething Dec 12 '17 at 15:37
• My bad, I've edited my answer so that you can pass two vectors as end points of your LineRenderer – Hellium Dec 12 '17 at 15:42
• Thanks, it's working. I'd like to know. What happens if A and C are points and also form a line. How would line AC be aligned to line AB? – SuperHyperMegaSomething Dec 12 '17 at 16:53

The signed angle between two 2d vectors A and B is

angle = atan2(-B.y * A.x + B.x * A.y, B.x * A.y + B.y * A.y)


If you have a signed angle between the point and the line, then rotating the former towards the latter is as simple as checking for the sign of the angle. If it's positive, then subtract from the current angle. If it's negative, then add to it.

In code (step is the angle the point rotates in one frame):

IEnumerator Rotate(Vector2 A, Vector2 B) {
float angle;
do {
angle = Mathf.atan2(-B.y * A.x + B.x * A.y, B.x * A.y + B.y * A.y);
if (angle < 0) {
// Rotate the point by 1 step in the positive direction
} else {
// Rotate the point by 1 step in the negative direction
}
} while (angle > step);
// Set the angle of the point to the angle of the line
}
{"extraction_info": {"found_math": true, "script_math_tex": 0, "script_math_asciimath": 0, "math_annotations": 0, "math_alttext": 0, "mathml": 0, "mathjax_tag": 0, "mathjax_inline_tex": 0, "mathjax_display_tex": 0, "mathjax_asciimath": 1, "img_math": 0, "codecogs_latex": 0, "wp_latex": 0, "mimetex.cgi": 0, "/images/math/codecogs": 0, "mathtex.cgi": 0, "katex": 0, "math-container": 0, "wp-katex-eq": 0, "align": 0, "equation": 0, "x-ck12": 0, "texerror": 0, "math_score": 0.18295051157474518, "perplexity": 7643.0684351709215}, "config": {"markdown_headings": false, "markdown_code": true, "boilerplate_config": {"ratio_threshold": 0.18, "absolute_threshold": 10, "end_threshold": 15, "enable": true}, "remove_buttons": true, "remove_image_figures": true, "remove_link_clusters": true, "table_config": {"min_rows": 2, "min_cols": 3, "format": "plain"}, "remove_chinese": true, "remove_edit_buttons": true, "extract_latex": true}, "warc_path": "s3://commoncrawl/crawl-data/CC-MAIN-2020-29/segments/1593655902377.71/warc/CC-MAIN-20200709224746-20200710014746-00381.warc.gz"}