# How to rotate a local position offset based on a direction vector?

I'm trying to fire three raycasts in the direction of movement, from offset starting points. I'm having trouble calculating the start positions of the rays based on the direction.

As you can see in the animation, the three parallel lines in the middle overlap when moving upwards using the code below, but I want them to remain evenly spaced. I cannot use transform.right (up/etc) etc because the transform is always facing the same direction by design. Instead I am using the currentDirection which is the normalized last movement velocity.

I want the lines to always be evenly spaced based on the direction the object is moving without rotating the actual transform - the problem is I don't know the math behind it and have spent last several hours trying to figure it out.

Current code:

Debug.DrawRay(this.transform.position, currentDirection * (avoidObjectsScanDistance + 0.05f), Color.blue, 0.09f);
Debug.DrawRay(this.transform.position + new Vector3(0, 0.1f, 0), currentDirection * (avoidObjectsScanDistance + 0.05f), Color.magenta, 0.09f);
Debug.DrawRay(this.transform.position + new Vector3(0, -0.1f, 0), currentDirection * (avoidObjectsScanDistance + 0.05f), Color.blue, 0.09f);


I've tried to get the position based on direction by using

var drawRayTopPos = currentDirection * localpos + position;


  //find angle of direction
float angle = Mathf.Atan2(currentDirection.y, currentDirection.x) * Mathf.Rad2Deg;
//convert angle to rotation
Quaternion rot = Quaternion.AngleAxis(angle, Vector3.forward);

Debug.DrawRay(TransformPoint(transform.localPosition,
new Vector3(0,0.3f,0), rot, 1),
Quaternion.AngleAxis(angle, Vector3.forward) * Vector3.right,
Color.magenta,
0.1f);

Debug.DrawRay(TransformPoint(transform.localPosition,
new Vector3(0, -0.3f, 0), rot, 1),
Quaternion.AngleAxis(angle, Vector3.forward) * Vector3.right,
Color.magenta,
0.1f);

//convert local to world position including rotation
Vector2 TransformPoint(Vector3 referencePoint, Vector3 p, Quaternion rot,
float scale)
{
return referencePoint + ((rot * p) * scale);
}


Since it looks like you're working in the 2D x/y plane here, you can use a cute little trick:

Vector3 perp = new Vector3(-currentDirection.y, currentDirection.x, 0);


This gives you a vector perpendicular to currentDirection (rotated 90 degrees about the z axis) without any trigonometric functions or quaternions required. :)

Now your three offsets can be:

Vector3 raySpan = currentDirection * (avoidObjectsScanDistance + 0.05f);

Debug.DrawRay(this.transform.position,
raySpan, Color.blue, 0.09f);
Debug.DrawRay(this.transform.position + 0.1f * perp,
raySpan, Color.blue, 0.09f);
Debug.DrawRay(this.transform.position - 0.1f * perp,
raySpan, Color.blue, 0.09f);


Nice and compact. :)

In more general contexts, you can use the Quaternion.LookRotation method to form a quaternion that aligns forward in a particular direction, without needing to explicitly compute the angle yourself.
{"ft_lang_label":"__label__en","ft_lang_prob":0.87993956,"math_prob":0.94461286,"size":1306,"snap":"2019-51-2020-05","text_gpt3_token_len":305,"char_repetition_ratio":0.15053764,"word_repetition_ratio":0.05978261,"special_character_ratio":0.22894333,"punctuation_ratio":0.19123507,"nsfw_num_words":0,"has_unicode_error":false,"math_prob_llama3":0.9676338,"pos_list":[0,1,2],"im_url_duplicate_count":[null,4,null],"WARC_HEADER":"{\"WARC-Type\":\"response\",\"WARC-Date\":\"2019-12-13T03:27:35Z\",\"WARC-Record-ID\":\"<urn:uuid:a8d74776-c950-4ec3-a52b-139317ddb761>\",\"Content-Length\":\"141187\",\"Content-Type\":\"application/http; msgtype=response\",\"WARC-Warcinfo-ID\":\"<urn:uuid:73dcaa9e-0d9c-4585-80ce-479c6473c991>\",\"WARC-Concurrent-To\":\"<urn:uuid:71c4c62b-84d9-4ed7-93c8-7ebd55dc0b3d>\",\"WARC-IP-Address\":\"151.101.193.69\",\"WARC-Target-URI\":\"https://gamedev.stackexchange.com/questions/149654/how-to-rotate-a-local-position-offset-based-on-a-direction-vector/149656\",\"WARC-Payload-Digest\":\"sha1:A2VW7JXVQ7DINE3NTU6SNZXOUSK5CVWA\",\"WARC-Block-Digest\":\"sha1:L6CAHXBEJGBMBWGWXRG44FFANR4PDYGW\",\"WARC-Identified-Payload-Type\":\"text/html\",\"warc_filename\":\"/cc_download/warc_2019/CC-MAIN-2019-51/CC-MAIN-2019-51_segments_1575540548537.21_warc_CC-MAIN-20191213020114-20191213044114-00130.warc.gz\"}"}