Anti Character Void

Something like this?

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! :smiley:
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.

1 Like

I’m actually concerned with what you’ve said here

Humanoid.FreeFalling will fire during falling and when landed, I tested jumping and it printed true then false. It also says in the wiki:

image

Or am I not getting something?

Well the event will fire twice, but the variable doesn’t update on the second time. Your loop will keep going forever.

1 Like

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.

1 Like

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.

2 Likes

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.

The velocity is negative while falling, positive velocity goes up.

Perhaps using (HumanoidRootPart.Velocity.Y) ~= 0 will do?

1 Like

@Hexcede proposed to use math.abs though which should return a positive value when the velocity is negative.

1 Like

Hang on, I’m blind. Did not see that when I was reading in broad daylight, but at least ~= 0 works.

1 Like

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.

Maybe because it was checked immediately after the signal. The case of scenario is when you start falling, the velocity is 0.

Try delaying slightly and see if it changes anything.

Wait, it does not have a PrimaryPart? Usually a character has their PrimaryPart HumanoidRootPart.

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.

I wonder if setting the velocity of all descendants to the character prevents the accelerating speeds. Try that too.

If all else fails, anchor the player after teleportation and delay their unanchoring for some time.

1 Like

Something is quite strange with this…

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.

Update:
Nope, still didn’t work.

Oh yeah, forgot to mention this is a local script. Perhaps some remote events will help?

Else you could possibly use a BodyPosition in the character which will move to a safe position in workspace.

1 Like

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.

Would Region3 be an option then? I’m not entirely sure how it affects the game in performance.

My map covers a very big area and I think large region 3 areas are performance heavy? This would still require an infinite loop though.

Edit:
I’ll update this thread later, I’m currently still searching for another method that makes use of events.

1 Like

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 :slight_smile:

6 Likes