Animation Issue

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve? Keep it simple and clear!
    This is about the 50th post I’ve made looking for help with this animation, but I’ve tracked down the issue. I’m currently making an animation play for the end of a chase sequence in my indie roblox horror game.

  2. What is the issue? Include screenshots / videos if possible!
    I believe the cloned rigs simply aren’t being moved to workspace.

  3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    I have made so many devforum posts, and even tried rescripting it entirely.

After that, you should include more details if you have any. Try to make your topic as descriptive as possible, so that it’s easier for people to help you!

TriggerServer Script

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

local DisableEvent = ReplicatedStorage:WaitForChild("DisableEvent")
local EnableEvent = ReplicatedStorage:WaitForChild("EnableEvent")
local ChasePhaseTwoEvent = ReplicatedStorage:WaitForChild("ChasePhaseTwo")
local EndChaseTeleportPosition = workspace:WaitForChild("EndChaseTeleportPosition")

local function TriggerPhaseTwo(player)
	print("Server: Player", player.Name, "triggered ChasePhaseTwo")

	-- Disable player controls
	DisableEvent:FireClient(player)
	print("Server: Fired DisableEvent for", player.Name)

	-- Fire client event to all for cutscene
	ChasePhaseTwoEvent:FireAllClients()
	print("Server: Fired ChasePhaseTwo event for all clients")

	wait(6.5)

	-- Move player after cutscene
	if player.Character and player.Character:FindFirstChild("HumanoidRootPart") then
		player.Character:MoveTo(EndChaseTeleportPosition.Position)
		print("Server: Teleported", player.Name, "to EndChaseTeleportPosition")
	end

	-- Enable player controls
	EnableEvent:FireClient(player)
	print("Server: Fired EnableEvent for", player.Name)

	wait(2)
	print("Server: Debounce cleared for", player.Name)
end

-- Replace with actual way you're triggering it
game.ReplicatedStorage.StartPhaseTwo.OnServerEvent:Connect(TriggerPhaseTwo)
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local TweenService = game:GetService("TweenService")
local ContentProvider = game:GetService("ContentProvider")

local player = Players.LocalPlayer
local camera = workspace.CurrentCamera

local Event = ReplicatedStorage.Remotes:WaitForChild("ChasePhaseTwo")
local Characters = ReplicatedStorage:WaitForChild("EndChaseAnimation")
local John = Characters:WaitForChild("NaughtyJohn")
local Main = Characters:WaitForChild("PlayerModel")

local ChaseTriggerer = workspace:WaitForChild("ObjectiveParts"):WaitForChild("ChasePhaseTwo")

-- Utility: Disable collisions
local function disableCollisions(model)
	if not model then
		warn("Client: No model provided for disableCollisions")
		return
	end
	for _, part in ipairs(model:GetDescendants()) do
		if part:IsA("BasePart") then
			part.CanCollide = false
		end
	end
end

-- Make player invisible/visible
local function setPlayerVisible(character, isVisible)
	if not character then
		warn("Client: No character found for visibility toggle")
		return
	end
	print("Client: Setting player visibility to " .. tostring(isVisible))
	for _, part in ipairs(character:GetDescendants()) do
		if part:IsA("BasePart") or part:IsA("Decal") then
			part.Transparency = isVisible and 0 or 1
		elseif part:IsA("Accessory") and part:FindFirstChild("Handle") then
			part.Handle.Transparency = isVisible and 0 or 1
		elseif part:IsA("ParticleEmitter") then
			part.Enabled = isVisible
		end
	end
end

-- Preload cutscene assets
local function preloadCharacters()
	print("Client: Preloading cutscene assets")
	local assets = {}
	for _, desc in ipairs(Characters:GetDescendants()) do
		if desc:IsA("MeshPart") or desc:IsA("Decal") or desc:IsA("Texture") or desc:IsA("Animation") then
			table.insert(assets, desc)
		end
	end
	ContentProvider:PreloadAsync(assets)
	print("Client: Asset preloading complete")
end

