Unity and Vector3, Quaternion, classes, structs, and instancesphamalainen/unity_intro... ·...
Transcript of Unity and Vector3, Quaternion, classes, structs, and instancesphamalainen/unity_intro... ·...
Unity and Vector3, Quaternion,
classes, structs, and instances
Assistant professor in computer games
Perttu Hämäläinen
Vector3 • A collection of three numbers: x,y,z.
• Can represent place, displacement, velocity – anything
with a 3d direction and magnitude
• Vector2 is the same, but with just x,y
• Vector1 = scalar, just a single number
(0,0)
Vector2 a = new Vector2(5,5);
(5,0)
(0,5)
y
x
Vector scaling (multiplication with scalar)
• Scalar multiplication only affects magnitude, not
direction
0,0
Vector2 a = new Vector2(3,1);
Vector2 b = a * 3;
or alternatively,
Vector2 b = a;
b.Scale(3);
Vector scaling example
• Make an object move forward 5 m/s
rigidbody.velocity = transform.forward * 5.0f;
• transform.forward is a unit vector (of magnitude 1.0),
points along the game object’s z axis. This gives us the
direction. To get the velocity vector, we scale the
direction appropriately.
Vector addition
0,0
Vector2 a = new Vector2(3,1);
Vector2 b = new Vector2(1,3);
Vector2 c = a + b;
Vector addition
0,0
Vector2 a = new Vector2(3,1);
Vector2 b = new Vector2(1,3);
Vector2 c = a - b;
• Remember that a – b = a + (-1.0 * b)
Vector addition and scaling example
• Translate an object without a rigidbody with a constant speed
independent of game frame rate. Code in Update()
transform.position += transform.forward * speed
* Time.deltaTime;
• transform.position and transform.forward are both Vector3
• transform.forward * speed is the velocity vector
• need to scale with Time.deltaTime to make motion
independent of game fps
Scaling the moved distance based on
Time.deltaTime
• Object moves at constant speed -> travelled distance
grows linearly as a function of time
distance
time (seconds)
distance per frame at 10 fps, deltaTime = 1/10
1.0 2.0
distance per frame at 1 fps,
deltaTime = 1
Vector addition and scaling example 2
• Place a camera behind and above this gameobject,
looking at this gameobject
camera.transform.position = gameObject.transform.position
- gameObject.transform.forward * 2.0f
+ Vector3.up * 2.0f;
camera.transform.LookAt(gameObject.transform.position);
• Vector3.up is a constant, equal to new Vector3(0,1,0).
Note that using uppercase Vector3 denotes the struct or
class instead of a specific instance (see next slide...)
• The transform.LookAt() method rotates the object so
that it’s z-axis (transform.forward) points at the target
Classes, structs and instances
• Related to how things are stored in computer memory
Memory:
Scale()
0,1,0
1,0,0
...
...
...
...
...
...
...
...
...
...
Vector3 (code, static
and const)
//Vector3 definition (C#)
struct Vector3
{
//global (static, const) data
void Scale(float scale)
{
...
}
static Vector3 up=new Vector3(0,1,0);
const Vector3 right=new Vector3(1,0,0);
//member variables
float x,y,z;
};
unused (free) memory
Classes, structs and instances • The new operator allocates instances in memory
• Class/struct data stored only once, member variables for each instance
Memory:
Scale()
0,1,0
1,0,0
1,2,3
3,2,1
...
...
...
...
...
...
...
Vector3
Vector3 a=new Vector3(1,2,3);
Vector3 b=new Vector3(3,2,1);
a (instance data)
b (instance data)
Classes, structs and instances
• Important! Vector3 is a struct (a value type). For
structs, a new instance is allocated and members copied
when assigning Vector3 c=b;
Memory:
Scale()
0,1,0
1,0,0
1,2,3
3,2,1
3,2,1
...
...
...
...
...
...
...
Vector3 struct data
Vector3 a=new Vector3(1,2,3);
Vector3 b=new Vector3(3,2,1);
Vector3 c=b;
a
b
c
Classes, structs and instances
• In this case, changing c doesn’t change b
Memory:
Scale()
0,1,0
1,0,0
1,2,3
3,2,1
10,2,1
...
...
...
...
...
...
...
Vector3 struct data
Vector3 a=new Vector3(1,2,3);
Vector3 b=new Vector3(3,2,1);
Vector3 c=b;
c.x=10; a
b
c
Classes, structs and instances
• If Vector3 was not a struct, but a class like GameObject,
only a reference would be allocated when assigning (=)
Memory:
Scale()
0,1,0
1,0,0
1,2,3
3,2,1
983241
...
...
...
...
...
...
...
Vector3
Vector3 a=new Vector3(1,2,3);
Vector3 b=new Vector3(3,2,1);
Vector3 c=b;
a
b
c (reference to b)
Classes, structs and instances
• To be more precise, the memory would look like this...
Memory:
Scale()
0,1,0
1,0,0
1,2,3
3,2,1
983241
983242
983242
...
...
...
...
...
Vector3
Vector3 a=new Vector3(1,2,3);
Vector3 b=new Vector3(3,2,1);
Vector3 c=b;
Vector 3 instance
Vector 3 instance
a (reference)
b (reference)
c (reference, equal to b)
Classes, structs and instances
• In this case, changing member variables of c changes b.
The references c and b denote the same object.
Memory:
Scale()
0,1,0
1,0,0
1,2,3
10,2,1
983241
...
...
...
...
...
...
...
Vector3 class data
Vector3 a=new Vector3(1,2,3);
Vector3 b=new Vector3(3,2,1);
Vector3 c=b;
c.x=10;
a
b
c (reference to b)
Classes, structs and instances
• Remember the difference, otherwise you’ll encounter
strange bugs
Memory:
Scale()
0,1,0
1,0,0
1,2,3
10,2,1
983241
...
...
...
...
...
...
...
Vector3 class data
Vector3 a=new Vector3(1,2,3);
Vector3 b=new Vector3(3,2,1);
Vector3 c=b;
c.x=10;
a
b
c (reference to b)
Classes, structs and instances
• However, we can make a copy by allocating a new
object and explicitly copying the data.
Memory:
Scale()
0,1,0
1,0,0
1,2,3
3,2,1
10,2,1
...
...
...
...
...
...
...
Vector3 class data
Vector3 a=new Vector3(1,2,3);
Vector3 b=new Vector3(3,2,1);
Vector3 c=new Vector3(b);
c.x=10;
a
b
c
Memory allocation and performance
issues
• You should avoid using new in FixedUpdate() or
Update() because otherwise you will get occasional
framerate drops because of memory allocation problems
(heap fragmentation, garbage collection).
• However, using new for structs doesn’t cause fps
glitches, because structs are allocated from stack
memory instead of heap, which is faster
Javascript and value types
class Vector3 extends System.ValueType
{
var x:float;
var y:float;
var z:float;
}
Quaternion = rotation
• Fast and intuitive use of Vector3 etc. requires
repetition.
Quaternion = rotation
• Fast and intuitive use of Vector3 etc. requires
repetition.
• Explaining how things like vector math work helps in
learning, but with enough repetition, we can learn, e.g.,
new verbs and grammar based on context only
Quaternion = rotation
• Fast and intuitive use of Vector3 etc. requires
repetition.
• Explaining how things like vector math work helps in
learning, but with enough repetition, we can learn, e.g.,
new verbs and grammar based on context only
• A quaternion is a mathematical tool for operating with
rotations. It’s a collection (in Unity, a struct) of 4
numbers: x,y,z,w.
Quaternion = rotation
• Fast and intuitive use of Vector3 etc. requires
repetition.
• Explaining how things like vector math work helps in
learning, but with enough repetition, we can learn, e.g.,
new verbs and grammar based on context only
• A quaternion is a mathematical tool for operating with
rotations. It’s a collection (in Unity, a struct) of 4
numbers: x,y,z,w.
• Quaternion math is difficult to understand, but using
Unity quaternions is fairly easy
Why quaternion instead of Euler angles
• 3d modeling packages, including Unity Inspector view,
let users manipulate rotation using Euler angles (rotation
around x, y and z angles)
• Internally, there’s some computational problems (gimbal
lock) -> most software use quaternions
• Unity allows you to convert between eulers and
quaternions
Quaternion examples
//rotate v (Vector3) 90 degrees around y axis using Eulers
v *= Quaternion.Euler(0,90,0)
//rotate v (Vector3) 90 degrees around a given axis (here Vector3.up)
v *= Quaternion.AngleAxis(90,Vector3.up)
//Rotate head partially to the direction of a target.
//In reality, we follow partly using eyes, partly by turning our head.
//Here, we limit the head turning to 45 degrees, assuming that we start
//from a neutral rotation. Slerp (spherical linear interpolation) returns
//a rotation that is between the given two rotations
Vector3 headToTarget = targetPosition – headTransform.Position;
Quaternion fullRotation = Quaternion.LookRotation(headToTarget);
Quaternion partialRotation = Quaternion.Slerp(headTransform.rotation,
fullRotation,0.5f);
headTransform.rotation = Quaternion.RotateTowards(headTransform.rotation,
partialRotation,45);
• Vector3 is rotated by multiplying it with a Quaternion.
About radians and degrees
• Some Unity rotation helpers assume that given angles
are in radians. 360 degrees = 2π radians
• π is in Unity Mathf.PI
• 0 radians = 0 degrees.
• 0.5π radians = 90 degrees
• π radians = 180 degrees
Summary
• Vector3 and Vector2 scaling and adding/subtracting
often needed
• Quaternion provides rotation utilities – need to know
how to use, don’t need to know the numbers inside.
• structs (value types) allocated from stack -> use when
possible, new Vector3() doesn’t have an additional cost
• Remember that for classes (reference types),
assignment only copies a reference