Marble Script Guidance Needed!

Me and my friend are creating a marble game, we created the spawn which allows you to spawn your marble. When the marble spawns it has the players name in marbles name (if thats useful to know).

We need help figuring out how to put the player into the marble when it spawns. We know that we need to create a weld with the part, but we don’t know how to make it so that the player welds with marble after it spawns. We don’t know how to trigger it, or how to make it specific to the Marbles name. You can see we have a naming system in the spawning script, that makes it custom to the player, and we would like to now how to get the player to weld inside their specific named marble.

Here is the video demonstrating how the spawning system works:

Here is the script for the spawning system:

local button = script.Parent:WaitForChild("Button")
local detector = script.Parent:WaitForChild("Detector")
local target = script.Parent:WaitForChild("Target")

local SS = game:GetService("ServerStorage")
local cloneables = SS:WaitForChild("Cloneables")
local TC_Model = cloneables:WaitForChild("Marble2")

debounce = false

function MakeIt(plr)
    local model = TC_Model:Clone()
    model.Name = plr.Name.."Marble2"
    model.Parent = game.Workspace
    model:SetPrimaryPartCFrame(target.CFrame)
    model.Owner.Value = plr.Name
end

button.ClickDetector.MouseClick:Connect(function(plr)
    if not debounce then
        debounce = true
        print(plr.Name.." wants to spawn a Marble2")

        local parts = detector:GetTouchingParts()
        for i,v in pairs(parts) do
            local isMarble2 = v.Parent:FindFirstChild("IsMarble2")
            if isMarble2 then
                print("Marble2 detected...removing")
                local Marble2 = isMarble2.Parent
                Marble2:Destroy()
            end
        end

        local Marble2 = game.Workspace:FindFirstChild(plr.Name.."Marble2")
        if Marble2 then
            print(plr.Name.." already has a Marble2, so removing that one")
            Marble2:Destroy()
        end

        MakeIt(plr)
        wait(2)
        debounce = false
    end
end)

If you need any more information let us know and we will get it to you asap!

You would want to move the HumanoidRootPart or Torso of the player’s character to the exact position of the marble, then weld them together.

Yes, but we don’t know how to make that happen once the marble spawns.

Change the CFrame of the HumanoidRootPart to the CFrame of the marble, do it like this:

HumanoidRootPart.CFrame = Marble.CFrame + Vector3.new(0,3,0)

The + Vector3.new(0,3,0) part is there because if it isn’t you could get stuck in the floor.

Thanks, How would I set this to happen when the Marble clones into the workspace? Sorry.

Create a new function that detects when the marble becomes available in the workspace. When that happens create a weld constraint, move the player to the marble and enable the weld.

game.workspace.ChildAdded:Connect(function(child)
    if(child.Name == plr.Name.."Marble2")then
        local weld = Instance.new("WeldConstraint")
        weld.Parent = child
        weld.Enabled = false --stop it from working just yet
        weld.Part0 = child
        weld.Part1 = plr.Character.HumanoidRootPart
        plr.Character:PivotTo(child:GetPivot()) --Move character to the marble center
        weld.Enabled
    end
end)

This is only an example and as written will not work since the “plr” variable is undefined in this scope. You would need to keep a local player variable in the main script. You may find that just by welding the character to the marble it causes some goofy camera movements since the character and marble are rolling around.

Edit: Since I assume this is meant to be a vehicle you may want to add a seat to the marble and force the player to sit in it. Then you’d want to connect the seat to the marble using a cylindrical constraint so the marble can roll around without flipping around the character with it. Further you’d want to add a gyro to the seat so the seat stays upright.

2 Likes

Thank you so much for this! It isn’t going to be a vehicle, but instead a free moving part that the player is just inside of (if that makes sense). Sorry, as this is a stupid question but the plr is the name of a function in the spawning script. How would you define it in this script? Thanks again for the help!

1 Like

I think you’ll find it is a vehicle (of sorts). In order to keep the player attached and still allow it to roll, you’ll require it to be setup like a custom vehicle, even if your not allowing it to be steered/controlled, it is something the player will ride inside of. It also doesn’t necessarily require a Seat but you’ll probably want some part inside the marble that doesn’t roll with the marble since I am fairly sure will cause camera problems. You could then just weld the character to this part.

