Visulie ─ A Novel, All-Purpose Animation, Data, and Effects Suite

Skip to 2:03 in the following video:

Notice how there are multiple attachments in a part that’s outside the rig? That can be animated using Visulie.

However, in your example, it is not possible (without some workarounds) since there’s a Motor6D.

Visulie isn’t a plugin to animate your typical rigs (rigs with physics constraints). Visulie is a plugin to animate “pseudorigs” (rigs without physical constraints). Think of explosions, a tree falling, or loading screen animations.

Does this also apply to the texture change fuction
(I assume so I am just making sure)

Yes, you can animate textures by assigning different textures to the texture or image of properties.

By the way, what is the ‘technical workaround’ mentioned above?
Im just a bit curious.

1 Like

The plugin doesn’t allow animating physics constraints, so attempting to import the rig with them will fail. Fortunately, loading an animation only checks for required items. If there are more items than necessary, they will be ignored. To leverage this, you can remove the Motor6D, then animate it. Then load the animation on the tool during runtime.

Thank you for the help.
I will be purchasing this plugin.

This is definitely one of my favourite plugins!

I do have 2 requests:

  • Have a button/toggle that will create the whole setup of the animation including placing the rig back in the world, Visulie script in replicated storage and Load Animation to rig script with the starting Cframe to be the rigs location. Just to streamline the process for small fun stuff around a game.

  • When I have a selected items and click “create animation” Can it put the selected items into the “Rig” folder (not really needed, When I first started using the plugin I was a bit confused on what to do and didn’t realise it created a folder)

1 Like

Are there any other way to obtain this plugin? Store purchases are not yet supported in my country.

These are great suggestions! I’ve definitely pondered some these before, but here are my thoughts:

Assuming you mean that unloading the animation won’t “delete” the rig, is there a reason why the rig couldn’t be copied at the first keyframe?
I have tried this feature with the legacy version of Visulie, but there are many edge cases that make what should be placed back in the world unclear:

  • Animation was moved from one place to another
  • Items were added/removed from the rig
  • New ROOT* instances added/removed
  • ROOT* instances moved
  • Items inside the rig were rearranged

* ROOT instances are topmost instances in the hierarchy
The best option right now is simply to copy the rig at the zeroth frame, or make a duplicate before importing.

Right now, exported modules are parented to the workspace. Since Visulie exports modules, there are many coexisting places a user can store them, even in the same game. If you think that it’s a large enough hassle, I’ll consider adding a feature like this!

This feature was a challenge I tackled for an embarrassingly long time during the plugin rewrite. While I understand the convenience of simply loading animations on a rig without providing a CFrame location, I ultimately concluded that this was not possible.

Since there can be many ROOT instances in a rig (and so you are loading animations on multiple objects), what if each one were moved around? How would we know which instance to base the location on? I’ve thought about adding a “best guess” feature, where the CFrame of an animation is “guessed” based on the existing positions of the parts. However, I realized that it was slightly costly in terms of performance, and if the “guess” was wrong, you’ll end up playing your animation where you’re not supposed to be playing it.

Good point. I found that many users have voiced concerns about clarity issues, which is definitely frustrating. I’ll try to see if I can make this more clear, such as with a “search” feature in the “Help” section of the plugin to find what you are confused about faster.


Yes, you can PM me for details if you’re interested!

I think I need to rephrase the first suggestion.

So the goal of the first suggestion was more so that anyone without scripting knowledge can use it.

All of the first suggestion was only if the button/Toggle was clicked/enabled. Just want to make that clear because I like the CFrame in Load animation.

I think I was kind of jumping the gun with solutions more than the why the need.

I wanted the artists to be able to act independently with visulie. But by having to create scripts and manage the animations they will have to do more than what is expected.

hence the package generation where it will just be “Done animating; okay here’s it in game”. I don’t think the rig itself is important but the fact they can kinda treat the output like a marker to where it is going to happen. So for all intensive purposes it could just Be a part that is red representing the offset. Just thought the rig showing would of been more ideal. So what I’m really asking is just a button that would have everything built ready to go and can be reused and moved about with normal roblox controls.

I’m just going to refer to the end result as Package

Oh Right! I keep forgetting things can be scattered abound. I just kinda kept it in a model.

Nah it wasnt because it was a hassle, I just didnt want 50 of the same module clogging up the workspace if each Package had its own visulie api. and you could do fun things such as versioning with the name as visulie_v1_x_x.

1 Like

Thank you for the clarification! I’m starting to vaguely understand what the feature is, but I’m still a little confused :sweat_smile:.

If I’m understanding correctly, you want to export as a “package”, where it will run immediately inside the game, without any extra scripting, and at the location of a part. If this is the case, this is possible, with some considerations:

  • Automatic versioning only handles updating data modules, not the Visulie Renderer module (for now). So, when you version the data modules, the older Visulie Renderer will not be able to play the animation due to data version conflicts.
  • Multiple copies of the Visulie Renderer (of which contain hundreds of lines of code) isn’t very optimal, both memory and performance wise.
  • Without adding too much complexity within the editor, and ensure compatibility, how would animation properties (such as speed, framerate, looped, etc.) be handled in these packages?

On the surface level, I’m sure this feature wouldn’t be too difficult to implement. However, on the technical level, there may be some hurdles that one must jump through to get this working as smoothly as possible.

1 Like

