Finding least rotation

So if I have 3 objects with object A being the rotating object, and Objects B and C are in random locations.
I want to find if ether Object B or C needs the least amount of rotation for Object A to be “Looking At”, and set that object as the target for Object A to look at. I also need it to be found from “Items” in a list of objects whose colliders are intersecting the ray cast. the ray cast is a straight line facing the same direction as Object A. And I have to ignore the distance of there transformations. In short I have almost no clue how to do this, and I’m really sorry for any grammar or spelling errors. I am also very sorry if you can’t understand what i mean I have no clue how to word this. (note: I only use an example with 2 objects that are possible targets but it needs to work with any amount of possible targets.)

Thank you so much for any and all advice, also if you find a thread with a like question or relating topic please leave a link as well.

It’s not so bad. Use Quaternion.Angle to measure the angle to each of your targets. Pick the smallest one.

Ok, but how would I get the closest object from a list

So you need to find the angle between the facing direction of your ‘object A’, and a direction pointing at the other object. This is the amount of change that will be made when rotating to ‘look at’ the other object. (no Quaternion.Angle here, we’re using Vector3.Angle)

var a = Vector3.Angle(objectA.transform.forward, otherObject.transform.position - objectA.transform.position);

Where objectA.transform.forward is the direction in which objectA is currently facing.
And otherObject.transform.position - objectA.transform.position is vector pointing from objectA towards otherObject.

We’ll need to do this for all objects, and order them ascending, and grab the first. We can use System.Linq for this:

var objectNearestByDirection = (from other in collectionOfObjectsToTest
                orderby Vector3.Angle(objectA.transform.forward, other.transform.position - objectA.transform.position) ascending
                select other).FirstOrDefault();

Of course, this is assuming that the ‘forward’ vector of objectA is the facing direction.

Or if LINQ makes your brain hurt (or gives you concerns about performance), you can do the same thing with a for loop, simply keeping track of the best hit you’ve found (and the angle you found it at).

GameObject bestObj = null;
float bestAng = 0;
for (int i=0; i<items.Length; i++) {
    float ang = Vector3.Angle(objectA.transform.forward, items[i].transform.position - objectA.transform.position);
    if (bestObj == null || ang < bestAng) {
        bestObj = items[i];
        bestAng = ang;
    }
}

Of course the LINQ is substantially shorter, and possibly clearer, so if those concerns don’t apply you should probably use it. :slight_smile:

1 Like