plr variable is the player instance who clicked the button. See ClickDetector | Roblox Creator Documentation

When you obtain that instance you can save it outside of the function in a variable called “player” (just like the TC_Model variable). Then the “player” variable will be available inside any of your functions.

2 Likes

I’m struggling with this so much, so sorry. Can you just like dumb it down for me a little bit pretty please or give a little example on how I would define that, I’m very sorry.

Look for the changes I’ve made in your script here to see how to save the player instance in a variable.

local button = script.Parent:WaitForChild("Button")
local detector = script.Parent:WaitForChild("Detector")
local target = script.Parent:WaitForChild("Target")

local SS = game:GetService("ServerStorage")
local cloneables = SS:WaitForChild("Cloneables")
local TC_Model = cloneables:WaitForChild("Marble2")

local player = nil --Empty player variable

debounce = false

function MakeIt(plr)
    local model = TC_Model:Clone()
    model.Name = plr.Name.."Marble2"
    model.Parent = game.Workspace
    model:SetPrimaryPartCFrame(target.CFrame)
    model.Owner.Value = plr.Name
end

button.ClickDetector.MouseClick:Connect(function(plr)
    if not debounce then
        debounce = true

        player = plr --Save the player instance to your empty variable above        

        print(plr.Name.." wants to spawn a Marble2")

        local parts = detector:GetTouchingParts()
        for i,v in pairs(parts) do
            local isMarble2 = v.Parent:FindFirstChild("IsMarble2")
            if isMarble2 then
                print("Marble2 detected...removing")
                local Marble2 = isMarble2.Parent
                Marble2:Destroy()
            end
        end

        local Marble2 = game.Workspace:FindFirstChild(plr.Name.."Marble2")
        if Marble2 then
            print(plr.Name.." already has a Marble2, so removing that one")
            Marble2:Destroy()
        end

        MakeIt(plr)
        wait(2)
        debounce = false
    end
end)

The function example I provided that is now using the player variable

game.workspace.ChildAdded:Connect(function(child)
    if(child.Name == player.Name.."Marble2")then
        local weld = Instance.new("WeldConstraint")
        weld.Parent = child
        weld.Enabled = false --stop it from working just yet
        weld.Part0 = child
        weld.Part1 = player.Character.HumanoidRootPart
        player.Character:PivotTo(child:GetPivot()) --Move character to the marble center
        weld.Enabled
    end
end)
2 Likes

Thank you so much for this, as it is helping us tremendously, but how would we bring this instance and information to the other script?

local player = plr??

We don’t know how to transfer it there for it to run. Thanks so much for your help!

You could just add in the changes I made to your script. Then copy that function and paste it in the script at the bottom.

Yes the empty “player” variable will hold the same value as “plr” after it is assigned inside the clickDetector function you have. Since the function I provided won’t do anything until that marble is created and added to the workspace the “player” variable will not be empty when it runs.

1 Like

We are getting this error for this line? Any idea on what it could be? Thanks again for your help!

unknown

Hmm. No I’m not sure why you would get that error. “child” should hold the Marble part instance. Repost your script let me look at what you have.

local button = script.Parent:WaitForChild("Button")
local detector = script.Parent:WaitForChild("Detector")
local target = script.Parent:WaitForChild("Target")

local SS = game:GetService("ServerStorage")
local cloneables = SS:WaitForChild("Cloneables")
local TC_Model = cloneables:WaitForChild("Marble2")

local player = nil --Empty player variable

debounce = false

function MakeIt(plr)
	local model = TC_Model:Clone()
	model.Name = plr.Name.."Marble2"
	model.Parent = game.Workspace
	model:SetPrimaryPartCFrame(target.CFrame)
	model.Owner.Value = plr.Name
end

button.ClickDetector.MouseClick:Connect(function(plr)
	if not debounce then
		debounce = true

		player = plr --Save the player instance to your empty variable above        

		print(plr.Name.." wants to spawn a Marble2")

		local parts = detector:GetTouchingParts()
		for i,v in pairs(parts) do
			local isMarble2 = v.Parent:FindFirstChild("IsMarble2")
			if isMarble2 then
				print("Marble2 detected...removing")
				local Marble2 = isMarble2.Parent
				Marble2:Destroy()
			end
		end

		local Marble2 = game.Workspace:FindFirstChild(plr.Name.."Marble2")
		if Marble2 then
			print(plr.Name.." already has a Marble2, so removing that one")
			Marble2:Destroy()
		end

		MakeIt(plr)
		wait(2)
		debounce = false
	end
end)

