How do I do this?

I’ve made this post about 3 or 4 times and no one’s answered not one of them. I couldn’t think of a better name. How do I make a part apply gravity to itself without making him clip in the floor? Here’s a video of this glitch happening, I’m too tired to keep writing.
(video removed due to roblox recording at 1 fps and you couldnt see it. basically, sonic clips right into the white floor in this picture)

if you absolutely need the code, here it is:

local inAir = script.Parent.Variables.inAir.Value
local speedY = script.Parent.Variables.speedY.Value
local collisionBtmRight = script.Parent.Variables.collisionBtmRight.Value
local collisionBtmLeft = script.Parent.Variables.collisionBtmLeft.Value
local dTime = 0.01

wait(10)

--COLLISIONS
script.Parent.Parent.btmLeftAnchorPoint.Touched:Connect(function(part)
	if part.BrickColor == BrickColor.new("Institutional white") then
		print("hi")
		collisionBtmLeft = true
	end
end)
script.Parent.Parent.btmRightAnchorPoint.Touched:Connect(function(part)
	if part.BrickColor == BrickColor.new("Institutional white") then
		print("bye")
		collisionBtmRight = true
	end
end)
script.Parent.Parent.btmLeftAnchorPoint.TouchEnded:Connect(function()
	collisionBtmLeft = false
end)
script.Parent.Parent.btmRightAnchorPoint.TouchEnded:Connect(function()
	collisionBtmRight = false
end)

game:GetService("RunService").Heartbeat:Connect(function()
	script.Parent.Parent.btmRightAnchorPoint.Touched:Connect(function() end)
	local touching = script.Parent.Parent.btmRightAnchorPoint:GetTouchingParts()
	for i=1,#touching do
		if touching[i].Name == "Solid" and touching[i].BrickColor == BrickColor.new("Institutional white") then
			speedY = 0
		end
	end
	script.Parent.Parent.btmLeftAnchorPoint.Touched:Connect(function() end)
	local touching = script.Parent.Parent.btmLeftAnchorPoint:GetTouchingParts()
	for i=1,#touching do
		if touching[i].Name == "Solid" and touching[i].BrickColor == BrickColor.new("Institutional white") then
			speedY = 0
		end
	end
end)

repeat
	--BASIC CHECKS
	if collisionBtmLeft == false and collisionBtmRight == false then
		inAir = 1
	elseif collisionBtmLeft == true and collisionBtmRight == false then
		inAir = 0.8
	elseif collisionBtmLeft == false and collisionBtmRight == true then
		inAir = 0.4
	elseif collisionBtmLeft == true and collisionBtmRight == true then
		inAir = 0
	end
	
	--GRAVITY
	if inAir == 1 then
		if collisionBtmLeft == false and collisionBtmRight == false then
			speedY = speedY - 0.1
		end
	else
		speedY = 0
	end
	
	--MOVE PLAYER AND ANCHOR POINTS
	script.Parent.Parent.btmRightAnchorPoint.CFrame = script.Parent.Parent.btmRightAnchorPoint.CFrame + Vector3.new(0, speedY, 0)
	script.Parent.Parent.btmLeftAnchorPoint.CFrame = script.Parent.Parent.btmLeftAnchorPoint.CFrame + Vector3.new(0, speedY, 0)
	script.Parent.CFrame = script.Parent.CFrame + Vector3.new(0, speedY, 0)
	
	wait(0.01)
until false
3 Likes

To be honest, it would be nice if you could specify a little more, however, you mention that the piece “catches on the ground.” Maybe because you are moving the piece down continuously in the moveSonicDown loop. Instead of doing this, you could try letting Roblox’s physics system take care of gravity for you (That’s my understanding)

Try removing the moveSonicDown function and put this:

