| Home Page | Recent Changes | Preferences

UnrealScript Vector Maths

This is a page of "how to I do foo" sort of things, for values of "foo" involving points, vectors, rotators, quaternions, etc. Add question, post pseudocode / UnrealScript code.

And as we sometimes say... "it's not rocket science!". Except in this case, it is ;).

How Do I...

In the following, A and B are vectors for the position of points unless noted otherwise. (e.g. anActor.Location)

...find a vector that points from A to B?:

vector = B - A;

[Vector2]

...find a unit vector pointing to B from A?:

vector = Normal(B - A);

...find a unit vector pointing in the direction a player is looking?:

vector = vector(myPlayerController.GetViewRotation());

...rotate Actor A to face B?:

A.SetRotation(rotator(B - A.location));

...find the distance between A and B?:

distance = VSize(A - B);

...find where A is in relation to B?:

orientation = A dot B;
  // > 0.0  A points forwards in relation to B (up to 90° apart)
  // = 0.0  A is perpendicular to B (exactly 90° between A and B)
  // < 0.0  A points backwards in relation to B (more than 90° apart)

Note, that the angles in this example are mesured at the origin of the Unreal world's coordinate system.

Tarquin: This needs a rewrite.

...find where Actor A is in relation to Pawn B, taking into account B's ViewRotation? (make sure Pawn B has a Controller):

orientation = vector(B.Controller.GetViewRotation()) dot Normal(A.Location - B.Location);
  // > 0.0  A points forwards in relation to B (up to 90° apart)
  // = 0.0  A is perpendicular to B (exactly 90° between A and B)
  // < 0.0  A points backwards in relation to B (more than 90° apart)

Question: How do I know if its to the Left or Right?

...find a point that's at a certain distance from a starting point in a given direction? :

LocationTarget = LocationStart + vector(Rotation) * Distance;

...find the (smallest) angle between A and B?

Note: Acos is a built-in function in UT2003. It is not present in UT, see Useful Maths Functions.
This assumes A and B are normalized (are unit vectors). If either of them is not normalized you need to wrap them in a Normal().

angle = Acos(A dot B);

DemonThing: Just wanted to point out that the vector A dot B is defined as

A dot B = VSize(A) * VSize(B) * cos(angle)
//or
A dot B = vect(A.x * B.x, A.y * B.y, A.z * B.z)

if I remember correctly. Don't try this code out – it won't work!!! :D

...point to my left or right? :

A vector that points at 90 degrees to the way you're looking can be given by the following. Note that it is horizontal; in the XY plane. (So for a rolling aeroplane, this won't point along the wing which will be slanted)

 resultingVector = Normal(vector cross vect(0, 0, 1));

...find out vector B that points x degrees to the left or right of vector A?

Foxpaw: I believe there are multiple vectors that could satisfy this. Can you be more specific?

Tarquin: It depends on what you want – 'left' and 'right' doesn't mean much in 3D, it has to be on a plane. We can assume the horizontal though, as above.

smattbac: Like in the example above this one, but instead of 90 degrees, any angle (or less than 90).

Tarquin: Get a normal of the direction you're pointing in. Call it i. Get the 90 degrees to the left one. Call it j. Do some sine and cosine mojo with them.

Foxpaw: I think it would be something along the lines of:

  Normal((Normal(vector) * (1 - (AngleInDegrees / 90) ) ) + (Normal(vector cross vect(0, 0, 1)) * (AngleInDegrees / 90)));

I'm not sure if that would work or not. It seems to work for 0 degrees, 90 degrees, and 45 degrees, but I don't know if it will work for other ones or not.

Tarquin: eek. What you need is this: i*cos(alpha) + j*sin(alpha). Alpha is angle in radians, obviously

...damp a velocity vector toward a surface?

Velocity += SurfaceNormal * (Normal(Velocity) dot SurfaceNormal) * DampFactor;

Useful DampFactor is >=-1, where -1 will make Velocity parallel to the surface, 0 will do nothing, and positive values will give a "pop up" effect by making the Velocity vector point further from the plane of the surface.

...find point Q where a normal from point P to a line from A to B meets the line?

Given a line AB and a point P, we want to find a point Q on that line such that PQ and AB are perpendicular.

[normal_to_a_line_01]

Q = A + Normal( B - A ) * ((( B - A ) dot ( P - A )) / VSize( A - B ));

This is perfect for that railgun with shockwave damage you always wanted:

