Most optimal way to create a Facial Animation rig via drivers / Python, advice requested

Hello all, thank you for your time reading this.

I found a model online which seems to be the “Captain Sparklez” character in the game Minecraft Dungeons.
Most resources talking about these Minecraft based models are Maya based, so I have to do some reversed engineering to get the motor running in Blender, I`m sure we have all been here before.

By the looks of it, they animate the mouth / lower half of the face by swapping out different Mouth models, turning them visible or invisible based on a control rig.


The current version I recreated myself has the driver on the specific Mouth model, which checks a cursor`s local position on its parent.
This is working on one model, but it seems like it will be very opaque to troubleshoot when this gets applied to many more models.

Ideally, it seems like a better idea to have the script / driver constantly set on the cursor, having all the options in one clear list in one place.

That way, the Driver would also not auto-hide every time I move my cursor for troubleshooting, since it is attached to a mesh that I`m turning invisible.

Is this a pipedream, or too convoluted?
I would greatly appreciate any advise or help regarding this, my Google-fu is also failing me and I`m slowly puzzling this thing together during my lunch breaks :sweat_smile:

Right off the bat, one thing that will make this a lot easier is using the position of an Empty rather than the Cursor to drive this. That way, you can have an empty per character, no problem, and you can have this effect applied on all your characters at once, which you cannot do with the cursor. You can add an Empty from the Shift + A menu.

Your highly complex OR code can be tossed out entirely and replaced with this simple line:
(floor(1+posX) +.1) * floor(1+posZ)
To get rid of the floating point errors you might have seen in the other thread, you can wrap that in a int(v*100) where v is (floor(1+posX) +.1) * floor(1+posZ). This will give you results- in your case- from 101 to 4206, no decimals, so no need to worry about floating point errors.

Those two things will help tremendously, there’s probably more optimizations that can be made but it’s a start :slight_smile:

Ah wonderful, thank you very much!
Since this Driver system is self-taught, I have a hard time visualizing the steps that I need to take to set it up, but this should at least give me something to google again.

If you happen to have any video resources you could direct me to, regarding these constructions, it would be a cherry on top!

Hello Joseph, (And other lurkers),

Now that I have a bit of time to run through the comment, I have a few questions.

How is the position of an Empty different than using the position of any other item, aside cosmetics?

This sounds like the opposite of what I am trying to do?
An empty per character sounds like 26 empties for the 26 characters in the alphabet, rather than 1 to Drive them all.
Perhaps I am misunderstanding, English is not my first language.

As for the earlier mentioned “Google-fu”;
What is the industry name for the type of rig I am trying to build?
This would be useful for my own documentation, and to find more resources online regarding the process.

By using an empty, you don’t have to worry about an object with mesh data getting mixed up with something else. Empties are visual pointers- they’re specifically intended for tasks like this, as part of an interface without having attached data.

I mean character in your scene, or person- each person can have their own chart (your existing image) with an empty, driving the drivers for just that person.

I’m not the most familiar with industry terminology, hopefully someone else can answer that :slight_smile:

That clears that up, thank you Joseph.


(Please ignore the fact that I havent gotten around to change the posX code yet)
I just found out about Custom Properties, but even with those on the table, it seems I am always coming back to an approach where the “Code” to turn an object on/off is contained in the object itself, rather than the Empty/Cursor/Driver that I am manipulating.

There are many roads that lead to Rome, but if I want to change the cities name I`ll have to manually change all the road markers by traveling down every possible road, it seems.

Is this a correct statement, or am I missing something?

I appreciate all the help you have given me today, I am at least learning a few new things!

There should be a workaround to get what you’re looking for, but I’m a bit fuzzy on the exact details. Let me get back to you on this, unless someone else does first :slight_smile:


Perhaps this graphic clears up what direction my mind is at.
It keeps reverting back to how I’d tackle it in unity, haha!

Hi Joseph,
Using your code and some feedback from a friend, I arrived at the following:

ceil(posX) + (floor(posZ) *6)

Since my grid is 6*6, this will get me solid INT’s no matter the location, which I can place into a Custom Property with a Driver.
That way, all my mouth meshes just need to request the current value of the Custom Property and it should be -pretty easy- to scale when I need it to.

Either way, it is the solution I am going with for now.
Thank you again for all your help, you really made the end result more achievable!


I have found one final problem on the math front.
First of all, I’m not sure what the python driver logic is.
If the Scripted value becomes 1, it fires?

When I formulate my driver as “abs(mouthful-44) or abs(mouthful-31)”, I get strange results.

What would be the correct way to approach this?