repeat
    --BASIC CHECKS
    if collisionBtmLeft == false and collisionBtmRight == false then
        inAir = 1
    elseif collisionBtmLeft == true and collisionBtmRight == false then
        inAir = 0.8
    elseif collisionBtmLeft == false and collisionBtmRight == true then
        inAir = 0.4
    elseif collisionBtmLeft == true and collisionBtmRight == true then
        inAir = 0
    end

    if inAir == 1 then
        if collisionBtmLeft == false and collisionBtmRight == false then
            speedY = speedY - 0.1
        end
    else
        speedY = 0
    end

    -- MOVE PLAYER AND ANCHOR POINTS
    script.Parent.Parent.btmRightAnchorPoint.CFrame = script.Parent.Parent.btmRightAnchorPoint.CFrame + Vector3.new(0, speedY, 0)
    script.Parent.Parent.btmLeftAnchorPoint.CFrame = script.Parent.Parent.btmLeftAnchorPoint.CFrame + Vector3.new(0, speedY, 0)
    script.Parent.CFrame = script.Parent.CFrame + Vector3.new(0, speedY, 0)

    wait(0.01) 

until false

Let me know if I understood you correctly and if it works

that is exactly what’s happening, i said that the function (in reference to this) goes unused but i probably should’ve just removed it from the code. also, the parts ARE unanchored but I set the world’s gravity to 0 because Roblox’s gravity doesn’t accelerate the longer you’re in the air.

Oops, in the previous code I have sent some extra things (my bad) Try this:

script.Parent.Parent.btmLeftAnchorPoint.TouchEnded:Connect(function()
    collisionBtmLeft = false
end)
script.Parent.Parent.btmRightAnchorPoint.TouchEnded:Connect(function()
    collisionBtmRight = false
end)

local lastTime = tick()

game:GetService("RunService").Stepped:Connect(function()
    --BASIC CHECKS
    if collisionBtmLeft == false and collisionBtmRight == false then
        inAir = 1
    elseif collisionBtmLeft == true and collisionBtmRight == false then
        inAir = 0.8
    elseif collisionBtmLeft == false and collisionBtmRight == true then
        inAir = 0.4
    elseif collisionBtmLeft == true and collisionBtmRight == true then
        inAir = 0
    end

    -- GRAVITY
    local deltaTime = tick() - lastTime
    if inAir == 1 then
        if collisionBtmLeft == false and collisionBtmRight == false then
            speedY = speedY - 0.1 * deltaTime
        end
    else
        speedY = 0
    end

    -- MOVE PLAYER AND ANCHOR POINTS
    script.Parent.Parent.btmRightAnchorPoint.CFrame = script.Parent.Parent.btmRightAnchorPoint.CFrame + Vector3.new(0, speedY, 0)
    script.Parent.Parent.btmLeftAnchorPoint.CFrame = script.Parent.Parent.btmLeftAnchorPoint.CFrame + Vector3.new(0, speedY, 0)
    script.Parent.CFrame = script.Parent.CFrame + Vector3.new(0, speedY, 0)

    lastTime = tick()
end)

Theoretically that should solve the problem :thinking:, since I have added more actions in the RunService that have worked for me in Roblox Studio at the moment (just as a test) :wink: lmk

Hi, I noticed you are relying on touched events to detect when the part reaches the ground, however, depending on the speed of the part, the step in which the touched event is activated could well be the one where it overshoots the boundary of the ground causing it to clip.
Basically, parts render/calculate physics at most 60 times per second at a specific location, it just looks like they are traveling because it is so fast. But for higher speed events if the last render point of the part was closer than the distance it should travel on the next step it will clip.

To get around this I recommend raycasting in the direction of travel to the next expected render location, and if a hit is returned set the final cframe to that location (taking into account part size), and activating the code currently in the touched events.

This method moves Sonic slower but there’s still a little bit of overlap (and now the anchor points seem to overlap too)


1 Like

Try this:

local inAir = script.Parent.Variables.inAir
local speedY = script.Parent.Variables.speedY
local collisionBtmRight = script.Parent.Variables.collisionBtmRight
local collisionBtmLeft = script.Parent.Variables.collisionBtmLeft
local dTime = 0.01

-- No need for the 'wait(10)' statement at the beginning

script.Parent.Parent.btmLeftAnchorPoint.Touched:Connect(function(part)
    if part.BrickColor == BrickColor.new("Institutional white") then
        collisionBtmLeft = true
    end
end)

