I’ve been thinking about ways in which rigs can be made to have faster viewport playback without sacrificing functionality and would be keen to hear your experiences if you’re willing to share them. I’ll welcome all comments but specifically I’d like to know how modular rigs can be made lighter as they are implicitly more complex and heavier due to their flexibility.
One idea I had, which I think would be difficult to implement, would be to do a post-build flattening of the modular rig into a hierarchy which you would associate with one which had been “hand built”, I’d draw a comparison to collapsing all layers in Photoshop.
Avoiding expressions like the plague is always the first step. I wrote a function where I could input basic expressions into it and it would create the expression using render nodes. Any amount of Subtract/Addition/Multiply/Divide operations combined with Clamping/Inverting/Negating the values, all with incoming connections if needed. Saved a lot of time. Even when only using expressions for simple things like visibility switches, removing every last one of them from the rig improved it by about 30fps.
Remember you can also turn node evaluation off, so certain parts of the rig can be disabled/enabled for faster playback. In my main rig there’s the option to completely disable all face nodes and all secondary deformation nodes such as twist bones and elbow bones. This is done via a picker/control panel, instead of live connections- custom attributes attached to every relevant node mean it’s easy to cycle through the scene and detect which ones need disabling.
You’re right that generally rigs built using a modular rigging approach tend to come with extra fat. Trimming those out is usually fine but its unlikely to be the bottleneck of performance (depending of course on how far the tool goes when creating structural nodes).
Twiggy is spot on with regards to avoiding expressions at all costs. Another way is to move your rig’s functionality into compiled code. Consider that building rigs is like using mechano - each element forms part of a larger function but you ultimately pay a cost for each individual node in the graph. Many nodes will also do far more than you need for the operation its providing - again adding more cost. Taking a higher level piece of functionality and writing it out in C++, implementing it as a dedicated node should (depending on how its written and what it is doing) start to give you far better performance as the DG becomes far simpler. You also get the side benefit of being able to debug rig behaviour which is a great benefit.
That is an over-simplification though as you have to also factor in that Maya uses lazy evaluation methods to ensure a reasonable performance level. This means that if you have a node graph where most of your nodes are not actually being re-calculated then you’d end up paying a higher cost by compiling it all into a high level node. Equally, I don’t know how the parallel graph evaluation effects the impact of this approach.
Going back to your specific question about modular rigging and ways to simplify it, it very much comes down to the specific tool. Removing the redundant nodes is actually very simple if that was being considered at the time the tool was being written (the key is ensuring each node that could be trimmed is marked as such etc). In a scenario where nothing is marked the risk of removing objects in a rig after construction is probably quite high.