Issue with my semi-solid platform

Howdy! I’m making semi-solid platforms for my 2D game. Basically, when a player jumps underneath it, the player can pass through it until they land on the platform. I also made it so when the player crouches/presses down, they can pass through the platform again, going down.

The main issue I have is with the going down part. It works… too well, I’d say?

Basically, whenever the player crouches, EVERY platforms go CanCollide false.

Here’s the script!

local RS = game:GetService("ReplicatedStorage")

local goDown = RS.Events:FindFirstChild("goDownEvent")
local platform = script.Parent
local standing


local function goingDown()
	platform.CanCollide = false
	standing = false
	wait(1)
end


local function onTouch(hit)

	if hit.Name == "Head" or hit == hit:FindFirstChild("HatAttachment") or hit == hit:FindFirstChild("HairAttachment") then
		platform.CanCollide = false
		standing = true
	elseif hit.Name == "Right Leg" or hit.Name == "Left Leg" then
		if standing then
			platform.CanCollide = true
		end
		goDown.OnServerEvent:Connect(goingDown)
	end
end

platform.Touched:Connect(onTouch)

Platforms stay that way until I jump back on them and seem to ignore the legs while I’m falling through them.

I tried making it so it goes back to being CanCollide after the wait, in the goingDown function. It kind of makes things better, but not much, as every platforms are still affected and I have another issue where basically if the platform is CanCollide, the player has to hit it a few times before it actually let them through.
I was thinking maybe I could use another remote event for when the player stops crouching, but it seems more like it would make the player get stuck against a platform if they let go of the down key while passing through a platform (which also happens with making the platforms CanCollide after the wait in the goingDown function, adjusting the wait time isn’t really ideal either to be honest).

I thank you in advance for your help!

2 Likes

Wait so if I understand it right, the platform works this way:

Jumping from underneath makes it so you can go through until you land on it.
Crouching on the platform makes you go through it.

Am I missing something?

That’s how it works, yup! But if I crouch, on a platform or not, every platforms can get passed through and it also ignores the part where if the legs touch them, they get solid again.

What is the goingDown() function for? When exactly does it get fired?
I’d recommend starting over with different approach, you could use player Velocity and check if when touched the part the velocity is going up Velocity.Y > 0 and for the crouch, when you crouch I’d fire a Raycast down and check if you are standing on a platform, if yes → make it CanCollide = false.

2 Likes

There is another approach you can do which is a lot simpler to do.

Simply check if the platform is beneath the player.

You can check the Position of the HumanoidRootPart Vs the Height position of the Platform.

Part.Touched(function(otherPart)
    if otherPart.Positiom.Y < Part.Position.Y then
        Part.CanCollide = false
    end
end)

Note: There are some cases if a platform is a tall wall you may be able to pass through it. In those cases make sure you differentiate between a platform and a wall.

In case you want to drop down from a part you can simply change the part to Cancollide off.

1 Like

The goingDown() function is called whenever the player crouches: Crouching fires a remote event from my player control LocalScript to the server. There isn’t really any part in any script that indicates that the player is standing on the platform and it seems like connecting the goingDown() function inside the onTouch() one doesn’t really do anything either way.

Starting over seems to be the best option. It’s not much of a big deal, gotta learn after all!
I’m going to try what you suggested, using Velocity and Raycast. I’m not really familiar with these, it will be fun to learn. I’ll come back with the results later!

Make sure to notify me with the results you’ve achieved!

1 Like

I took both your and Agent_Invalid’s advices and it appears to work well now! Well, I don’t exactly know if it will affect performances, but it seems to do the trick really well already!

The script inside each platforms:

local Players = game:GetService("Players")
local RunS = game:GetService("RunService")

local platform = script.Parent

game.Players.PlayerAdded:Connect(function(player)
	RunS.Heartbeat:Connect(function()

		local character = player.Character or player.CharacterAdded:wait()
		local root = character:FindFirstChild("HumanoidRootPart")

		if root.Position.Y < platform.Position.Y then
			platform.CanCollide = false
		else 
			platform.CanCollide = true
		end
	end)
end)

The Raycast function inside my control script:

local function fireCaster()
	local rayOrigin = Root.Position
	local rayDirection = Vector3.new(0,-4,0)
	local raycastParams = RaycastParams.new()
	raycastParams.FilterDescendantsInstances = {game.Workspace.Platforms:GetChildren()}
	raycastParams.FilterType = Enum.RaycastFilterType.Whitelist
	local raycastResult = workspace:Raycast(rayOrigin, rayDirection, raycastParams)
	
	if raycastResult then
		local hitPart = raycastResult.Instance
		if hitPart.Name == "Platform" then
			hitPart.CanCollide = false
		end
	end
end

It is fired at the very end of the crouch function.
If the player is already crouching and goes on a platform, they won’t pass through it unless they let go of the down key. If they fall from a platform to another while holding the down key, the character will crouch when landing and will not pass through the platform. In both scenarios, if the player let go of the down key while on a platform, they will pass through it.
That’s pretty much what I want.

I thank you a lot! It was kind of you to help me with this and I learned new things in the end! It will be really helpful in developing my game.

Here’s a little video to demonstrate the final result!

I’m loving it, it looks really cool!

One thing, the .Heartbeat shouldn’t really mess up with the performance, but if you have a lot of those “Platforms” then it could affect some computers, I’m not talking about big performance issues but just slight ones. I’d recommend instead of using .Heartbeat simply use BasePart.Touched.

local platform = script.Parent

local function touched(hit)
   if hit ~= nil then
      local player = game.Players:GetPlayerFromCharacter(hit.Parent)

      if player ~= nil then
         local character = player.Character

         if player.PrimaryPart.Position < platform.Position.Y then
            platform.CanCollide = false
         else
            platform.CanCollide = true
         end
      end
   end
end

platform.Touched:connect(touched)

Your script would make new function with heartbeat every time a new player joins, if the game is a single player it shouldn’t really matter but the script above should do the trick with performance :wink:

1 Like

The game is singleplayer, but if anything happens I’ll make sure to do that, thank you!