script.Parent.Parent.btmRightAnchorPoint.Touched:Connect(function(part)
    if part.BrickColor == BrickColor.new("Institutional white") then
        collisionBtmRight = true
    end
end)

script.Parent.Parent.btmLeftAnchorPoint.TouchEnded:Connect(function()
    collisionBtmLeft = false
end)

script.Parent.Parent.btmRightAnchorPoint.TouchEnded:Connect(function()
    collisionBtmRight = false
end)

game:GetService("RunService").Heartbeat:Connect(function()
    local touchingBtmLeft = script.Parent.Parent.btmLeftAnchorPoint:GetTouchingParts()
    local touchingBtmRight = script.Parent.Parent.btmRightAnchorPoint:GetTouchingParts()
    
    local grounded = false
    
    for i = 1, #touchingBtmLeft do
        if touchingBtmLeft[i].Name == "Solid" and touchingBtmLeft[i].BrickColor == BrickColor.new("Institutional white") then
            grounded = true
        end
    end

    for i = 1, #touchingBtmRight do
        if touchingBtmRight[i].Name == "Solid" and touchingBtmRight[i].BrickColor == BrickColor.new("Institutional white") then
            grounded = true
        end
    end

    if grounded then
        speedY = 0
    else
    end

    script.Parent.Parent.btmRightAnchorPoint.CFrame = script.Parent.Parent.btmRightAnchorPoint.CFrame + Vector3.new(0, speedY, 0)
    script.Parent.Parent.btmLeftAnchorPoint.CFrame = script.Parent.Parent.btmLeftAnchorPoint.CFrame + Vector3.new(0, speedY, 0)
    script.Parent.CFrame = script.Parent.CFrame + Vector3.new(0, speedY, 0)
end)

Sonic just doesn’t move at all now

1 Like

This method was originally working but now Sonic just goes way further than before. Maybe it’s just my crappy scripting but here’s what I mean


and here’s what I came up w/

local inAir = script.Parent.Variables.inAir.Value
local speedY = script.Parent.Variables.speedY.Value
local collisionBtmRight = script.Parent.Variables.collisionBtmRight.Value
local collisionBtmLeft = script.Parent.Variables.collisionBtmLeft.Value

wait(10)

--COLLISIONS
script.Parent.Parent.btmLeftAnchorPoint.Touched:Connect(function(part)
	if part.BrickColor == BrickColor.new("Institutional white") then
		print("hi")
		collisionBtmLeft = true
	end
end)
script.Parent.Parent.btmRightAnchorPoint.Touched:Connect(function(part)
	if part.BrickColor == BrickColor.new("Institutional white") then
		print("bye")
		collisionBtmRight = true
	end
end)
script.Parent.Parent.btmLeftAnchorPoint.TouchEnded:Connect(function()
	collisionBtmLeft = false
end)
script.Parent.Parent.btmRightAnchorPoint.TouchEnded:Connect(function()
	collisionBtmRight = false
end)

game:GetService("RunService").Heartbeat:Connect(function()
	script.Parent.Parent.btmRightAnchorPoint.Touched:Connect(function() end)
	local touching = script.Parent.Parent.btmRightAnchorPoint:GetTouchingParts()
	for i=1,#touching do
		if touching[i].Name == "Solid" and touching[i].BrickColor == BrickColor.new("Institutional white") then
			speedY = 0
		end
	end
	script.Parent.Parent.btmLeftAnchorPoint.Touched:Connect(function() end)
	local touching = script.Parent.Parent.btmLeftAnchorPoint:GetTouchingParts()
	for i=1,#touching do
		if touching[i].Name == "Solid" and touching[i].BrickColor == BrickColor.new("Institutional white") then
			speedY = 0
		end
	end
end)

