In motion design, timing is everything. Whether you’re animating a logo reveal, orchestrating particle bursts, or building complex procedural sequences, the ability to control when clones activate can make or break the rhythm of your animation.
The Weights by Time Effector, originally scripted by Iain Greenhalgh, is a Python‑based Cinema 4D tool that gives designers precise control over clone weighting based on time. Instead of relying solely on MoGraph’s built‑in delay or step effectors, this script allows you to map clone weights to specific time ranges, opening up a world of sequencing possibilities.
✨ What It Does
- Time‑Based Weighting Each clone is assigned a weight value that evolves over a defined duration. This makes it possible to stagger animations across a sequence rather than triggering everything at once.
- Forward & Reverse Playback Choose whether clones activate in order (forward) or in reverse. Perfect for creating mirrored animations or reversing sequences without re‑rigging.
- Flexible Offsets Add global offsets or per‑clone frame offsets to fine‑tune timing. This lets you create cascading effects where clones trigger one after another.
- Ease Controls Apply easing curves to weight transitions, ensuring smooth ramps rather than abrupt changes.
- Randomization Shuffle clone activation order with a seedable randomizer, giving you reproducible but organic variations.
🎨 Creative Applications for Motion Designers
- Logo & Text Reveals Animate letters or logo elements appearing one by one, with customizable timing and easing.
- Particle Bursts Control when particles “come alive” in a sequence, creating waves or pulses of activity.
- Procedural Animations Use weights to drive other effectors or fields, orchestrating complex procedural behaviors with precise timing.
- Cinematic Transitions Build wipes, cascades, or ripple effects where clones activate in sequence, adding rhythm to transitions.
- Generative Art Randomize activation order to produce evolving, unpredictable patterns that feel organic.
⚙️ How It Works
The script calculates start and finish times for each clone based on user‑defined parameters like clone duration, offsets, and easing. It then maps the current timeline position into a weight value between 0 and 1 using Cinema 4D’s RangeMap utility.
Weights are stored in the MoGraph data array (MODATA_WEIGHT), meaning they can influence visibility, effectors, shaders, or any parameter that responds to weight values.
🌍 Why It Matters
MoGraph’s native tools are powerful, but they often lack fine‑grained temporal control. The Weights by Time Effector fills that gap, giving motion designers a way to sequence animations with surgical precision. It’s especially valuable in broadcast graphics, UI motion, and procedural art, where timing and rhythm define the aesthetic.
🔮 Final Thoughts
The Weights by Time Effector is a deceptively simple script that unlocks complex sequencing workflows. By controlling clone weights over time, designers can choreograph animations that feel intentional, rhythmic, and alive.
For motion designers who thrive on timing and rhythm, this tool is a must‑have addition to the Cinema 4D toolkit.
🛠️ Core Capabilities of the Script
- Time‑based clone weighting Each clone gets a weight value that evolves over a defined time window. This weight can drive visibility, influence other effectors, or control parameters like scale, color, or position.
- Sequential activation Clones can be triggered one after another, either forward or in reverse order, creating cascades or ripple‑like animations.
- Offset control You can add global offsets or per‑clone frame offsets, which lets you stagger activation and create more complex timing patterns.
- Ease mapping The script uses
RangeMapwith easing, so transitions between weight values can be smooth (ease in/out) or linear, depending on your choice. - Randomization With the shuffle option, you can randomize the order in which clones activate, while still keeping it reproducible via a seed value.
🎨 Creative Uses for Motion Designers
- Logo/Text Reveals Animate letters or logo elements appearing one by one, with smooth easing and controlled timing.
- Particle Waves Trigger particles in sequence to create waves, pulses, or cascading bursts.
- Procedural Animations Drive other effectors (like Scale, Color, Shader) using weights, so clones gradually change properties over time.
- Reverse Sequences Flip the order of activation for mirrored or rewind‑style animations without re‑rigging.
- Organic Variations Randomize activation order to break up uniformity, producing more natural, less mechanical motion.
- Layered Timing Systems Combine this effector with others (like Delay or Step) to build multi‑layered timing rigs where clones respond to both sequential and procedural rules.
🔮 Why It’s Powerful
This script essentially gives you temporal choreography over your clones. Instead of everything happening at once, you can design when each element comes alive, how smoothly it transitions, and whether the order is predictable or chaotic. It’s like having a conductor’s baton for your MoGraph orchestra.
👉 In short: this script is all about sequencing and rhythm. It doesn’t move clones directly, but it controls their weights over time, which you can then use to drive any MoGraph parameter. That makes it a versatile backbone for logo reveals, particle systems, procedural art, and broadcast graphics.
import c4d
import random
from c4d.modules import mograph as mo
from c4d import documents as docs, utils
#weights clone by time - (c) Iain Greenhalgh 2013
def main():
md = mo.GeGetMoData(op)
if md==None: return False
time = doc.GetTime()
reverse = op[c4d.ID_USERDATA,5]
currentTime = time.Get()
cnt = md.GetCount()
cloneDuration = op[c4d.ID_USERDATA,3].Get()
offset = op[c4d.ID_USERDATA,2].Get()
fOffset = op[c4d.ID_USERDATA,1].Get()
ease = op[c4d.ID_USERDATA,4]
totalDuration = cnt * cloneDuration
randomise = op[c4d.ID_USERDATA,6]
ranSeed = op[c4d.ID_USERDATA,8]
warr = []
if reverse:
for i in xrange(0, cnt):
startTime = cloneDuration * i + (i * fOffset) + offset
finishTime = startTime + cloneDuration
warr.append(utils.RangeMap(currentTime, startTime, finishTime, 0.0, 1.0, True, ease))
else:
for i in reversed(xrange(0, cnt)):
startTime = cloneDuration * i + (i * fOffset) + offset
finishTime = startTime + cloneDuration
warr.append(utils.RangeMap(currentTime, startTime, finishTime, 0.0, 1.0, True, ease))
if randomise:
random.seed(ranSeed)
random.shuffle(warr)
md.SetArray(c4d.MODATA_WEIGHT, warr, True)
return True