game.workspace.ChildAdded:Connect(function(child)
	if(child.Name == player.Name.."Marble2")then
		local weld = Instance.new("WeldConstraint")
		weld.Parent = child
		weld.Enabled = false --stop it from working just yet
		weld.Part0 = child
		weld.Part1 = player.Character.HumanoidRootPart
		player.Character:PivotTo(child:GetPivot()) --Move character to the marble center
		weld.Enabled = true
	end
end)

What exactly is TC_Model? Is this a Part that you have pre-made?

Assuming it is I’ve made some changes to your script. Look this over carefully and give it a try.

local button = script.Parent:WaitForChild("Button")
local detector = script.Parent:WaitForChild("Detector")
local target = script.Parent:WaitForChild("Target")

local SS = game:GetService("ServerStorage")
local cloneables = SS:WaitForChild("Cloneables")
local TC_Model = cloneables:WaitForChild("Marble2")

local player = nil --Empty player variable

debounce = false

function MakeIt(plr)
	local model = TC_Model:Clone()
	model.Name = plr.Name.."Marble2"
	model.Parent = game.Workspace
	model:SetPrimaryPartCFrame(target.CFrame)
	model.Owner.Value = plr.Name
	
	--Return the new marble instance
	return model
end


--A function to check if the marble already exists in the workspace.
function MarbleExists(plr)
	if(game.Workspace:FindFirstChild(plr.."Marble2"))then
		--The marble already exists for this player
		return true
	end
	
	--The marble doesn't exist yet
	return false
end

button.ClickDetector.MouseClick:Connect(function(plr)
	if not debounce then
		debounce = true

		player = plr --Save the player instance to your empty variable above        

		print(plr.Name.." wants to spawn a Marble2")
		
		
		-- Check if the marble already exists
		if(MarbleExists(plr))then
			debounce = false
			return --Do nothing because the marble already exists...
		end
		
		--[[
		
		I'm not really sure what's happening with this part.. so I added
		A function to check if the marble is in the workspace already
		
		local parts = detector:GetTouchingParts()
		for i,v in pairs(parts) do
			local isMarble2 = v.Parent:FindFirstChild("IsMarble2")
			if isMarble2 then
				print("Marble2 detected...removing")
				local Marble2 = isMarble2.Parent
				Marble2:Destroy()
			end
		end
		
		
		local Marble2 = game.Workspace:FindFirstChild(plr.Name.."Marble2")
		if Marble2 then
			print(plr.Name.." already has a Marble2, so removing that one")
			Marble2:Destroy()
		end
		
		--]]
		
		--Make the marble and save the returned instance value
		local newMarble = MakeIt(plr)
		
		--wait(2)
		--Wait until the marble is added to the workspace
		repeat wait() until newMarble.Parent == game.Workspace
		debounce = false
	end
end)


game.Workspace.ChildAdded:Connect(function(child)
	if(child.Name == player.Name.."Marble2")then
		
		local marble = child --Rename it so its easier to understand
		
		local weld = Instance.new("WeldConstraint")
		weld.Parent = marble --store the weld constraint in the marble
		weld.Enabled = false --stop it from working just yet
		weld.Part0 = marble --Connect the marble to the weld constraint
		weld.Part1 = player.Character.HumanoidRootPart --connect the player's character root part to the weld constraint
		
		player.Character:PivotTo(marble:GetPivot()) --Move character to the marble center
		weld.Enabled = true --activate the weld now
	end
end)
1 Like

We are still receiving the error for this line of code. It now states:
image

Ok, So that means that the Marble is a “Model” instance and not a “BasePart”. Is that correct? I don’t know because you are cloning an instance of something when creating the Marble. It could be any sort of instance. The weld constraint requires a BasePart.

1 Like

YES, that was the issue it was a unnecessary model. But there is a new issue. Once spawned, the character is able to walk around…

image

1 Like

Also, yes the weld was trying to connect to a model. I fixed it by putting the required elements into a part, and it fixed the weld issue.

1 Like