Jan 7, 2011

Interesting Expressions - After Effects Tip

Hey guys!
I thought today I'd post something up about After Effects.

Lately, I've fallen in love with expressions, their huge life-savers. Some replace your everyday keyframes, others cause indefinite automation, other methods link two controls together and others are just plain cool!

UPDATE: If you're new to expressions, check out my free ebook AE Expression Basics by clicking on the link. It's pretty short and straight forward and works by examples, and I worked to make it as fun but still informative as possible.

This post is still relevant though. So read through it after you go through the eBook!

If you don't know, expressions are code you type into a property like "position" or "scale" or, well, anything! You can insert math stuff and reference various controls throughout After Effects. Kind of like if FL Studio's parenting thing, but that's another story.

Though sometimes it does get out of hand...

To place an expression, just ALT-CLICK on the stopwatch! Keep in mind you can still apply keyframes. To remove, ALT-CLICK again.

So, here are some stuff to know:

Variables are extremely useful. I repeat EXTREMELY.
Variables are basically sets of words that you assign values for. They are mostly useful for cleaning up your expressions. Here's an example:

(thisComp.layer("Null 1").opacity + thisComp.layer("Null 2").effect("Offset")("Slider"))/thisComp.layer("Null 2").effect("Divider")("Slider")

This can look a lot cleaner if we did this:
Reference=thisComp.layer("Null 1").opacity
Offset=thisComp.layer("Null 2").effect("Offset")
Divider=thisComp.layer(Null 2").effect("Divider")("Slider")

(Reference + Offset)/Divider

See, a lot cleaner!
If ever there should be an error anywhere in the expression, or if we need to change anything, we can do it very easily. Also, if I wanted to change Offset to a different slider, all I have to do is select the Offset variable and just pick-whip the new variable that I want.

I remember when I was creating the Linear Scan animation preset I had so many reference values in my expressions that when I got tired I couldn't fix problems anymore. After cleaning things up like this (especially for Radial Scan), things were a lot easier.

While we're at it, it's also good to know that paragraphing doesn't matter. So the above expression could look like this:


Wiggle randomizes the value of that property by the amplitude defined at the rate defined. For example:
wiggle(.5,20) will adjust the position value by 20, 0.5 times per second.

One thing to remember about wiggle is that this change happens around the set value. So if, say, you're opacity was set to 50% and you applied wiggle with 20, it'd go to a max of 70% and min of 30%. But, if you changed opacity to 20%, then it'd wiggle between 0 and 40%.
Basically, you still have control over the general area of where the wiggle occurs.
This is especially good when applied to camera's position/orientation. The next time you run some animation in 3D space, set all the keyframes you require and just add something like wiggle(.5,10) to the Orientation, and you've got yourself some nice camera-shake.

loopOut(TYPE , NUMBER)
loopOut and loopIn loops your keyframes.
If say you had 2 keyframes moving an object from the left to the right, using loopOut("pingpong",1) would make the object move back and forth until the layer's time is over in the timeline. Alternatively, loopOut("cycle",1) would make it move from point A to B then snap it immediately back to A and continue the animation.

What's the difference between loopOut and loopIn? Well, the NUMBER you type as the second variable determines how many of the keyframes are looped. If you use loopOut, it repeats the last keyframes starting from that number.
Lemme explain better: If you had 5 keyframes, loopOut("cycle",3) would cycle the last 4 keyframes, while loopIn("cycle",3) would cycle the FIRST 4 keyframes. At least that's how I understand it. I always use LoopOut since most of the time my looped properties have 2 keyframes.

This is especially good when used to make objects flash continuously (if applied to Opacity), move back and forth (if applied to Position) or throb (to Scale).

if(X) {Y} else {Z}
If-else is a boolean expression. If you've worked in any programming environment, you'd understand this, else just work with me here.

That last statement basically explains exactly what if-else does.

Here's an example of an expression set to the Rotation value:

if(opacity < 50) {90} else {180}

Basically, this means that if the opacity is less than 50, then the rotation will be set to 90.
But if it is not less than 50, then the value will be 180.

If the condition in the first set of parentheses is true, it will use the value in the first set of wavy brackets (I don't know what {} are called). However, if the condition is false, it will use the value in the set after the word else.

If this is true, do this, otherwise/else do this.

That's the statement I use when working with expression.
You could also look at the statement I used at first:
if(worked in programming enviromnent) {you'd understand} else {work with me}

Note that IF cannot be used inside a variable. It has to be standalone.
Also, if you'd like your condition to have two values working, use &&
         if you'd like your condition to be equal to a specific value, use ==

if(opacity < 25 && scale > 100) {90} else {180}

I'm sure you can figure that one out.
If is especially useful if you'd like something to animate with something else. If you'd like to look into more, learn about Linear. Very useful.

Here's a good example of these expressions in use:

I've created a new Angle Control and Checkbox control to a Null. I then link the Null's rotation to the Angle Control then rename it "Rotation". The checkbox control is "Loop"
I create 2 keyframes on Angle 1 second apart. The first if set to 90 while the second is set to 270.

What I want to happen is that if my Angle Control has 2 keyframes, it will continuously pingpong between the two values. Otherwise, it's going to rotate continuously at 1 revolution per second.
Before you continue reading, try it out yourself.

Okay, so here's how I did it.
I go into Angle Control and type this:


if(looping == 1) {loopOut("pingpong",1} else {time*360}

Look at the if explanation above if you don't understand this.

The immediate problem we're going to face is that if we remove the keyframes from Angle, the expression is going to hang and be disabled. So to prevent this problem from happening, we can go into the checkbox control and add this expression:

if(effect("Rotation")("Angle Control").numKeys < 2) {0} else {value}

Let me breakdown this expression.

effect("Rotation")("Angle Control").numKeys < 2 means the number of keyframes of Rotation's Angle Offset should be less than two. That's my condition.

If the condition is true (there are less than two), then the checkbox's value will be 0, which is off.
If the condition is false (there are two or more), then the checkbox's value will be the value set by the user.

The reason I used VALUE rather than 1 is because if the keyframes are more than 2, the checkbox will ALWAYS be on. I want to give some room for automation or changes. In this case, I want to be able to turn this on/off if the condition is false.

Get it now?

See if you can figure this image out and tell me exactly what's happening by dropping a comment below.
In case you can't see it, here it is:



if(auto==1) {if(reverse==1){rotator*-1} else {rotator}) else {offset+180};

If you have any questions, drop them in the comment section.
For more info on expression, go to Help > Expression Reference... in AE. (that's how I learnt 'em)




  1. Is there any way to move a layers "start" time through an expression?

  2. Expressions usually set a specific value of a property. You can't actually change something outside the property (like you can't set an expression in Opacity that changes Scale).
    If you'd like to change the start time, look into scripts.

    Thanks for the comment. Hope this helps.

  3. Nicholas SchwanklMay 24, 2015 at 8:31 PM

    try valueAtTime