Event.OnClientEvent:Connect(function()
	print("Client: Received ChasePhaseTwo event")
	local success, err = pcall(function()
		-- Validate character
		local character = player.Character or player.CharacterAdded:Wait()
		if not character then
			warn("Client: Player character not found")
			return
		end
		print("Client: Player character found")

		-- Wait for game to load
		game.Loaded:Wait()
		print("Client: Game loaded, proceeding with cutscene setup")

		-- Validate MainAnimationStartPoint
		local targetCFrame = workspace:WaitForChild("MainAnimationStartPoint", 10)
		if not targetCFrame then
			warn("Client: MainAnimationStartPoint not found in Workspace after waiting")
			return
		end
		print("Client: Found MainAnimationStartPoint")

		-- Hide player
		setPlayerVisible(character, false)

		-- Preload assets and force streaming
		preloadCharacters()
		player:RequestStreamAroundAsync(targetCFrame.Position, 1)
		task.wait(1)
		print("Client: Streaming requested and assets preloaded")

		-- Move cutscene models to workspace
		Characters.Parent = workspace
		print("Client: Characters parented to workspace")

		if ChaseTriggerer then
			ChaseTriggerer:Destroy()
			print("Client: ChaseTriggerer destroyed")
		end

		-- Validate model structure
		if not Main.PrimaryPart then
			warn("Client: Main model PrimaryPart missing!")
			return
		else
			print("Client: Main PrimaryPart found: ", Main.PrimaryPart.Name)
		end
		if not John.PrimaryPart then
			warn("Client: John model PrimaryPart missing!")
			return
		else
			print("Client: John PrimaryPart found: ", John.PrimaryPart.Name)
		end

		-- Reposition John relative to PlayerModel
		local offsetCFrame = Main.PrimaryPart.CFrame:ToObjectSpace(John.PrimaryPart.CFrame)
		Main:PivotTo(targetCFrame.CFrame)
		John:PivotTo(Main.PrimaryPart.CFrame * offsetCFrame)
		print("Client: Repositioned Main and John models")

		-- Disable collisions
		disableCollisions(John)
		print("Client: Disabled collisions for John")

		-- Load animations
		local JohnAnim = script:WaitForChild("John", 5)
		local MainAnim = script:WaitForChild("Player", 5)
		if not JohnAnim or not MainAnim then
			warn("Client: Failed to find John or Player animation in script")
			return
		end
		print("Client: Found John and Player animations")

		-- Validate humanoids
		local JohnHumanoid = John:WaitForChild("Humanoid", 5)
		local MainHumanoid = Main:WaitForChild("Humanoid", 5)
		if not JohnHumanoid or not MainHumanoid then
			warn("Client: Humanoid missing in John or Main")
			return
		end
		print("Client: Found Humanoids for John and Main")

		-- Load animation tracks
		local JohnAnimTrack = JohnHumanoid:LoadAnimation(JohnAnim)
		local MainAnimTrack = MainHumanoid:LoadAnimation(MainAnim)
		if not JohnAnimTrack or not MainAnimTrack then
			warn("Client: Failed to load animation tracks")
			return
		end
		print("Client: Loaded animation tracks")

		JohnAnimTrack.Priority = Enum.AnimationPriority.Action4
		MainAnimTrack.Priority = Enum.AnimationPriority.Action4

		-- Set up camera
		local torso = Main:WaitForChild("Torso", 5)
		if not torso then
			warn("Client: Torso not found in Main")
			return
		end
		camera.CameraSubject = torso
		camera.CameraType = Enum.CameraType.Custom
		camera.CFrame = camera.CFrame * CFrame.new(0, 5, -10)
		print("Client: Camera set up for cutscene")

		-- Play animations
		JohnAnimTrack:Play()
		MainAnimTrack:Play()
		print("Client: Playing John and Main animations")

		-- Handle animation end
		MainAnimTrack.Ended:Connect(function()
			print("Client: Main animation ended")
			-- Reset camera
			if player.Character and player.Character:FindFirstChild("Head") then
				camera.CameraSubject = player.Character.Head
			end
			camera.CameraType = Enum.CameraType.Custom
			print("Client: Camera reset to player head")

			-- Show player again
			setPlayerVisible(player.Character, true)
			print("Client: Player visibility restored")

			-- Cleanup cutscene models from workspace
			if Characters and Characters.Parent == workspace then
				Characters.Parent = ReplicatedStorage
				print("Client: Cutscene models returned to ReplicatedStorage")
			end
		end)
	end)

	if not success then
		warn("Client: Error in ChasePhaseTwo handler: " .. tostring(err))
	end
end)

I will be SO grateful for any help as this has been the most annoying issue in developing this game.

Please do not ask people to write entire scripts or design entire systems for you. If you can’t answer the three questions above, you should probably pick a different category.

1 Like

Have you tried printing the Characters.Parent? Maybe they could be getting parented but simply not actually being loaded by your forced streaming

You should pay attention to a few things, firstly, that the animation priority should be set in the importer and not in the script, because there is a chance of bugs happening and this makes a huge difference. And secondly, you need to see if the streaming is being requested at the right time. From what I saw, it seems to be being called before some things are placed in the workspace. It should be called later, right?

This function asks for the server to give the client information about the location they’re trying to load, the cutscene, being handled locally, wouldn’t be able to be loaded with this.

It’s been mentioned by a roblox staff member that local parts never get streamed out, so there might be something wrong with the way they’re loading their cutscene.

@V0RTEXwhoEditz Could you show some footage of your game when the cutscene should happen? Make sure to include the explorer in the footage so we could see if it actually gets parented or not. The model itself could be getting parented but not getting its loaded for some reason.

Make sure they’re properly parented to workspace before playing the animation. If that doesn’t fix it, try manually setting their position and checking if they’re loaded correctly before triggering the animation. Let me know if you need more details!

they aren’t supposed to be in workspace if the animation isn’t playing, so they’re in ReplicatedStorage

If your model is in ReplicatedStorage, animations won’t play because it’s not part of the active game world. You need to move or clone the model into workspace before playing the animation.
You can also put a script to clone the Animation in the Workspace, for example:

local model = game.ReplicatedStorage.Anim:Clone() -- replace 'anim' with the name of your animation
model.Parent = workspace
local animator = model:FindFirstChildWhichIsA("Animator", true)
local animation = Instance.new("Animation")
animation.AnimationId = "rbxassetid://0000000" -- the ID of your Animation
local track = animator:LoadAnimation(animation)
track:Play()

Try this and see if it works. Animations need the model to be in workspace to run.