We can use the global Animator to animate properties. This lets us set a start value an end value, a duration and an interpolation curve for the changing values to follow.
Animating Properties with Script
First, How to think about it: Animating through Script is Just Like Animating Manually with Timelines:
You can think of this simple animation script as the equivalent of animating on the timeline...but its being done on the fly / whenever your script says so. Things to think about when reading below:
- "addKeyClip" is the equivalent of adding a "New Key Track" on a property in the Property Editor. Technically you're adding a temporary keytrack that goes away after the animation has occurred.
- "addKey" is the equivalent of double clicking or pressing f8 to add key frames on the timeline.
- "setKeyInterpolator" is the equivalent of right clicking between two keys on the timeline and setting your value interpolation for that interval. Setting interpolation is technically optional.. if you don't set it, the default is "linear".
- In your animation function you will feed in:
- a time value 'duration'
- a property value to change to
Think of this as, the value for my property to animate to over this duration.
A reminder image of the key parts of the timeline animation process.
How to Setup and Write the Animation Script:
1. We Animate a Value's "Property Object" not the "Value" itself:
When we want to animate a property value, we need to pass into the Animator's animation function the property object and not the property value. What do we mean by "property object"? Think of it as the container for the value: accessing the 'property object' gives the system the exact place to go every frame as it sets and resets the value. Here's how we can understand the difference between the two cases.
For instance, here's a non-animating example where we can access a property value directly:
obj.active vs obj:getActiveProperty()
obj.active = false
As the object enters a trigger its active property is set immediately to the value false.
Now let's see the animated way...
Here's an example of animating the active property of the object:
clip = getAnimator():createKeyClip(obj:getActiveProperty())
In this example, we set the active property to 'false' after 2 seconds. The 'createKeyClip' function requires the active property object itself. Calling
'getAnimator():createKeyClip(obj.active) would not work as the value (true/false) would get passed in which is not what 'createKeyClip' wants.
obj.active vs obj:getActiveProperty()
More examples of how you access a 'Property Object' differently than the value itself:
- obj:getActiveProperty() vs obj.active
- obj:getColorProperty() vs obj.color
- skySpace:getTimeOfDayProperty() vs skySpace.timeOfDay
Example: Animating Color:
Here's another example animating an object's color from its current color:
clip = getAnimator():createKeyClip(obj:getColorProperty())
Set Several Keyframes at Once:
Here's an example of animating a box's dimensions to get bigger and then return to the original size:
clip = getAnimator():createKeyClip(obj:getMeshModel():getShape():getDimensionsProperty())
current_dimensions = obj:getMeshModel():getShape().dimensions
clip:addKey(seconds(1), current_dimensions + vector3(0.1,0.1,0.1))
Change the Interpolation
We can also change the interpolator used between keys to control how the value animates. Here's an example of changing a Sphere's radius via the Elastic Ease In interpolator:
clip = getAnimator():createKeyClip(obj:getMeshModel():getShape():getRadiusProperty())
clip:addKey(seconds(0.3), obj:getMeshModel():getShape().radius + 0.2)
'setKeyInterpolator()' will define the interpolator of any subsequent keys added.
Animating Transforms is slightly Different: Position, Rotation, Scale
Here's an example of animating an object's position when we interact with it:
clip = getAnimator():createPositionKeyClip(self)
clip:addKey(seconds(1), self:getWorldPosition() + vector3(0,1,0))
Notice we use 'createPositionKeyClip' instead of 'createKeyClip' and pass in the node itself as the function argument. In the above example, the object will be animated from its current position to a position 1 unit above it.
Here's an example that rotates the object 10 degrees, in a Bounce-Ease-In fashion:
clip = getAnimator():createRotationKeyClip(obj)
clip:addKey(seconds(1), obj:getWorldRotation() + vector3(0,math.deg(10),0))
- Note that the Animator will create animations relative to the Universe's timeline