That is basically the gist of it. Since trying to get an artist program at all is yucky. even a small amount. And to then also give them the flexibility to place their work across the map to enhance the game is the cherry on top.

  • Upon creating a Package Visulie will check if there is a current version in Visulie folder that is in replicated storage if the current version is not found make a new script named as the current version. that way it can check easier. Version could be handled by the package. I was thinking it would just have a script in there that would be set to Client (that way if they want it on server they can just change it to server). And in that script it will just play animation at the spot reference the local animation keys script and reference the version needed that is placed in Visulie folder.

  • Assuming the Renderer is the script that is created that contains the animation keyframes. 100% perfectly fine to have multiple copies of that Its worth the tradeoff imo. At that point it will be on the dev to fix. Since this is mainly for stuff already in the world. and not spawned in the hundreds. Like a fish swimming in the pond or a burger getting assembled stuff like that.

  • Could they just be attributes on the Package. so have everything as the default, 60fps, 1 times speed and looped = false. and then they can just change the attributes on the Package if they wanted something different. Just running the animation alone is good enough customization are a secondary thing (Maybe not looping that’s pretty important). This isn’t meant to replace the old way.

yeahh on paper things sound a whole lot easier.

After a bit of thinking, I don’t believe that this is a substantial enough feature to implement. Playing an animation requires a trivial amount of code:

local Visulie = require(path)
local NewAnimation = Visulie.new(args)
NewAnimation:Play()

I’m confident enough that the users would at least understand these few lines of code. If many users don’t find too many issues understanding the animation code snippet provided in the Animation Controller documentation:

...

-- Replace the humanoid with an animationcontroller
local humanoid = npcModel:FindFirstChildOfClass("Humanoid")
humanoid:Destroy()
local animationController = Instance.new("AnimationController")
animationController.Parent = npcModel

-- Create and load an animation
local animation = Instance.new("Animation")
animation.AnimationId = "http://www.roblox.com/asset/?id=507771019" -- Roblox dance emote
local animationTrack = animationController:LoadAnimation(animation)

-- Play the animation
animationTrack:Play()

I think it’s safe to say the three or so lines of code playing a Visulie animation would be more than simple enough.

1 line even

require(visulie).new(args):Play()

vs

That would not be called 1 line (even though that would fit in one line). The reason being that lines tend to be measured either bu how many actions are taken or line length.

Otherwise this is valid:

npcModel:FindFirstChildOfClass("Humanoid"):Destroy();Instance.new("AnimationController",npcModel):LoadAnimation(Instance.new("Animation")):Play()

which is technically 1 line but at it being a mess and needs to be split up.

require(workspace.visulie).new(require(workspace.Animation), CFrame.new(0,0,0)):Play()

So the full ^ needs to be split into multiple lines. Like FartedWayToHard did.

local visulie = require(workspace.visulie)
local Animation = require(workspace.Animation)

local newAnimation = visulie.new(Animation, CFrame.new(0,0,0)) 
newAnimation:Play()

I wasn’t going to reply since FWTH made up their mind. But the 1 line post was too much of a stretch and felt that I still need to defend the request.

2 Likes

Yeah makes sense, technically in lua you can put 5000 regular lines into one, but look at how short it is :slight_smile:

oh my god, this was SO WORTH my 10$. THANK YOU SO MUCH <3333333333

3 Likes

Thank you for making Visulie!

I’m trying to use Visulie to animate a 2D character made of ImageLabels inside a BillboardGui. The character is pre-built dynamically (different skins, clothes, etc), and I just want to animate its GuiObjects (position/rotation).

Right now, Visulie Editor seems to export a full module that rebuilds the entire hierarchy and instances when using the Visulie Renderer - which doesn’t work for my use case. Is there a way to export only animation data and apply it to existing instances? Or target a preexisting rig?

Appreciate any pointers - thanks for the great tool.

edit: Nevermind! I found the function Visulie.loadAnimation. This matched my use case perfectly. Only realized it was a thing after scrolled through this thread. It would be amazing if there was a proper documentation with search / lookups :sweat_smile:

3 Likes

Sorry!

Documentation and clarity is definitely a common concern. I’m taking a break from updating the plugin for now, but I’ll try my best to increase usage clarity in the future. Cheers!

Now I’m no expert but I’ll try making one. Please note that this is probably filled with errors.

Documentation (For the Renderer-ModuleScript)

(tags: docs, document, doc, info, functions, module, usage, how to, load, already existing)

Loading Animations

There are 2 ways you can load an animation:

  1. Renderer.new(data, origin, ParentContainer)
    Returns an animation instance holding a rig cloned from the given data after parenting it to ParentContainer and placing it at origin.
  2. data: Required module script of a saved animation
    origin (optional): CFrame describing the animated rigs position
    ParentContainer: Where the cloned rig should be located
  3. Renderer.loadAnimation(data, origin, rigDependencies)
    Returns animation instance connected to an already existing rig.
    data: Required module script of a saved animation
    origin: CFrame describing the animated rigs position
    rigDependencies: Reference to the already existing rig.

Renderer.getActiveAnimation(Instance)
Returns all animations that are currently active on instance




Documentation (For animation instances)

(tags: playing, play, run, show, load, pause, reposition, origin)

animation:Play()

Metamethod that plays the animation.


animation:Destroy(keepRig?)

Metamethod that destroys the animation instance.

keepRig: Decides wether or not the rig should be destroyed with the animation.

animation:Pause()

Metamethod that pauses the animation if it is running.


animation:Resume()

Metamethod that resumes the animation if it is paused.


animation:GetRigDependencies()

Returns the rig connected to the animation.


animation:SetTime(time)

Metamethod that sets the animation’s time.

time: frame of the animation to skip to?

animation:SetOrigin(newOrigin)

Metamethod that sets the animation’s position.

newOrigin: New CFrame / “Pivot” of the animation


animation:GetInstance()

Returns itself?


animation:PlayThenDestroy()

Plays the animation and destroys it once it is completed.


animation:GetEventReachedSignal(eventName)

Returns an RBXScriptConnection / “Signal” of the provided name.
eventName: The name of the event that you set and which to get a reference to.

2 Likes