[V2] Moon2Cutscene | Play Moon Animator 2 Files

Moon2Cutscene Version 2.1

What is Moon2Cutscene?

  • Moon2Cutscene is a free open source Moon Animator 2 run-time cutscene playback module

Where to get it?

  • You can get the module here for absolutely free
Documentation

Setting up

local moon2Cutscene = require(path.to.module)
local newCutscene = moon2Cutscene.new(file, map?)

the file can be found under ServerStorage.MoonAnimator2Saves
image

If given the map parameter, objects will be looked for under it. Optionally, you can use the replace method

newCutscene:replace(objIndex:number, newInstance:Instance)

This method will replace the object of the given index to a different one.
Example use case: Playing an animation on the player

local character = player.Character
character:PivotTo(startCFrame) -- pivot the player to the CFrame the cutscene should start (OPTIONAL)
newCutscene:replace(1, character) -- replace the appropiate index with the player's character

But wait, how do i know which index’s which?

  • You can use this snippet to easily find which index to replace:
for i,v in file.file.Items do
	local path = "game"
	for i, n in v.Path.InstanceNames do
	if i == 1 then continue end
		path ..= "."..n
	end

	print(`[{i}] {path}`)
end

Now, you want to ensure every object can be found via

newCutscene:waitForObjects()

My cutscene doesn’t play after adding this!

  • You have objects that can’t be found! Use the newCutscene:canFindObjects() method to debug:
local canFind, objectMissing = newCutscene:canFindObjecs()
if not canFind then
warn(objectMissing)
end

Perhaps you have an effect track? They must be manually created (atleast for now).
But fear not! This module got you covered, simply create a task and use the moon2Cutscene.subtitle(Text:string, properties:{}?) function!

Tasks

Firstly, we need to get the task object from the cutscene, i like to assing it to a variable.

local _task = newCutscene.task

and now, we add tasks at certain frames

local subtitleProperties = {
	Font = Enum.Font.Code
}

local frameNumber = 43 -- you dont need to set a variable, this is just for clarification

_task:register(frameNumber, function()
	moon2Cutscene.subtitle("this is an example subtitle!", subtitleProperties) -- REMEMBER: you only have to set the properties once, if you want them to change; make multiple property tables
end)

Now to playing the cutscene;

newCutscene:play()

as simple as that! The play method takes in an optional restart boolean parameter.

Manually stepping over the cutscene

newCutscene:setFrame(timeElapsed:number) -- time elapsed being the time that passed in (seconds * FPS)

Changing FPS

newCutscene.FPS = 30

Vignette

local removeFunction, ui = moon2Cutscene.vignette(image?) -- give an optional image, or use the default

print(ui) -- the vignette ui
removeFunction() -- removes the ui
-- usage example
_task:onEnd(moon2Cutscene.vignette()) -- this will make the vignette and automatically get rid of it after the cutscene ends!

Fade

-- Following the vignette, the moon2Cutscene.Fade(fadeInTime:number?, stayTime:number?, fadeOutTime:number?, Color:Color3?) function returns a function that starts the fade and the ui

local fade = moon2Cutscene.Fade(1, 1, 1)
fade()
_task:onEnd(fade)
old post

I’ve decided i’ll make a Moon Animator 2 File cutscene player
get here

documentation outdated, will maybe update later

What does this do?
it takes a Moon Animator 2 Animation file and play’s it out, not only Rig’s but also BaseParts and Models!

It supports :

  • Theese properties: CFrame, Color, Size, Material, Transparency, Reflectance, Anchored, CastShadow
  • Rigs
  • Animation FrameRate (this only affects the speed at which the animation moves)
  • Easing styles and directions
  • Cutscene camera (Built in Camera or part named “cutscene_camera”)
  • Animation events
  • Reversing (Possible by doing new.FPS = -new.FPS or any other negative value)
Documentation

cutscene.new(AnimationFile, map:Model?)

AnimationFile being the moon animation file found under ServerStorage.MoonAnimator2Saves
image

And map being an instance which will get copied and put into workspace
When setting a map the script will automatically look for objects under the same path but in the map. This skips the first 2 objects likely being game.Workspace

subtitle(text:string, properties:{}?)

subtitles do not automatically dissapear and must be manually removed via subtitle(“”)

createFadeFunction(fadeInTime:number?, stayTime:number?, fadeOutTime:number?, Color:Color3?): () → nil, ScreenGui

Returns a tuple with the function which will fade the screen and the GUI
Used as new:ended(cutscene.createFadeFunction())

createVignette(image:string?): () → nil, ScreenGui

Returns a tuple with the function which will remove the vignette GUI
Used as new:ended(cutscene.createVignette())
Note: The ui is made as soon as the createVignette function is called and will be removed when the returned function is called. The image label has a default image and an ImageTransparency of 0.5

new:play(restart:boolean?, secondsToWaitAfterFinished:number?, shouldClearTasks:boolean?)

