local function OnHumanoidFreeFalling()
while math.abs(HumanoidRootPart.Velocity.Y) > 0 do
if HumanoidRootPart.Position.Y < -100 then
print("Falling")
Character:SetPrimaryPartCFrame(CFrame.new(0,100,0)) --this position is not final
end
wait(0.1)
end
end
Humanoid.FreeFalling:Connect(OnHumanoidFreeFalling)
That would work!
Any variables you receive through a function call are sort of just copies… If you change the passed variable it doesn’t change inside the function. And if you change the variable in the function it won’t change outsideof the function.
You can fix the speed issue pretty easily by putting a BodyForce inside the character, and giving it an upward force proportional to the characters downward velocity (in a loop). Effectively giving the character a terminal velocity.
There is one case where this can get you in trouble, which is if your character ends up getting flung towards the kill plane at a high velocity on a client’s machine that is struggling to get a perfect physics framerate. What can happen is that a small bit of lag can result in overcorrection, which goes into unstable (growing) oscillation. That is the particular peril you get when you specify a force or acceleration as a correction in a stepped physics simulation. You can’t use the time delta argument to Stepped or Heartbeat to mitigate it either, since it’s the future step’s duration that’s the problem. The safe option is to set the part Velocity or BodyVelocity, etc. When you deal with velocity, you’re safely one derivative away from the problem.
After further testing, it seems that your suggested method does not always work, however the loop will stop when necessary. There is a rare case when a player is falling, the FreeFalling event will trigger, but cannot get past this condition
while math.abs(HumanoidRootPart.Velocity.Y) > 0 do
I can conifrm that the velocity is greater than 0, but it still doesn’t work? I will look further into this, but I still don’t understand how this tends to fail.
I just tried the method you provided, however it tends to fail as well?
Code:
local Character = script.Parent
local Humanoid = Character:WaitForChild("Humanoid")
local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")
local function OnHumanoidFreeFalling()
print("Event Fired")
while HumanoidRootPart.Velocity.Y ~= 0 do
print("Active")
if HumanoidRootPart.Position.Y <= -50 then
print("Teleporting")
local Success, ErrorCode = pcall(function()
Character:SetPrimaryPartCFrame(CFrame.new(0,700,0))
end)
print(Success, ErrorCode)
end
wait(0.1)
end
end
Humanoid.FreeFalling:Connect(OnHumanoidFreeFalling)
Output:
Event Fired
Active
Teleporting
false Model:SetPrimaryCFrame() failed because no PrimaryPart has been set, or the PrimaryPart no longer exists. Please set Model.PrimaryPart before using this.
The character was already falling though, so it had maintained it’s velocity after teleporting.
It does, however since a condition does not get satisfied (or something else), the character dies instead of teleporting, hence the error gets thrown.
Edit:
I adjusted the fall height incase the velocity was an issue, however the method still tends to fail even if the character is evidently falling fast.
if HumanoidRootPart.Position.Y <= -50 then
print("Teleporting")
HumanoidRootPart.Anchored = true
In the code above, “Teleporting” is printed, but the HumanoidRootPart does not get anchored all the time? The character is not falling super fast to surpass anything.
Edit:
I was actually editing the script while the game was running (face palm), I’ll be back with updates.
After further analysis… it seems that the velocity will become 0 when a player hits a part at a certain speed and bounces up and falls down (this stops the loop) My best solution so far is to consider using an infinite loop or place parts under the map. The down side of these two alternatives is the performance.
After several tests, I was able to come up with this:
local Character = script.Parent
local Humanoid = Character:WaitForChild("Humanoid")
local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")
local Falling = false
local function OnHumanoidFreeFalling(Active)
print("Event Fired")
Falling = Active
while Falling do
print("Active")
if HumanoidRootPart.Position.Y <= -50 then
print("Teleporting")
HumanoidRootPart.Anchored = true
wait(1)
local Success, Error = pcall(function()
for i,v in pairs(Character:GetDescendants()) do
if v:IsA("BasePart") then
v.Velocity = Vector3.new(0,0,0)
end
end
Character:SetPrimaryPartCFrame(CFrame.new(0,200,0))
end)
if Success then
HumanoidRootPart.Anchored = false
else
warn(Error)
end
end
wait(0.1)
end
end
Humanoid.FreeFalling:Connect(OnHumanoidFreeFalling)
The loop will stop when necessary and makes use of events. I also looped through the character and set all the base parts’ velocity to zero to prevent speeds that will cause issues, I may change this in the future. If anyone sees any potential imporvements, I’d be happy to know them