First person cutscene help

I’m trying to create a first person cutscene, something that changes the camera to the players head and temporarily disables their accessories in a renderstepped event. When the animation is finished, it disconnects it. Here is the following code.

local anim = script.waekup -- I know it's misspelled but its the correct path
local char = game.Players.LocalPlayer.Character
local animset = char:WaitForChild("Humanoid").Animator:LoadAnimation(anim)
local camera = game.Workspace.CurrentCamera
local connection

function cutscene()
	print("began")
	for i,v in ipairs(script.Parent:GetDescendants()) do
		if v:IsA("Accessory") then
			print("handle")
			v:WaitForChild("Handle").Transparency = 1
		end
	end
	camera.CameraType = Enum.CameraType.Scriptable
	camera.CFrame = script.Parent.Head.CFrame
end

connection = game:GetService("RunService").RenderStepped:Connect(cutscene)
animset:Play()
print("playing")
char.HumanoidRootPart.Anchored = true
animset.Stopped:Wait()
connection:Disconnect()
char.HumanoidRootPart.Anchored = false
camera.CameraType = Enum.CameraType.Custom
print("disconnected, returned to regular camera")

Instead of working properly, it outputs this:
image

the animation doesn’t play at all or the renderstepped thing. I have no idea what to do or how to fix this. The animation is set to Action4 and it is not looped. The script is in startercharacterscripts.

2 Likes

thats odd, I would try doing this instead

connection = game:GetService("RunService").RenderStepped:Connect(function(dt)
cutscene()
end)
2 Likes

It outputs the same thing like the picture above

Be aware of Mouths or facial features on Characters head, as they can obstructed the view.

So RunService is a loop, yeah. So is it Looping CameraType and a for loop!?
Try firing cutscene by itself once as:

cutscene()

And loop the Camera CFrame in RunService as:

connection = game:GetService(“RunService”).RenderStepped:Connect(function(dt)
camera.CFrame = script.Parent.Head.CFrame
end)

However your problem seems to be with the animation Stopping too soon or not playing at all. This is common and may be to do with lag or the loop messing up. I would try/recommend playing the Animation before starting the loop.

Example Code
local function cutscene()
	print("began")
	for i,v in ipairs(script.Parent:GetDescendants()) do
		if v:IsA("Accessory") then
			print("handle")
			v:WaitForChild("Handle").Transparency = 1
		end
	end
	camera.CameraType = Enum.CameraType.Scriptable
	connection = game:GetService("RunService").RenderStepped:Connect(function(dt)
       camera.CFrame = script.Parent.Head.CFrame
 end)
end

animset:Play() 
cutscene() -- Fire function after Animation plays
animset.Ended:wait() -- this works too :)
Connection:Disconnect() -- removes function connected to Connection
Camera.CameraType = Enum.CameraType.Custom

Extra:

Have Moon Animator2?

I would recommend checking this Article out then.

Code
local RunService = game:GetService("RunService")

local Character = game.Players.LocalPlayer.Character or game.Players.LocalPlayer.CharacterAdded:Wait()
local Camera = workspace.Camera

--local CurrentCameraCFrame = workspace.CurrentCamera.CFrame
local function cameraScene()
    Camera.CameraType = Enum.CameraType.Scriptable
	Connection = RunService.RenderStepped:Connect(function(DT)
		Camera.CFrame = Character.Head.CFrame
	end)
end
--Camera.CFrame = CurrentCameraCFrame	
animset:Play()
cameraScene()
animset.Ended:wait()
Connection:Disconnect()
Camera.CameraType = Enum.CameraType.Custom

All that accomplishes is calling a function when another function is called, instead of calling the initial function directly. :joy: That would do nothing but make the program just the tiniest bit more expensive.

@OP I doubt you need a RenderStepped at all for this. Just call the function and re-enable the stuff afterwards.

local anim = script.waekup
if game.Players.LocalPlayer.Character == nil then
    game.Players.LocalPlayer.CharacterAdded:Wait()
end
local char = game.Players.LocalPlayer.Character
local animset = char:WaitForChild("Humanoid").Animator:LoadAnimation(anim)
local camera = game.Workspace.CurrentCamera

