I did that and it’s not changing much here’s the code I used.
while true do
wait()
if Partinbox == true then
linear_velocity.Enabled = true
local A = Character.PrimaryPart.Position
local B = Part.Position
local CharVel = Character.PrimaryPart.AssemblyLinearVelocity
local force = 4000 * (A - B).Magnitude
local VectorVel = (B - A).Unit * force
linear_velocity.VectorVelocity = VectorVel
else
linear_velocity.Enabled = false
end
end
Here you update the velocity to be applied to the player with each iteration of the loop. Instead, you want to calculate the velocity to be applied when the player first enters the gravitational field and then apply the velocity. That way, instead of updating the velocity in a loop, you remove the velocity when the player has left the gravitational field.
Let me know if you need some pseudocode demonstrating this!
First of all, avoid using variable names like “A” and “B.” Use “characterPosition” and “partPosition” instead; these names are longer but nobody has to go back through the code to figure out what they are. Styling your code correctly is essential. (Including indentation and spacing)
Don’t use wait, use task.wait(); pretty sure it performs better in every way possible. You can also do: while task.wait() do instead of while true do task.wait().
Lastly, relating to your actual problem, your force is getting stronger the further from the center you are, that’s why you’re getting that back-and-forth motion you referred to. Instead, the force should get weaker the further the player is. You can use division for this, though I assume you still want it to suck in the player momentarily at the beginning; you can do what you’re currently doing at the start, wait for a second or 2, then switch to the other one. OR, just math.max() the force to something reasonable.
Code for math.max() method
while task.wait() do
linear_velocity.Enabled = Partinbox
if not Partinbox then continue end
-- Get properties
local characterPosition = Character.PrimaryPart.Position
local partPosition = Part.Position
-- Calculate force
local force = 4000 * (characterPosition - partPosition).Magnitude
local forceMaxed = math.max(force, 20000)
-- Apply force
linear_velocity.VectorVelocity = (partPosition - characterPosition).Unit * forceMaxed
end
Using this method however I haven’t seen much change, I still get the back-and-forth movement. I tried messing with the force values but that didn’t help I could tweak them a little more but I’m unsure if that would actually fix the issue. Additionally, I still get moments where I walk into the circle and get pulled walk halfway out and then the force pulling me into the circle is less strong than the initial pull. I want the force to be consistent if that makes sense, I don’t want it to get lesser or greater the farther from the center you get but rather a consistent force being applied.
Heres my full code again to see if there’s something else that’s wrong.
--Services
local Replicated = game:GetService('ReplicatedStorage')
local UIS = game:GetService('UserInputService')
--
--Character/Player
local Players = game:GetService('Players')
local Player = Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local Humanoid = Character:WaitForChild('Humanoid')
local Animator = Humanoid:WaitForChild('Animator')
local RootPart = Character:WaitForChild('HumanoidRootPart')
local Mouse = Player:GetMouse()
local Animator = Humanoid:WaitForChild('Animator')
local TweenService = game:GetService("TweenService")
local Partinbox = false
--Body
local Part = workspace.UmbraField
local linear_velocity = Instance.new("LinearVelocity")
local Att1 = Instance.new("Attachment")
local Att0 = Instance.new("Attachment")
Att1.Name = "Att1"
Att0.Name = "Att0"
Att0.Parent = RootPart
Att1.Parent = Part
linear_velocity.Parent = Character.PrimaryPart
linear_velocity.Attachment0 = Att0
linear_velocity.Attachment1 = Att1
linear_velocity.Enabled = true
linear_velocity.MaxForce = 4032
local params = OverlapParams.new()
params.FilterType = Enum.RaycastFilterType.Include
params.FilterDescendantsInstances= {RootPart}
coroutine.wrap(function()
while task.wait() do
local PartsInBox = workspace:GetPartBoundsInRadius(Part.Position,24.6,params)
if PartsInBox[1] == RootPart then
Partinbox = true
else
Partinbox = false
end
end
end)()
while task.wait() do
linear_velocity.Enabled = Partinbox
if not Partinbox then continue end
-- Get properties
local characterPosition = Character.PrimaryPart.Position
local partPosition = Part.Position
-- Calculate force
local force = 4000 * (characterPosition - partPosition).Magnitude
local forceMaxed = math.max(force, 20000)
-- Apply force
linear_velocity.VectorVelocity = (partPosition - characterPosition).Unit * forceMaxed
end
For a constant force applied (no matter how far away you are), you’ll want to use this code:
Constant force code
while task.wait() do
linear_velocity.Enabled = Partinbox
if not Partinbox then continue end
-- Get properties
local characterPosition = Character.PrimaryPart.Position
local partPosition = Part.Position
-- Calculate force
local force = 4000
local characterToPartVector = (partPosition - characterPosition).Unit
-- Apply force
linear_velocity.VectorVelocity = characterToPartVector * force
end
It just sets the force to 4000 instead of the complicated math. You’ll have to change the force value to something greater if it doesn’t do anything.
Just a suggestion, but instead of using the LinearVelocity body mover you could adjust the velocity of the character directly; something like:
Adding force to character code
This likely has errors.
--[[ Services ]]--
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
--[[ Variables ]]--
local localPlayer = Players.LocalPlayer
local character = localPlayer.Character or Player.CharacterAdded:Wait()
local humanoidRootPart = character:WaitForChild("HumanoidRootPart")
local umbraField = workspace.UmbraField
local params = OverlapParams.new()
params.FilterType = Enum.RaycastFilterType.Include
params.FilterDescendantsInstances= {RootPart}
--[[ Functions ]]--
while task.wait() do
-- Check if the character is touching part
local umbraFieldPosition = umbraField.Position
PartsInBox = workspace:GetPartBoundsInRadius(umbraFieldPosition, 24.6, params)
if PartsInBox[1] ~= humanoidRootPart then continue end -- sus >_>
-- Get properties
local characterPosition = humanoidRootPart.Position
-- Calculate force
local characterToPartVector = (umbraFieldPosition - characterPosition).Unit
local force = characterToPartVector * 5
-- Apply force
humanoidRootPart.AssemblyLinearVelocity += force
--[[or "humanoidRootPart:ApplyImpulse(force)"]]
end
Again, if it doesn’t do anything, increase the force.
Well I believe you should switch how the distance is calculated as the further you are the stronger it gets because of how you set up this:
local force = 4000 * (A - B).Magnitude
--example: 4000 * 70(further away) = 280,000 , 4000 * 4 (closer) = 16,000
-- I believe it should be divided maybe that'll work,
- I believe this will work:
local force = 4000 / (A - B).Magnitude
After trying all the solutions you recommended, I found that adjusting the character’s velocity directly worked best. However, the only issue I found with that was when you get dragged into the middle of the circle walk a few steps towards the edge and stop you don’t get pulled back to the center with the same amount of force you got pulled in with. I’m content with leaving this as it is because I’m starting to think that maybe my goal isn’t achievable. If you guys have any clue on how to fix that issue, please tell me but if not, thanks for the help!
Interesting, not sure why that’d be happening, but here are my two guesses:
The line of code if PartsInBox[1] ~= humanoidRootPart then continue end is passing true more than it should be after the beginning. This would cause the code not to apply force to the character despite them being in the radius. If you want to fix this, then you’d have to check every part the GetPartsInRadius returned to see if it’s the humanoidRootPart.
or
The character stands still, and there isn’t a counterforce in the beginning like when you’re walking away.
It also might be that something else is adjusting the force of the character like a separate script.
Yes, it is a percentage, but the “1 -” doesn’t make it a percentage.
When I divide the player distance by the max distance it gives me a percentage value depending on how far the player is. 0% if the player is in the center, 100% if the player is on the edge. Though we want the opposite, therefore I do 1 - the original percentage value to get the inverse of that percentage. Now it’s 100% in the center and 0% on the edge.
Using the example above, if the player is 10 studs away then we get: local force = 4000 * (1 - 10 / 100) local force = 4000 * (1 - .1) local force = 4000 * .9 local force = 3600
if the player is 90 studs away then we get: local force = 4000 * (1 - 90 / 100) local force = 4000 * (1 - .9) local force = 4000 * .1 local force = 400
The math.min is to make sure we don’t multiply with negative numbers and the percentage value is between 0 and 1.
I meant if the distance is a 110 and you divide by 100 your going to get 1.1. Then when you do 1 - 1.1 you get a negative number of -.1 making the force -400.
Alright even after trying both solutions I’m still getting the back-and-forth motion. I don’t know what could possibly be wrong. If you are still willing to help, I strongly encourage you to edit the place in the link yourself because I feel I might be doing something wrong.
The solution here is very close to how I would solve it, but not quite right to me. The Linear Velocity constant is handy because it calculates a force that keeps a constant velocity, instead of applying a constant force, as constant force is constant acceleration. So My answer would be:
-- grab the direction.unit and multiply by force
local force = ((partPosition - Character.PrimaryPart.Position) * Vector3.new(1,0,1)).Unit * 5000 --Vector3.new(1,0,1) is used to cancel out any downward force
if partPosition - Character.PrimaryPart.Position > 0.1 then--prevents jittering at the center of the circle
force = Vector3.zero
end
-- Apply force
linear_velocity.VectorVelocity = force
Yes this does mean that it only works properly flat on the ground, but that can be changed. Hope this helps!