Cameras CFrame is Random and not cycling through sequentially

I’m trying to make cutscenes. The camera’s cframe is not starting at my first parts index in my scene folder. It is starting in a random order, sometimes it will just start at index 3 and then 2 then 1. I just want it to go in my scene folder and go from part 1, part 2, part 3. I have tried doing a for_, loop with my collection service cause I did tag the parts for my cutscene but that did not work either I will show you an example of my for loop:

for i, CameraPart in ipairs(CameraParts) do
print(i, CameraPart.Name)
if CameraPart == CameraPart then
CameraIndex = i
break
end
end

The print statement printed out: 1 Stage 2

Nothing is working

local SceneFolder = workspace.SceneFolders 

local currentPartIndex = 0

local function animateText()
	currentTextIndex = (prevTextIndex % #TEXTS) + 1
	prevTextIndex = currentTextIndex

	local newText = TEXTS[currentTextIndex]
	local textLabelSize = TextLabel.TextBounds
	local textTweenIn = TweenService:Create(TextLabel, TweenInfo.new(1), {
		TextTransparency = 0,
		Size = UDim2.new(0, 586, 0, 98)
	})
	local textTweenOut = TweenService:Create(TextLabel, TweenInfo.new(1), {
		TextTransparency = 1,
		Size = UDim2.new(0, 586, 0, 98)
	})

	-- Get the current part in the scene folder based on the currentTextIndex
	currentPartIndex = currentPartIndex % #SceneFolder:GetChildren() + 1
	local currentPart = SceneFolder:GetChildren()[currentPartIndex]


	textTweenOut.Completed:Connect(function()
		currentText = newText
		TextLabel.Text = currentText
		textTweenIn:Play()

		-- Set the camera's CFrame to the current part's CFrame
		Camera.CFrame = CFrame.new(currentPart.Position)

	end)
	textTweenIn:Play()


	local currentCharacterIndex = 0
	while currentCharacterIndex < #newText do
		currentCharacterIndex = currentCharacterIndex + 1
		TextLabel.Text = newText:sub(1, currentCharacterIndex)
		sound:Play()
		wait(0.05)
		sound:Stop()
	end

	wait(TEXT_DISPLAY_TIME)
	textTweenOut:Play()

end



local t0 = os.clock()


while os.clock() - t0 < CUTSCENE_LENGTH do
	animateText()
	RunService.Stepped:Wait()
end

-- enable control of character and camera after cutscene
Humanoid:ChangeState(Enum.HumanoidStateType.GettingUp)
Camera.CameraType = Enum.CameraType.Custom

1 Like

Have you tried indexing the parts by their names, not their indexes in the array? In the following example, cameraParts is a Folder, and its children are named like “1”, “2”, “3”, etc:

for i = 1, #cameraParts:GetChildren() do
    --[[
         Get the current camera part by using
        `cameraParts[i]`.

        `cameraParts[i]` is not different than `cameraParts["2"]` (if `i` is `2`),
        and is like `cameraParts:FindFirstChild("2")`.
    ]]
end

I don’t think that a table of children will follow the order in which the children were added. I could be wrong, though. However, this seems to be your problem.

1 Like

Ok so I did this:
It is still not indexing at Scene1 instead its going to Scene3 and then Scene2 sometimes Scene2 and then Scene3. Im not getting any errors in the output. Whenever I print partName it prints all 3 names and when i print currentPart it prints out all 3 names

	```for i = 1, #SceneFolder:GetChildren() do
		local partName = "Scene" .. i  
		local currentPart = SceneFolder:FindFirstChild(partName)
		if currentPart then
			print(currentPart)
			Camera.CFrame = CFrame.new(currentPart.Position)
		end
	end
end)```

Sorry for the late response.
The names are not being outputted in the correct order?

Yeah its printing out all 3 names at the same time

Oh, would that be because there is no task.wait()? And is there any code outside of this loop that would be interfering with the loop?

1 Like

I dont know maybe here is (almost) the full script I just left my TEXTS table out of it. and I switched up the method we are using with the table.sort but it still doesnt work:

local LocalPlayer = Players.LocalPlayer
local Character = LocalPlayer.Character or LocalPlayer.CharacterAdded:Wait()
local Humanoid = Character:WaitForChild("Humanoid")
local Camera = workspace.Camera
local RunService = game:GetService("RunService")
local TweenService = game:GetService("TweenService")
local Gui = script.DialogueBox
local TextLabel = Gui.TextLabel

--- CAMERAS--------------------------------------------------------------
local CollectionService = game:GetService("CollectionService")
local CutsceneCameras = CollectionService:GetTagged("CutsceneCameras")

Camera.CameraType = Enum.CameraType.Scriptable

local CUTSCENE_LENGTH = 30 -- length of cutscene in seconds
local TEXT_DISPLAY_TIME = 2 -- time to display each line of text in seconds
------------------------------------------------------------------------------

local ConnectRemote = game.ReplicatedStorage.Remotes.Connect

Humanoid:ChangeState(Enum.HumanoidStateType.Physics)



-- display cutscene GUI and start animating text
TextLabel.Visible = true
script.Parent.Visible = false
local currentTextIndex = 1
local currentText = TEXTS[currentTextIndex]
TextLabel.Text = currentText
local sound = Gui.Sound
local prevTextIndex = 0


local SceneFolder = workspace.SceneFolders -- Replace "SceneFolder" with the name of your scene folder
local currentPartIndex = 0

-- Get the current part in the scene folder based on the currentPartIndex
currentPartIndex = currentPartIndex % #SceneFolder:GetChildren() + 1
local currentPart = SceneFolder:GetChildren()[currentPartIndex]



local sceneChildren = SceneFolder:GetChildren()
table.sort(sceneChildren, function(a, b)
	return a.Name < b.Name
end)


local function animateText()
	currentTextIndex = (prevTextIndex % #TEXTS) + 1
	prevTextIndex = currentTextIndex

	local newText = TEXTS[currentTextIndex]
	local textLabelSize = TextLabel.TextBounds
	local textTweenIn = TweenService:Create(TextLabel, TweenInfo.new(1), {
		TextTransparency = 0,
		Size = UDim2.new(0, 586, 0, 98)
	})
	local textTweenOut = TweenService:Create(TextLabel, TweenInfo.new(1), {
		TextTransparency = 1,
		Size = UDim2.new(0, 586, 0, 98)
	})

	textTweenOut.Completed:Connect(function()
		currentText = newText
		TextLabel.Text = currentText
		textTweenIn:Play()

		for i = 1, #sceneChildren do
			local partName = "Scene" .. i  
			local currentPart = sceneChildren[i]
			Camera.CFrame = currentPart.CFrame
		end
	end)
	
	textTweenIn:Play()


	local currentCharacterIndex = 0
	while currentCharacterIndex < #newText do
		currentCharacterIndex = currentCharacterIndex + 1
		TextLabel.Text = newText:sub(1, currentCharacterIndex)
		sound:Play()
		wait(0.05)
		sound:Stop()
	end

	wait(TEXT_DISPLAY_TIME)
	textTweenOut:Play()

end



local t0 = os.clock()


while os.clock() - t0 < CUTSCENE_LENGTH do
	animateText()
	RunService.Stepped:Wait()
end

-- enable control of character and camera after cutscene
Humanoid:ChangeState(Enum.HumanoidStateType.GettingUp)
Camera.CameraType = Enum.CameraType.Custom



-- hide cutscene GUI
TextLabel.Visible = false

script.Parent.Visible = true


script.Parent.MouseButton1Click:Connect(function()
	script.Parent.Parent.Visible = false
	Character.HumanoidRootPart.Anchored = false
	Character.Humanoid.WalkSpeed = 16
	Character.Humanoid.JumpPower = 59
	ConnectRemote:FireServer("Move")
end)

If the loop was placed after the following line of code, it could be that you have two variables with the same name.

local currentPart = SceneFolder:GetChildren[currentPartIndex]

So the loop is using this variable instead of the currentPart variable created inside of the loop.

Comment out the line above, then use the loop.

1 Like

It still be starting at the 3rd index(3rd Parts) cframe :sob:

Im just going to brainstorm but maybe its because of this line?

currentPartIndex = currentPartIndex % #SceneFolder:GetChildren() + 1

would that cause it to not start at 1?

If you’re using that currentPartIndex in the loop, I believe so.
I do think that the code before the loop is “interfering” with it.

It seems strange that it’s going out of order even though the loop’s index starts at 1, that’s why I don’t think it’s the loop itself.
And you’re saying that it’s “starting” at the 3rd index, which means you see it being set to the 1st and 2nd, too?

1 Like

No I see it starting at the 3rd index. Whenever the player joins the game the cutscene goes to the 3rd part. I have it so as soon as the player joins the game, text displays, and when the text gets done displaying it moves to the next line of text in my array, when that next line of text starts my camera goes to part 3 and not 1 I only see it being set to 3 and then 2 but I never get to see 1

OK. I am trying to go along with your original code – I don’t know how your current code looks now. Also, the loop I provided was just an example of indexing parts by their names, so you do not actually need it.

As I stated above, you don’t actually need the loop, so forget it. However, the idea of indexing the parts by their names may be what you need.

In this example, pretend that camIndex is currentPartIndex, and camPart is currentPart:

local camIndex = 1 -- Start at 1, which isn't necessary depending on the math you use.

local function animate()
    -- (I am just focusing on the camera parts in this function.)

    -- Index the part. If there's a chance that the index would be higher than
    -- the number of camera parts, you may want to do some checks:
    --[[
        if camIndex > #cameraParts:GetChildren() then
            camIndex = 1
        end
    ]]
    local camPart = cameraParts[camIndex]

    camera.CFrame = camPart.CFrame -- Set the camera's CFrame at sometime.

    camIndex += 1 -- Increment the index for the next time the function gets called.
end
1 Like

Hey, Thank you so much! Im grateful for all the help you have provided me with! now it finally works.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.