Plays the cutscene (does not yield)
Restart being a boolean which determines whether or not the cutscene should start over.
secondsToWaitAfterFinished being a number to wait after the cutscene is finished
shouldClearTasks being a boolean which determines whether or not to run new:clearTasks()

new:stop()

Stops the cutscene (does not reset objects to default state)

new:reset()

Resets objects to default state

new:wait()

Yields untill cutscene stops playing (if its currently not playing, does not yield)

new:destroy()

Stops the cutscene (does not reset)
Removes the map and the metatable

new:ended(f:(self) → nil) :() → nil

Whenever the cutscene ends, calls the function f with the parameter self
Returns a function that disconnects this
Runs all functions in parralel, waits until all functions are finished to end cutscene

new:createTask(frame:number, fn:(map:Model) → nil)

Creates a task which is performed at a specified frame.
Tasks are removed after playing once
Tasks yield the cutscene but their functions do not!

new:clearTasks()

Clears all tasks

new:setFrame(timeElapsed:number)

timeElapsed being a float of time elasped, same thing as the frame.

new:setObject(index:number, object:Instance)

Overwrites the object to animate. Allows for animating the player, check code examples.

cutscene_camera

Naming a part “cutscene_camera” will automatically make the camera follow the part.
You can also add a Camera in the animation file.

Code Examples
local moon2Cutscene = require(path.to.module)
local cutscene = moon2Cutscene.new(script.file)

[...]

Fade example

local fade = moon2Cutscene.createFadeFunction(1, 1, 1)

fade() -- yields for 1 second
cutscene:play()
cutscene:ended(fade) -- fade out of cutscene

cutscene:wait() -- yield untill cutscene finished

Vignette example

local vignette, vingetteUi = moon2Cutscene.createVignette() -- vignette is created, altough; its image transparency is set to 0.5, lets change it!
vingetteUi.ImageLabel.Transparency = .7 -- changing image transparency
cutscene:play()
cutscene:ended(vignette ) -- remove the vignette after end

cutscene:wait() -- yield untill cutscene finished

setObject Example (Animating the player)

local character = game:GetService("Players").LocalPlayer.Character
character.PrimaryPart.Anchored = true -- if needed, anchor the player
character:PivotTo(playerPosition:GetPivot()) -- if needed, position the player

cutscene:setObject(1, character) -- set object 1 (in this case a rig) into the player, if you are unsure of the index you can print(self.objs)
cutscene:play()

cutscene:wait() -- yield untill cutscene finished
character.PrimaryPart.Anchored = false -- remember to unanchor the player

subtitles Example

local properties = {
	FontFace = Font.new("rbxasset://fonts/families/PressStart2P.json", Enum.FontWeight.Regular, Enum.FontStyle.Normal)
}

cutscene:createTask(100, function()
      moon2Cutscene.subtitle("text", properties)
end)

cutscene:play()
cutscene:wait()
moon2Cutscene.subtitle("") -- remove subtitles from screen

This module is still a work in progress and it lacks some features. Feedback appreciated!

This module is still a work in progress! Reply with anything you’d like to see in it!

45 Likes

TYSM!!! FOR MAKING THIS. i’VE NEEDED SOMETHING LIKE THIS FOR YEARS

4 Likes

No probs! Let me know if you need any features, i’d be glad to add them!

2 Likes

Fr tho I’ve needed a system like this for years

3 Likes

Update:

  • Bug fixes
  • Changes to the onEnd function
  • New createFadeFunction function
2 Likes

Now we have Moonlite and Moon2Cutscene as free exporting tools for Moon2, this is so swag.

5 Likes

Update:

  • bug fixes
  • Added support for Size, Material, Transparency, Reflectance, Anchored and CastShadow
2 Likes

Can you give us a demo script?

2 Likes

OR can you give us a rbxl for this

2 Likes

Yo the Camera FieldOfView didnt work

1 Like

neither did attachtopart work. Can you help?
How did your animation camera work

1 Like

Update :

  • Added support for camera and field of view
    (didnt realise moon animator had the camera built in lol)
1 Like

and, can you elaborate on attachToPart

1 Like

It’s a feature in the moon animator camera

1 Like

It allows you to go in it’s properties and select an instance to attach the MA camera to

1 Like

Can you add features like when it hits an animation event or when it hits a certain keyframe and there’s a keyframereached type of thing

1 Like

Update :

  • Added Animation Events used as:
    new:createTask(frame:number, fn:(map:Model) → nil)
    Tasks have to be remade for each play of the cutscene
    They can be removed by doing:
    new:clearTasks()
    The play function now has a 3rd argument shouldClearTasks:boolean? which will run the above function when true before playing the cutscene
    Tasks yield the cutscene but their functions do not
1 Like

Can you define the frame parameter?

1 Like

can you do slow motions cutscenes if u change the frame parameter with a tween?, or slowly change it?, you should make that a custom function

1 Like

The frame is a number the function will run at,
You can see the frame as shown in the picture:
image

1 Like