Attempt to index nil with 'CFrame'

I’ve newly opened Roblox commissions and finished my first order consisting of a fully functioning teleporter with GUI.

The teleporter works without any major issues, and my client, using a baseplate, confirmed this too, however when he wanted to test it out in his game, it threw this error.

The script in question is a local script located in the GUI, and it looks like this:

local frame = script.Parent.Frame
local touchEvent = game:GetService("ReplicatedStorage").TouchEvent

touchEvent.OnClientEvent:Connect(function()
	frame.Visible = not frame.Visible
end)

for _, button in pairs(frame:GetChildren()) do
	if button:IsA("TextButton") then
		button.MouseButton1Click:Connect(function()
			local location = button.Location.Value
			local char = game:GetService("Players").LocalPlayer.Character
			
			if char then
				char.HumanoidRootPart.CFrame = location.CFrame + Vector3.new(20,5,0)
			end
		end)
	end
end

I tested the same teleporter set on a baseplate and then another development place I worked on earlier, and there were no issues in both cases, so I assume it’s something related to the client’s game specifically.

1 Like

you cant mix cframe with vector3,

you should do this instead

local frame = script.Parent.Frame
local touchEvent = game:GetService("ReplicatedStorage").TouchEvent

touchEvent.OnClientEvent:Connect(function()
	frame.Visible = not frame.Visible
end)

for _, button in pairs(frame:GetChildren()) do
	if button:IsA("TextButton") then
		button.MouseButton1Click:Connect(function()
			local location = button.Location.Value
			local char = game:GetService("Players").LocalPlayer.Character
			
			if char then
				char.HumanoidRootPart.CFrame = CFrame.new(20,5,0) * location.CFrame
			end
		end)
	end
end

please notice that CFrame is relative, thats why i had to swap the position of location.CFrame and the position value

(unless thats what your going for, then swap it back)

1 Like

the location value is a string, not a part or model, which is why it’s throwing the error. A string doesn’t have a CFrame property. To get the actual location you need to do local location = workspace:GetChildren()[button.Location.Value] -- Get the instance in the workspace using the value of the location string. If your location instance is a part, then you can proceed with the rest of your code, but if its a model, then pick whichever you like:

1 → char.HumanoidRootPart.CFrame = location.PrimaryPart.CFrame + Vector3.new(20,5,0)
2 → char.HumanoidRootPart.CFrame = location:GetPivot() + Vector3.new(20,5,0)
The main idea here is to get the reference cframe of your location to tp ur player to

Assuming your Location Instance is an ObjectValue, it is because of streaming. Group your teleporter parts in a group and set the ModelStreamingBehavior to Persistent, that way the part is always loaded in regardless of distance.

It does load after the player joins/spawns (meaning you would have to use PersistentLoaded or WaitForChild), but it’s being connected to a button anyways and it’s almost guaranteed to be loaded in before the player activates the button.

image

If you got this error then you are probably teleporting to a part, since a part doesn’t have a primary part

It is a part, but even if I delete the PrimaryPart thing from the script, it still shows the same error, same with when I try to use :GetPivot().

Read my post above, and ensure it is properly set when you transferred your commission over.

I did, but sadly it still doesn’t work.

For clarification, yes, Location is an ObjectValue, and the entire model’s ModelStreamingBehavior is set to Persistent.

Right, but is the Location.Value actually set when you transferred it over? When you play test in studio, ensure you are on the Client view and go to your Explorer window and navigate to Workspace → … → Teleporter Part, does it exist? Also navigate to Players → PlayerGui → … → Location and check the Properties window if the value is set.

Edit: Also ensure your entire map isn’t set to Persistent, otherwise it ruins the whole purpose of streaming.

That’s a really good point, the Location.Value is set correctly, but the issue may have been that the script didn’t like that the model in which the parts are was renamed. Is that an issue, and if so, how could that be fixed?

That should not be an issue.

If you have an ObjectValue and it’s Value is set, that ObjectValue now holds direct reference to that Instance internally, meaning even if you rename or moved it, it wouldn’t matter.

Additionally, with streaming, an ObjectValue’s Value will automatically change to either the initially attached Instance or nil, depending if the part is streamed in on the client.

Answer these questions for me:

  1. Are your teleporter parts grouped in it’s own Model with ModelStreamingBehavior set to Persistent?
  2. Check all your Location ObjectValues while in edit mode (not playing), do they all have Values set?
  3. Play test in studio and ensure you are still on the client view. Check all your Location ObjectValues again if their Values are still set (which it should be because of persistence).
  1. Yep.
  2. Yep.
  3. Still the same.

characterscharacterscharacters

Then it should be working just fine now. Can you send over your new script?

local frame = script.Parent.Frame
local touchEvent = game:GetService("ReplicatedStorage").TouchEvent

touchEvent.OnClientEvent:Connect(function()
	frame.Visible = not frame.Visible
end)

for _, button in pairs(frame:GetChildren()) do
	if button:IsA("TextButton") then
		button.MouseButton1Click:Connect(function()
			local location = workspace:GetDescendants()[button.Location.Value]
			print(location)
			local char = game:GetService("Players").LocalPlayer.Character
			
			if char then
				char.HumanoidRootPart.CFrame = CFrame.new(20,5,0) * location.CFrame
			end
		end)
	end
end

This is, of course, after editations from previous suggestions.

Go back to your old script. This script and their suggestion does not make any sense.

Still doesn’t work.

characterscharacters

I can be completely wrong but I’m not sure you can index an instance.

workspace:GetDescendants()[button.Location.Value]

I reverted to my old script though, and it didn’t work either.

Put the teleport locations in ReplicatedFirst. If that doesn’t work, then you’ll probably need to manually input the vector3 values.