function cutscene()
	print("began")
	camera.CameraType = Enum.CameraType.Scriptable
	camera.CFrame = script.Parent.Head.CFrame
	for i, v in ipairs(char:GetDescendants()) do
		if v:IsA("Accessory") == true and v:FindFirstChild("Handle") ~= nil then
			print("handle")
			v.Handle.Transparency = 1
		end
	end
end

cutscene()
animset:Play()
print("playing")
char.HumanoidRootPart.Anchored = true
animset.Stopped:Wait()
char.HumanoidRootPart.Anchored = false
camera.CameraType = Enum.CameraType.Custom
print("disconnected, returned to regular camera")

EDIT
Why does that “solution” have two likes? .-. It’s literally a non-solution and is complete garbage.

If I do that, I’m pretty sure the camera will update only once and stay at the position during when the function was called.

Simple and ezpz fix then – just run the camera code in a RenderStepped instead.

local anim = script.waekup
if game.Players.LocalPlayer.Character == nil then
    game.Players.LocalPlayer.CharacterAdded:Wait()
end
local char = game.Players.LocalPlayer.Character
local animset = char:WaitForChild("Humanoid").Animator:LoadAnimation(anim)
local camera = game.Workspace.CurrentCamera
local conn = nil

function cutscene()
	print("began")
	char.HumanoidRootPart.Anchored = true
	for i, v in ipairs(char:GetDescendants()) do
		if v:IsA("Accessory") == true and v:FindFirstChild("Handle") ~= nil then
			print("handle")
			v.Handle.Transparency = 1
		end
	end
	if conn == nil then -- We don't want to have multiple `RenderStep`s stacking now do we?
		conn = game:service("RunService").RenderStepped:Connect(function()
			camera.CameraType = Enum.CameraType.Scriptable
			camera.CFrame = script.Parent.Head.CFrame
		end)
	end
end

function stopCutscene()
	print("stop")
	char.HumanoidRootPart.Anchored = false
	for i, v in ipairs(char:GetDescendants()) do
		if v:IsA("Accessory") == true and v:FindFirstChild("Handle") ~= nil then
			print("handle")
			v.Handle.Transparency = 0
		end
	end
	if conn ~= nil then
		conn:Disconnect()
		conn = nil
	end
end

cutscene()
animset:Play()
print("playing")

animset.Stopped:Wait()
stopCutscene()
camera.CameraType = Enum.CameraType.Custom
print("disconnected, returned to regular camera")

This way the code’s less expensive to run.

1 Like

I didn’t bother testing anything, go yap yap yap if you like

Alright, I will! Yap yap yap yap yap yap yap yap yap.
Plot twist- I didn’t test the code that I’d written neither. DUN DUN DUN DUUUUN!!! :scream::scream::scream:
What does “testing” even have to do with identifying (at a glance) that your “solution” was a non-solution anyways?

@IndeedMythical Did anything change by using that latest bit of code? If not, you may need to look into a custom camera controller.

Screenshot 2024-02-28 174725
It finds the handles an does begin and things, but its just an extra way to achieve the same results as earlier. Nothing in the renderstepped happens and the animation doesn’t play.

I know it’s not a problem with the animation, I tried a script where I play it straight away and it works (without the camera or anything fancy, just playing the animation)

Playing the animation before still achieves the same results, no animation, renderstepped things don’t happen, and it just disconnects.

If I change the animset.Stopped to animset.Ended then the animation will supposedly start, and the renderstepped stuff will actually happen, but it will be stuck on the renderstepped event forever

Screenshot 2024-02-28 180518
Screenshot 2024-02-28 180444

I have also tried using animset.IsPlaying to try to debug the situation. The result is that the animation is once again supposedly playing and then stops after it ended.

This is the code I’m using to try to see what happens

local anim = script.waekup
local char = game.Players.LocalPlayer.Character
local animset = char:WaitForChild("Humanoid").Animator:LoadAnimation(anim)
local camera = game.Workspace.CurrentCamera
local connection

function cutscene()
	print("began")
	for i,v in ipairs(script.Parent:GetDescendants()) do
		if v:IsA("Accessory") then
			print("handle")
			v:WaitForChild("Handle").Transparency = 1
		end
	end
	camera.CameraType = Enum.CameraType.Scriptable
	camera.CFrame = script.Parent.Head.CFrame
end

