MoonAnimator2 Camera Cutscene Problem

  1. I want to fix the in game camera of the cutscene

  2. In game cutscene camera doesn’t correspond to the MoonAnimator2 Camera.
    In game camera is slower than the actual camera in MoonAnimator2

  3. I tried skipping frames but no luck maybe I did it wrong…

1st video in MoonAnimator2 Scene :

2nd video in game scene :

This is the script i have so far

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Workspace = game:GetService("Workspace")

local FarmerWinEvent = ReplicatedStorage.RemoteEvents:WaitForChild("FarmerWin")
local SurvivorWinEvent = ReplicatedStorage.RemoteEvents:WaitForChild("SurvivorWin")

-- Table to store playing animations
local animationTracks = {}

-- Function to play animations for models
local function playModelAnimations(isFarmerWin)
	local models = {}

	if isFarmerWin then
		-- Farmer Win: Use models 1-10 for Survivors and "Farmer" for the Farmer
		for i = 1, 10 do
			local survivor = Workspace:FindFirstChild("Survivor" .. i)
			if survivor then
				table.insert(models, survivor)
			end
		end

		local farmer = Workspace:FindFirstChild("Farmer")
		if farmer then
			table.insert(models, farmer)
		end
	else
		-- Survivor Win: Use models 11-20 for Survivors and "Farmer1" for the Farmer
		for i = 11, 20 do
			local survivor = Workspace:FindFirstChild("Survivor" .. i)
			if survivor then
				table.insert(models, survivor)
			end
		end

		local farmer = Workspace:FindFirstChild("Farmer1")
		if farmer then
			table.insert(models, farmer)
		end
	end

	-- Play animations for each model
	for _, model in ipairs(models) do
		local humanoid = model:FindFirstChildOfClass("Humanoid")
		if humanoid then
			local animation = model:FindFirstChild("Animation") -- Look for the "Animation" object

			-- Play the animation if found
			if animation and animation:IsA("Animation") then
				local animTrack = humanoid:LoadAnimation(animation)
				animTrack:Play()

				-- Store the animation track for cleanup
				animationTracks[model] = animTrack
			else
				warn("[DEBUG] Animation not found or invalid in model:", model.Name)
			end
		end
	end
end

-- Function to stop animations for models
local function stopModelAnimations()
	for model, animTrack in pairs(animationTracks) do
		if animTrack then
			animTrack:Stop()
		end
	end
	-- Clear the animationTracks table
	animationTracks = {}
end

-- Function to play the cutscene
local function playCutscene(sceneFolder, isFarmerWin, totalDuration)
	local camera = Workspace.CurrentCamera
	camera.CameraType = Enum.CameraType.Scriptable

	-- Get the Frames folder
	local frames = sceneFolder:FindFirstChild("Frames")
	if not frames then
		warn("[DEBUG] Frames folder not found.")
		return
	end

	-- Sort frames numerically
	local frameKeys = frames:GetChildren()
	table.sort(frameKeys, function(a, b)
		return tonumber(a.Name) < tonumber(b.Name)
	end)

	-- Calculate time per frame to match the given total duration
	local frameCount = #frameKeys
	local timePerFrame = totalDuration / frameCount

	-- Start animations
	playModelAnimations(isFarmerWin)

	-- Play each frame with the calculated delay
	for i = 1, frameCount - 1 do
		local currentFrame = frameKeys[i]
		local nextFrame = frameKeys[i + 1]

		-- Ensure both frames are valid CFrameValues
		if currentFrame:IsA("CFrameValue") and nextFrame:IsA("CFrameValue") then
			local startCFrame = currentFrame.Value
			local endCFrame = nextFrame.Value

			-- Interpolate between frames over timePerFrame
			local startTime = tick()
			while tick() - startTime < timePerFrame do
				local alpha = (tick() - startTime) / timePerFrame
				camera.CFrame = startCFrame:Lerp(endCFrame, math.min(alpha, 1))
				wait(0.01) -- Smooth transitions
			end
		else
			warn("[DEBUG] Invalid frame at:", currentFrame.Name, "or", nextFrame.Name)
		end
	end

	-- Stop animations after the cutscene duration
	task.wait(totalDuration)
	stopModelAnimations()

	-- Reset the camera after the cutscene
	camera.CameraType = Enum.CameraType.Custom
end

-- Connect to the FarmerWin RemoteEvent
FarmerWinEvent.OnClientEvent:Connect(function()
	-- Play the FarmerWinScene cutscene (2.52 seconds)
	local farmerWinScene = ReplicatedStorage:FindFirstChild("WinCutscenes"):FindFirstChild("FarmerWinScene")
	if farmerWinScene then
		playCutscene(farmerWinScene, true, 2.31)
	else
		warn("[DEBUG] FarmerWinScene not found in ReplicatedStorage.")
	end
end)

-- Connect to the SurvivorWin RemoteEvent
SurvivorWinEvent.OnClientEvent:Connect(function()
	-- Play the SurvivorWinScene cutscene (4.8 seconds)
	local survivorWinScene = ReplicatedStorage:FindFirstChild("WinCutscenes"):FindFirstChild("SurvivorWinScene")
	if survivorWinScene then
		playCutscene(survivorWinScene, false, 4.48)
	else
		warn("[DEBUG] SurvivorWinScene not found in ReplicatedStorage.")
	end
end)