for (P = Level.PawnList; P != None; P = P.NextPawn)
{
    Q = StartTrace + Normal( HitLocation - StartTrace ) * ((( HitLocation - StartTrace )
    dot ( P.Location - StartTrace )) / VSize( StartTrace - HitLocation ));

    if (VSize( P.Location - Q ) < ShockwaveRadius)
    {
        // Pawn is within ShockwaveRadius, do your mojo!
    }
}

Note: Point Q is not restricted to the length of line AB, so remember to check that the victims are in front of StartTrace and behind HitLocation for that railgun (unless you want it to go through the whole level in either direction, ofcourse...)

DemonThing: Q is a location vector. Observe:

See my definition of dot product above (the first one). You will see that (B - A) dot (P - A) is equal to VSize(B - A) * VSize(P - A) * cos(angle). Divide that by VSize(A - B) (which is equal to VSize(B - A)) and you get VSize(P - A) * cos(angle). If you know a bit of trigonometry, you will see that this is equal to VSize(Q - A). When you multiply that by Normal(B - A) (which is equal to Normal(Q - A), since A, B, and Q are collinear), you get Q - A. We add A to that and we get Q, which is a location vector.

...only affect certain components of a vector?

In UnrealScript there's a component-by-component vector multiplication. You can use it to either only use two components of a vector for an operation and/or ignore certain components of the result.

// do something with A but don't change the Z component of it
vector = vect(1,1,0) * DoSomethingWith(A) + vect(0,0,1) * A;

// do something with the X and Z components of A
vector = DoSomethingWith(vect(1,0,1) * A);

// do something with the Y and Z components of a vector and use its original X component
vector = vect(0,1,1) * DoSomethingWith(vect(0,1,1) * A) + vect(1,0,0) * A;

What does this do?

 resultingVector = Normal(vector cross vect(0, 0, 1));

The cross product of two vectors is perpendicular to both. Which means that (vector cross vect(0, 0, 1)) is a vector pependicular to the given vector AND the z-axis. Something perp to z is horizontal – it's confined to the XY plane. So it's a horizontal vector that is also perp to the given vector. It's then normalized. I can't remember which way the cross product points in Unreal. So it's either a unit vector that points to your right or left.

AlphaOne: What about this:

 vector = vect(0, 0, 1) >> Rotation;

I believe that Rotation is also a vector (not a rotator). Is it?

Tarquin: Be pretty cruddy coding if it were. >> is a rotator / vector operator.

Dade: How would i go about modifying only the "XY" coordinates of a vector? I.E. Changes the vector's

location, but not its height. Or is this even possible? (haven't studied vectors yet)

VonStrohmen: I'm not quite sure what you're asking, but if you mean can you change the X and Y components of a vector without modifying its Z, then sure.

Vector A,B;
B = vect(A.X +50, A.Y + 100, A.Z);

Dade: Ah Ha! Thank you. That was exactly what i needed.

Wormbo: Note that vect(x,y,z) and rot(p,y,r) are more like "a string" or 'aName', in other words a constant. Also note that you can "multiply" vectors in UnrealScript, i.e. vect(1,2,3) * vect(2,3,4) = vect(2,6,12). This is neither dot product nor cross product, it just multiplies the corresponding parts of the vector.

Mortal Monkey: Hello good people! I just added the "...find vector Q" part, feel free to improve it.

Foxpaw: What do << and >> do with regards to vectors? One of them appears to do a coordinate rotation of the vector given that the rotator points along the X Axis of the target coordinate system, but what does the other one do?

inio: I thought they rotated a vector by a rotator, and the reverse a of a rotator ((theVec << theRot) >> theRot == theVec)

Foxpaw: That may be. I know that one of them does the coordinate rotation, which is basically what you said. It is possible that the other just does it by the reverse of that rotator.

Sir_Brizz: Is it too much to ask that someone PLEASE put some pictures up showing precisely how these all work? Imaginary directions and all are way too confusing to leave to the brain.

Tarquin: Care to nominate some that need a picture particularly badly?

Sir_Brizz: Well, I think there should at least be one explaining several at a time. I'm trying to figure out exactly how "...find where A is in relation to B?" works exactly.

Related Topics


Category How Do I
Refactor Me

The Unreal Engine Documentation Site

Wiki Community

Topic Categories

Image Uploads

Random Page

Recent Changes

Offline Wiki

Unreal Engine

Console Commands

Terminology

Mapping Topics

Mapping Lessons

UnrealEd Interface

Questions&Answers

Scripting Topics

Scripting Lessons

Making Mods

Class Tree

Questions&Answers

Modeling Topics

Questions&Answers

Log In