- Home /
How to work out the rotation of a pivot to point an offset vector at a target?
Title is confusing and I am bad with words.
In your typical 2D game, to aim a gun at something, you might work out the angle between the pivot and the target and simply rotate.
However, my guy doesn't hold the gun directly along the pivot. See the following gif for what happens if I try that method:
http://i.imgur.com/hU7nVJD.gif
What I really want, is the red line to always point at the mouse, not the white line.
I've tried the following script:
using UnityEngine;
using System.Collections;
public class RotateOffset : MonoBehaviour
{
[SerializeField]
Transform _source;
[SerializeField]
Transform _directionSource;
[SerializeField]
Transform _pivot;
// Update is called once per frame
void Update()
{
Vector3 mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
Vector2 mousePos = new Vector2(mousePosition.x, mousePosition.y);
Vector2 pivotPos = new Vector2(_pivot.position.x, _pivot.position.y);
Vector2 sourcePos = new Vector2(_source.position.x, _source.position.y);
Vector2 directionSourcePos = new Vector2(_directionSource.position.x, _directionSource.position.y);
// wasn't sure how to work out a relative direction, so had to use tranforms
Vector2 direction = directionSourcePos - sourcePos;
// attempting basic trig (which I'm not very good at)
// from pivot to source is one side
float sideB = Vector2.Distance(pivotPos, sourcePos);
// this angle is fixed given the pivot -> source -> direction relationship
float angleB = Vector2.Angle(pivotPos - sourcePos, direction);
// from pivot to mouse is another side
float sideA = Vector2.Distance(mousePos, pivotPos);
// So I actually want AngleC here, meaning i have to work out AngleA first as I don't know C or AngleC
// sine rule
float sinB = Mathf.Sin(angleB * Mathf.Deg2Rad);
sinB = sinB / sideB; // had to split these steps out for some reason - was giving the same answer no matter the input if done on one line?
sinB = sinB * sideA;
float angleA = Mathf.Asin(sinB) * Mathf.Rad2Deg;
// can now get AngleC with the fact triangles add up to 180
float angleC = 180f - angleB - angleA;
// I originally tried to just set the pivot rotation here but it didn't work
// _pivot.transform.eulerAngles = new Vector3(0, 0, angleC);
// so I tried to attempt to work out some kind of offset to work out where that angle exists in world space
// translate target back to origin and atan2 magic it
float offset = Mathf.Atan2(mousePos.x - pivotPos.x, mousePos.y - pivotPos.y);
// use the angleC with the offset... I've tried angle - offset, offset - angle, angle + offset
_pivot.transform.eulerAngles = new Vector3(0, 0, angleC - offset);
}
}
But it doesn't quite work. I think I've got confused somewhere.
I've made sure to test this with just positive X and Y values, in case going over an axis confuses it. It doesn't work in any of the 4 'areas' around the pivot (i.e. X, Y, -X, -Y relative to pivot).
Your answer
Follow this Question
Related Questions
AI reflect shooting 0 Answers
Transform 2d object by two points gained from touch 0 Answers
Extending a vector? 4 Answers
Drawing projectile trajectory 5 Answers
Fit in squares in a dedicated space 2 Answers