Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
1

How do I push a character away from a part? (Repost, self-answered) [closed]

Asked by
BenSBk 781 Moderation Voter
6 years ago

Somebody recently asked a question about how you could push a character away from a part when the character touches the part. I wrote a detailed answer, but the question was deleted, so I'll post the answer as an answer to my own question instead, in case anybody has the same question.

0
I remember that, I was wondering where that question went. SteamG00B 1633 — 6y
0
ja BenSBk 781 — 6y

Locked by SteamG00B, fredfishy, and Amiaa16

This question has been locked to preserve its current state and prevent spam and unwanted comments and answers.

Why was this question closed?

1 answer

Log in to vote
2
Answered by
BenSBk 781 Moderation Voter
6 years ago

Let's assume that we have a BasePart named "Part", which is the part that will push Players' characters away.

local part = workspace.Part

We'll need to connect a function to BasePart.Touched, an RBXScriptSignal that fires whenever a BasePart touches the BasePart, with the other BasePart passed as the only argument.

local part = workspace.Part

part.Touched:Connect(function(other_part)

end)

When part is touched, let's first check if other_part belongs to a character or not with Players:GetPlayerFromCharacter. If not, we'll return from the function. If so, we'll continue and keep the character for later.

local players = game:GetService("Players")
local part = workspace.Part

part.Touched:Connect(function(other_part)
    -- Check if other_part doesn't belong to a character.
    local character = other_part.Parent
    if not players:GetPlayerFromCharacter(character) then
        return
    end
end)

Then, we'll check if the character has a Humanoid or not with Instance:FindFirstChild. If not, we'll return from the function. If so, we'll continue and keep the Humanoid for later.

local players = game:GetService("Players")
local part = workspace.Part

part.Touched:Connect(function(other_part)
    -- Check if other_part doesn't belong to a character.
    local character = other_part.Parent
    if not players:GetPlayerFromCharacter(character) then
        return
    end
    -- Check if character has no Humanoid.
    local humanoid = character:FindFirstChild("Humanoid")
    if not humanoid then
        return
    end
end)

Now that we've done the necessary gets and checks, we can push the character away from part. First, we'll sit the Humanoid with Humanoid.Sit = true, otherwise the character won't always be pushed. After that, we'll instantiate CFrame at part.Position facing towards other_part.Position. Think of the CFrame as an arrow pointing away from part and towards other_part. This arrow is the direction that we want the character to be pushed, away from part. To get the Vector3 that describes the direction this arrow is pointing, we can use CFrame.LookVector. Now that we have the desired direction, we'll instantiate BodyForce and assign its BodyForce.Force to the direction multiplied by a multiplier (let's go with 5000). Finally, let's assign its parent to other_part.

local players = game:GetService("Players")
local part = workspace.Part

part.Touched:Connect(function(other_part)
    -- Check if other_part doesn't belong to a character.
    local character = other_part.Parent
    if not players:GetPlayerFromCharacter(character) then
        return
    end
    -- Check if character has no Humanoid.
    local humanoid = character:FindFirstChild("Humanoid")
    if not humanoid then
        return
    end
    -- Push other_part away from part.
    humanoid.Sit = true
    local direction = CFrame.new(part.Position, other_part.Position).LookVector
    local body_force = Instance.new("BodyForce")
    body_force.Force = direction * 5000
    body_force.Parent = other_part
end)

This works fine, except body_force stays there permanently. Let's Instance:Destroy it after 0.5 seconds.

local players = game:GetService("Players")
local part = workspace.Part

part.Touched:Connect(function(other_part)
    -- Check if other_part doesn't belong to a character.
    local character = other_part.Parent
    if not players:GetPlayerFromCharacter(character) then
        return
    end
    -- Check if character has no Humanoid.
    local humanoid = character:FindFirstChild("Humanoid")
    if not humanoid then
        return
    end
    -- Push other_part away from part.
    humanoid.Sit = true
    local direction = CFrame.new(part.Position, other_part.Position).LookVector
    local body_force = Instance.new("BodyForce")
    body_force.Force = direction * 5000
    body_force.Parent = other_part
    wait(0.5)
    body_force:Destroy()
end)

Finally, we should only have one BodyForce per character. Let's create a dictionary with character as keys and true or nil as values (describing whether or not the character has a BodyForce). We'll check and update this appropriately.

local players = game:GetService("Players")
local part = workspace.Part
local character_body_forces = {}

part.Touched:Connect(function(other_part)
    -- Check if other_part doesn't belong to a character.
    local character = other_part.Parent
    if not players:GetPlayerFromCharacter(character) then
        return
    end
    -- Check if character already has a BodyForce. If not, update.
    if character_body_forces[character] then
        return
    end
    character_body_forces[character] = true
    -- Check if character has no Humanoid.
    local humanoid = character:FindFirstChild("Humanoid")
    if not humanoid then
        return
    end
    -- Push other_part away from part.
    humanoid.Sit = true
    local direction = CFrame.new(part.Position, other_part.Position).LookVector
    local body_force = Instance.new("BodyForce")
    body_force.Force = direction * 5000
    body_force.Parent = other_part
    wait(0.5)
    body_force:Destroy()
    character_body_forces[character] = nil
end)

I hope this helped!

0
I am sure that this will help quite a lot of people because it is an excessive explanation :) SteamG00B 1633 — 6y
Ad