repeat
	--BASIC CHECKS
	if collisionBtmLeft == false and collisionBtmRight == false then
		inAir = 1
	elseif collisionBtmLeft == true and collisionBtmRight == false then
		inAir = 0.8
	elseif collisionBtmLeft == false and collisionBtmRight == true then
		inAir = 0.4
	elseif collisionBtmLeft == true and collisionBtmRight == true then
		inAir = 0
	end

	--GRAVITY
	if inAir == 1 then
		if collisionBtmLeft == false and collisionBtmRight == false then
			speedY = speedY - 0.1
		end
	else
		speedY = 0
	end

	--NO-CLIPPING CHECKS
	local newBtmRightAnchorPoint = script.Parent.Parent.btmRightAnchorPoint:Clone()
	local newBtmLeftAnchorPoint = script.Parent.Parent.btmLeftAnchorPoint:Clone()
	newBtmLeftAnchorPoint.Name = "newBtmLeftAnchorPoint"
	newBtmRightAnchorPoint.Name = "newBtmRightAnchorPoint"
	newBtmLeftAnchorPoint.CFrame = newBtmLeftAnchorPoint.CFrame + Vector3.new(0, speedY, 0)
	newBtmRightAnchorPoint.CFrame = newBtmRightAnchorPoint.CFrame + Vector3.new(0, speedY, 0)
	local params = RaycastParams.new()
	params.FilterDescendantsInstances = {
		workspace.MainElements, workspace.Baseplate
	}
	local raycast = workspace:Raycast(script.Parent.Parent.btmLeftAnchorPoint.Position, (newBtmLeftAnchorPoint.Position - script.Parent.Parent.btmLeftAnchorPoint.Position), params)
	if raycast then
		if raycast.Instance.Name == "Solid" and raycast.Instance.BrickColor == BrickColor.new("Institutional white") then
			script.Parent.Parent.btmLeftAnchorPoint.Position = raycast.Position
		end
	else
		script.Parent.Parent.btmLeftAnchorPoint.CFrame = script.Parent.Parent.btmLeftAnchorPoint.CFrame + Vector3.new(0, speedY, 0)
	end
	
	local raycast2 = workspace:Raycast(script.Parent.Parent.btmRightAnchorPoint.Position, (newBtmRightAnchorPoint.Position - script.Parent.Parent.btmRightAnchorPoint.Position), params)
	if raycast2 then
		if raycast2.Instance.Name == "Solid" and raycast2.Instance.BrickColor == BrickColor.new("Institutional white") then
			script.Parent.Parent.btmRightAnchorPoint.Position = raycast2.Position
		end
	else
		script.Parent.Parent.btmRightAnchorPoint.CFrame = script.Parent.Parent.btmRightAnchorPoint.CFrame + Vector3.new(0, speedY, 0)
	end
	
	newBtmRightAnchorPoint:Destroy()
	newBtmLeftAnchorPoint:Destroy()
	
	--MOVE SONIC
	if raycast then
		script.Parent.CFrame = script.Parent.CFrame + Vector3.new(0, script.Parent.Parent.btmLeftAnchorPoint.Position.Y + (script.Parent.Size.Y/2), 0)
	else
		script.Parent.CFrame = script.Parent.CFrame + Vector3.new(0, speedY, 0)
	end

	wait(0.01)
until false
1 Like

Did you adjust the code to what you need, or just simply copy and paste it?

1 Like

Most likely should’ve done the latter. Let me try that again.

I adjusted the code and Sonic still clips far too much into the floor, even with a way shorter distance than all the other ones.

1 Like

I’ve simplified the collision checking and made sure that the player’s position is adjusted consistently with the velocity (speedY). This should help prevent Sonic from clipping into the floor.

local inAir = script.Parent.Variables.inAir
local speedY = script.Parent.Variables.speedY
local collisionBtmRight = script.Parent.Variables.collisionBtmRight
local collisionBtmLeft = script.Parent.Variables.collisionBtmLeft

wait(10)

script.Parent.Parent.btmLeftAnchorPoint.Touched:Connect(function(part)
    if part.BrickColor == BrickColor.new("Institutional white") then
        collisionBtmLeft = true
    end
end)

script.Parent.Parent.btmRightAnchorPoint.Touched:Connect(function(part)
    if part.BrickColor == BrickColor.new("Institutional white") then
        collisionBtmRight = true
    end
end)