connection = game:GetService("RunService").RenderStepped:Connect(cutscene)
animset:Play()
print("playing")
if animset.IsPlaying then
	print("playing!")
else
	print("the animation is not playing")
end
char.HumanoidRootPart.Anchored = true
animset.Ended:Wait()
connection:Disconnect()
char.HumanoidRootPart.Anchored = false
camera.CameraType = Enum.CameraType.Custom
print("disconnected, returned to regular camera")
if animset.IsPlaying then
	print("still playing!")
else
	print("the animation has stopped")
end

If I used animset.Ended for line 28, it outputs
image
(then the renderstepped runs forever)

If I use animset.Stopped for line 28, it outputs
image

(I only found animset.IsPlaying on the documentation, I’m not sure if I actually used it right)

I’m pretty sure it’s an animation problem. No matter what I do I cannot get the animation to work (yet it still is supposedly playing…) but all the other things seem to work like intended

When I try this script, the animation plays
(just the plain animation)

local anim = script.WakeUp
local char = game.Players.LocalPlayer.Character
local animset = char.Humanoid.Animator:LoadAnimation(anim)
task.wait(1)
animset:Play()
print("should work")
char.Humanoid.WalkSpeed = 0
animset.Stopped:Wait()
print("ended")
char.Humanoid.WalkSpeed = 16
animset:Stop()

I might be misremembering, but have you tried not anchoring the humanoid root part? From what I recall years ago, doing that caused some issues with animations.

Maybe try a different approach instead of a RunService Loop

connection = task.spawn(cutscene)
animset:Play()
print("playing")
char.HumanoidRootPart.Anchored = true
animset.Stopped:Wait()
if connection then
task.cancel(connection)
end

that doesn’t seem to be the issue

I removed the anchored things and still same result, skips renderservice and no animation. I remember I tried a different approach for the cutscene, and the animation actually worked and I did anchor the player (nothing bad happened, but the “different approach” was terrible and it consisted of multiple scripts disabling and enabling eachother to stop the runservice and other stuff)

it seems to do the same thing once again… not play animation, nothing happens. Maybe it’s the renderstepped itself causing the problem? The animation on its own can work properly but with the renderstepped it just doesn’t work when I’m pretty sure I got all the things right to properly play an animation

Then maybe load the animation on the humanoid instead of the Animator?

local char = game.Players.LocalPlayer.Character or game.Player.LocalPlayer.CharacterAdded:Wait()
local humanoid = char:WaitForChild("Humanoid")
local animset = humanoid:LoadAnimation(anim) 

When I do that, the same thing happens, renderstepped skipped, animation doesn’t play

Update:
I managed to get everything working to my liking with the script having a similar approach. I genuinely have no idea why my previous script wasn’t working but I just remade it completely and it worked. This is the new script

--stuff
local anim = script.WakeUp
local char = game.Players.LocalPlayer.Character
local animset = char.Humanoid.Animator:LoadAnimation(anim)
local connection
local camera = game.Workspace.CurrentCamera

task.wait(1)
--Apply camera stuff
camera.CameraType = Enum.CameraType.Scriptable
connection = game:GetService("RunService").RenderStepped:Connect(function()
	camera.CFrame = char.Head.CFrame
end)

--hide accessories in a folder
local accFolder = Instance.new("Folder")
accFolder.Parent = game.ReplicatedStorage
accFolder.Name = tostring(game.Players.LocalPlayer.Name.."Accessories")
for i, v in ipairs(char:GetDescendants()) do
	if v:IsA("Accessory") then
		v.Parent = accFolder
	end
end

--play the animation
animset:Play()
char.Humanoid.WalkSpeed = 0
char.HumanoidRootPart.Anchored = true

--do stuff wehn the animation ends
animset.Stopped:Wait()
for i, v in ipairs(accFolder:GetChildren()) do
	if v:IsA("Accessory") then
		v.Parent = game.Players.LocalPlayer.Character
	end
end
accFolder:Destroy()
connection:Disconnect()
camera.CameraType = Enum.CameraType.Custom
print("ended")
char.HumanoidRootPart.Anchored = false
char.Humanoid.WalkSpeed = 16
animset:Stop()

I also just moved the accessories into a folder to hide it instead of making it invisible every time in the renderstepped because I’m pretty sure that caused lag.