Hi Pie_exe, I’m going to give you a solution that probably won’t be the best but will work. I will try to explain how I achieved this. The blue texts will be links to the documentation so that you can read the description and maybe even learn to use them without needing our help!
There are several ways to detect the collision between two parts in Roblox. One of the most well-known, especially among those who are just starting, is the signals Touched and TouchEnded. But this evening I don’t really want to use them because we could make it simpler with something else.
We could use the method GetTouchingParts which, as written in his description, returns a table of all parts that are physically interacting with the desired part. If you would make your own tests, you would have noticed that just doesn’t work.
By reading the description of this method we can see that Roblox gives us alternatives to that like workspace:
GetPartsInPart()
, once again, in making your own tests, you would noticed that works this time, but not every time. This is due to the fact that as said in the name, this method detects the parts which are in the one we are checking, it does not check if there is a collision just if it overlaps.
Once again, the description of this method gives us alternatives. I was interested to workspace:
GetPartBoundsInBox()
. This method is similar to the last one but instead of using a part it uses its position and its size, which is interesting to achieve our objective. We could slightly adjust the position and size so that the specified area is above your platform and not within the platform.
Simple calculations can help us achieve this. I will use a variable to store the offset and in the same time using it to the size of the box. In this example the offset and size will be 0.2 stud.
local Offset = 0.2
I will now get the platform and get the size
and position
of it.
local Offset = 0.2 -- We will slightly raise the position of the part to make sure the player is detected
local Platform = script.Parent
local CurrPartCF = Platform.CFrame
local CurrPartSize = Platform.Size
Now that we have the foundation, we can move on to the calculations. We will create a new CFrame and a new Vector3 to edit the last one and get the good result. To do this, we will take the currPartCF.Y
add its value with the half of CurrPartSize.Y
and the half of Offset
. We keep the same values on the X
and Z
axes.
local FinalPartCF = CFrame.new(CurrPartCF.X, CurrPartCF.Y + (CurrPartSize.Y / 2) + (Offset / 2), CurrPartCF.Z)
For the size, we keep the same X
and Z
axes but you will use the Offset
for the Y
axe like that:
local FinalPartSize = Vector3.new(CurrPartSize.X, Offset, CurrPartSize.Z)
We can create a part to see if we are good with these new values:
Yes we are correct! We can move for the next step.
We will make a loop to continuous cheking if a player touch the platform like that:
while true do
local parts = workspace:GetPartBoundsInBox(FinalPartCF, FinalPartSize, OverlapParams.new()) -- Gets the table of players who touch the part
task.wait(1) -- Wait 1 second before the next cycle
end
Know that you can adjust OverlapParams, but I’ll let you read the documentation for that.
The method we used returns a table, so we will use a generic loop to loop through it, you can also use a numeric loop if you wish.
for _, hit in pairs(parts) do
-- We go through the table here element by element
end
We still have a few things to sort out but I’ll let you discover the final code and experiment for yourself. I also put comments to help you understand, but I explained the most complex part to you
-- Services
local PlayerService = game:GetService("Players")
-- Variables
local Offset = 0.2 -- We will slightly raise the position of the part to make sure the player is detected
local Platform = script.Parent
local CurrPartCF = Platform.CFrame
local CurrPartSize = Platform.Size
local FinalPartCF = CFrame.new(CurrPartCF.X, CurrPartCF.Y + (CurrPartSize.Y / 2) + (Offset / 2), CurrPartCF.Z)
local FinalPartSize = Vector3.new(CurrPartSize.X, Offset, CurrPartSize.Z)
-- Functions
local function GetPlayerFromHit(hit)
local model = hit:FindFirstAncestorWhichIsA("Model") -- Find the first ancestor model of the instance
local player = PlayerService:GetPlayerFromCharacter(model) -- Try to find if model is a player's character, return nil if model is nil
return player
end
-- Loop
while true do
local parts = workspace:GetPartBoundsInBox(FinalPartCF, FinalPartSize, OverlapParams.new()) -- Gets the table of players who touch the part
local AlreadyGotHisTime = {} -- Stores players who have already had their time
for _, hit in pairs(parts) do
local player = GetPlayerFromHit(hit)
local block = table.find(AlreadyGotHisTime, player) -- Checks that the player has not already obtained his time in cases where several parts are in the table obtained part GetPartBoundsInBox
if player and (not block) then
table.insert(AlreadyGotHisTime, player) -- Add the player to the list of players who have already obtained their times
workspace.IntValue.Value += 1 -- Add 1 to the value
end
end
task.wait(1) -- Wait 1 second before the next cycle
end
You now know how you must proceed to succeed in achieving what you want to do. I hope I helped you and if you have any questions please don’t hesitate to ask me.