I’m trying to make a bezier curve work on characters however it is very unresponsible either due to player going forward or due to the character physics, any workarounds?
local t = 1;
local mouse = game.Players.LocalPlayer:GetMouse();
local hrp = game.Players.LocalPlayer.Character:WaitForChild("HumanoidRootPart");
mouse.Button1Down:Connect(function()
local g = Vector3.new(0, -game.Workspace.Gravity, 0);
local x0 = hrp.CFrame * Vector3.new(0, 2, -2)
-- calculate the v0 needed to reach mouse.Hit.p
local v0 = (mouse.Hit.p - x0 - 0.5*g*t*t)/t;
-- have the ball travel that path
local bv = Instance.new("BodyVelocity")
bv.Velocity = v0
bv.Parent = hrp
local nt = 0;
while (nt < t*2) do
bv.Velocity = CFrame.new(0.5*g*nt*nt + v0*nt + x0).Position
nt = nt + game:GetService("RunService").RenderStepped:Wait();
end
print("reached")
bv:Destroy()
end)
I had a similar problem, maybe a bit different in your case. I see that what you are doing is trying to get the player to go to some clicked position by manipulating the ball that is anchored to the player’s rootpart. What I realized is that in roblox, any attempt to do this will result in pretty weird physics.
The reason is because any time there is some type of weld, the calculations are always thrown off, using every method that I have known. Thus, even imparting velocity to the humanoidrootpart will not work.
For my game, the workaround I decided to do was use the humanoid MoveTo function with the HumanoidStateType to Jumping, to give the illusion that the player is jumping to a specific position
We can manipulate the jump height too based on how far away the player has clicked (but I did not implement this part yet). The only problem to my approach is that to reach some far away distance, we will need to calculate the jump height to something really high, and this can mean the player takes a while to reach that distance. To fix this, we do need some kind of velocity in the x direction, but of course, as I have said, the calculations are thrown off, so if you are fine with the player not perfectly reaching that position, then you can implement this.
Edit: thinking about this a bit more, the only other way I can think of is to keep raycasting to the target position constantly while the player’s State is FreeFall, and keep adding x-direction velocity (based on the distance which is another calculation) until the player is within some range, and when the player is close enough to that range, simply teleport the player to the position (this is minuscule if the targetposition is close enough to the player so the player should not notice this).
local humanoid = game.Players.LocalPlayer.CharacterAdded:Wait():WaitForChild("Humanoid");
-- note that typically gravity should be a negative value, but in this case I leave it positive hence the lack of -2 throughout the code
-- set the jump height to 10
humanoid.JumpPower = math.sqrt(2*game.Workspace.Gravity*10);
humanoid.StateChanged:Connect(function(old, new)
if (new == Enum.HumanoidStateType.Jumping) then
local h = humanoid.JumpPower^2/(2*game.Workspace.Gravity);
local t = 2*humanoid.JumpPower/game.Workspace.Gravity;
wait(t);
print(string.format("Jump took %s seconds and reached a max height of %s studs", t, h));
end
end)
This can be used from Modeling a projectile's motion to calculate both time and height, combining with the x,z velocity, we can technically use it.