Could it be an FPS difference?

1 Like

this slow motion cutsense

-- Function to play the cutscene with slow motion
local function playCutscene(sceneFolder, isFarmerWin, totalDuration)
	local camera = Workspace.CurrentCamera
	camera.CameraType = Enum.CameraType.Scriptable

	-- Get the Frames folder
	local frames = sceneFolder:FindFirstChild("Frames")
	if not frames then
		warn("[DEBUG] Frames folder missing in:", sceneFolder.Name)
		return
	end

	-- Sort frames numerically
	local frameKeys = frames:GetChildren()
	table.sort(frameKeys, function(a, b)
		return tonumber(a.Name) < tonumber(b.Name)
	end)

	-- Calculate time per frame to match the total duration
	local frameCount = #frameKeys
	local timePerFrame = frameCount > 1 and totalDuration / (frameCount - 1) or 0

	-- Define slow-motion settings
	local slowMotionFrames = {3, 4, 5} -- Frame numbers to apply slow motion
	local slowMotionFactor = 2 -- Slow motion is twice as slow

	-- Start animations
	playModelAnimations(isFarmerWin)

	-- Play each frame with dynamic timing
	for i = 1, frameCount - 1 do
		local currentFrame = frameKeys[i]
		local nextFrame = frameKeys[i + 1]

		-- Ensure both frames are valid CFrameValues
		if currentFrame:IsA("CFrameValue") and nextFrame:IsA("CFrameValue") then
			local startCFrame = currentFrame.Value
			local endCFrame = nextFrame.Value

			-- Adjust time per frame for slow-motion frames
			local adjustedTimePerFrame = table.find(slowMotionFrames, i) and timePerFrame * slowMotionFactor or timePerFrame

			-- Interpolate between frames over adjustedTimePerFrame
			local startTime = tick()
			while tick() - startTime < adjustedTimePerFrame do
				local alpha = (tick() - startTime) / adjustedTimePerFrame
				camera.CFrame = startCFrame:Lerp(endCFrame, math.clamp(alpha, 0, 1))
				task.wait(0.01)
			end
		else
			warn("[DEBUG] Invalid frame at:", currentFrame.Name, "or", nextFrame.Name)
		end
	end

	-- Wait for the cutscene to complete
	task.wait(totalDuration)
	stopModelAnimations()

	-- Reset the camera after the cutscene
	camera.CameraType = Enum.CameraType.Custom
end

-- Function to play the cutscene with customizable slow motion
local function playCutscene(sceneFolder, isFarmerWin, totalDuration, slowMotionSettings)
	local camera = Workspace.CurrentCamera
	camera.CameraType = Enum.CameraType.Scriptable

	-- Get the Frames folder
	local frames = sceneFolder:FindFirstChild("Frames")
	if not frames then
		warn("[DEBUG] Frames folder missing in:", sceneFolder.Name)
		return
	end

	-- Sort frames numerically
	local frameKeys = frames:GetChildren()
	table.sort(frameKeys, function(a, b)
		return tonumber(a.Name) < tonumber(b.Name)
	end)

	-- Calculate time per frame to match the total duration
	local frameCount = #frameKeys
	local timePerFrame = frameCount > 1 and totalDuration / (frameCount - 1) or 0

	-- Unpack slow-motion settings
	local slowMotionFrames = slowMotionSettings and slowMotionSettings.frames or {}
	local slowMotionFactor = slowMotionSettings and slowMotionSettings.factor or 1

	-- Start animations
	playModelAnimations(isFarmerWin)

	-- Play each frame with dynamic timing
	for i = 1, frameCount - 1 do
		local currentFrame = frameKeys[i]
		local nextFrame = frameKeys[i + 1]

		-- Ensure both frames are valid CFrameValues
		if currentFrame:IsA("CFrameValue") and nextFrame:IsA("CFrameValue") then
			local startCFrame = currentFrame.Value
			local endCFrame = nextFrame.Value

			-- Adjust time per frame for slow-motion frames
			local adjustedTimePerFrame = table.find(slowMotionFrames, i) and timePerFrame * slowMotionFactor or timePerFrame

			-- Interpolate between frames over adjustedTimePerFrame
			local startTime = tick()
			while tick() - startTime < adjustedTimePerFrame do
				local alpha = (tick() - startTime) / adjustedTimePerFrame
				camera.CFrame = startCFrame:Lerp(endCFrame, math.clamp(alpha, 0, 1))
				task.wait(0.01)
			end
		else
			warn(("[DEBUG] Invalid frame at: %s or %s"):format(currentFrame.Name, nextFrame.Name))
		end
	end

	-- Stop animations immediately after the last frame
	stopModelAnimations()

	-- Reset the camera after the cutscene
	camera.CameraType = Enum.CameraType.Custom
end

Based on this i found a solution. Thank you!

Your welcome :slight_smile:
ertshjio0rtyghjb5rtfjopnght