script.Parent.Parent.btmLeftAnchorPoint.TouchEnded:Connect(function()
    collisionBtmLeft = false
end)

script.Parent.Parent.btmRightAnchorPoint.TouchEnded:Connect(function()
    collisionBtmRight = false
end)

game:GetService("RunService").Heartbeat:Connect(function()
    local touchingBtmLeft = script.Parent.Parent.btmLeftAnchorPoint:GetTouchingParts()
    local touchingBtmRight = script.Parent.Parent.btmRightAnchorPoint:GetTouchingParts()
    
    local grounded = false
    
    for i = 1, #touchingBtmLeft do
        if touchingBtmLeft[i].Name == "Solid" and touchingBtmLeft[i].BrickColor == BrickColor.new("Institutional white") then
            grounded = true
        end
    end

    for i = 1, #touchingBtmRight do
        if touchingBtmRight[i].Name == "Solid" and touchingBtmRight[i].BrickColor == BrickColor.new("Institutional white") then
            grounded = true
        end
    end

    if grounded then
        speedY = 0
    else
        speedY = speedY - 0.1
    end

    script.Parent.CFrame = script.Parent.CFrame + Vector3.new(0, speedY, 0)
end)
1 Like

sonic just doesnt stop falling at all. maybe i should provide the hiarchy (im not searching up how to spell it)
Screenshot 2023-11-01 162939

1 Like

Can you tell me where you are putting my code?

1 Like

everything that controls Sonic (besides the button presses which will be handled in a local script (dont worry it will fire remote events) goes in the “Main” script

Okay, so give me a description on Sonic. Is he supposed to move? Is he supoosed to do x,y,z?

He’s only supposed to move on 2 axis (Y, Z (or X I always get the 2 mixed up)) and what I’m planning on doing is having different colored parts for collision (white for solid, red for death, yellow for semisolid, etc)

local inAir = script.Parent.Variables.inAir
local speedY = script.Parent.Variables.speedY
local collisionBtmRight = script.Parent.Variables.collisionBtmRight
local collisionBtmLeft = script.Parent.Variables.collisionBtmLeft

local whiteColor = BrickColor.new("Institutional white")

local function isCollisionPartSolid(part)
    return part.BrickColor == whiteColor
end

wait(10)

script.Parent.Parent.btmLeftAnchorPoint.Touched:Connect(function(part)
    if isCollisionPartSolid(part) then
        collisionBtmLeft = true
    end
end)

script.Parent.Parent.btmRightAnchorPoint.Touched:Connect(function(part)
    if isCollisionPartSolid(part) then
        collisionBtmRight = true
    end
end)

script.Parent.Parent.btmLeftAnchorPoint.TouchEnded:Connect(function()
    collisionBtmLeft = false
end)

script.Parent.Parent.btmRightAnchorPoint.TouchEnded:Connect(function()
    collisionBtmRight = false
end)

game:GetService("RunService").Heartbeat:Connect(function()
    local touchingBtmLeft = script.Parent.Parent.btmLeftAnchorPoint:GetTouchingParts()
    local touchingBtmRight = script.Parent.Parent.btmRightAnchorPoint:GetTouchingParts()
    
    local grounded = false
    
    for i = 1, #touchingBtmLeft do
        if isCollisionPartSolid(touchingBtmLeft[i]) then
            grounded = true
        end
    end

    for i = 1, #touchingBtmRight do
        if isCollisionPartSolid(touchingBtmRight[i]) then
            grounded = true
        end
    end

    if grounded then
        speedY = 0
    else
        speedY = speedY - 0.1
    end

    -- Update your Z (or X) position here
    local newPosition = script.Parent.Position + Vector3.new(0, speedY, 0) -- Modify as needed
    script.Parent.Position = newPosition
end)

ve added a whiteColor variable to make it easier to check for white collision parts. Also, I’ve adjusted the code to update the position on the Y axis (Z axis in Roblox) while restricting movement on the other axis (X axis in Roblox). Be sure to modify the newPosition calculation.

fixed this one also… 6 months later like the other 3 posts. you can learn more here: Sonic 1 Camera not Working