-
What do you want to achieve?
I want to achive a system that doesn’t fling me around when I am using my grappler. -
What is the issue?
I’m encountering an issue with my grappler where the player gets flung around uncontrollably. This happens because I’m setting the player’s rotation to a fixed Z and X rotation, while the Y rotation is set to match where the player is looking, similar to Shiftlock. However, this results in random forces being applied to the player for some reason.
I need to keep the applied rotation, so removing it isn’t an option. The reason I set the rotation in the first place is that when the player is in the physics state, they’re free to rotate. To prevent this, I set the rotation to keep the player upright, but this causes the flinging issue.
And also, the flinging gets extra intense when I am holding a tool while grappling. But it still happends when I don’t hold another tool just not as much, so the issue is not when I am holding a tool.
In the video, I don’t get flung around when not holding a tool but still setting the players rotation. That is because it only happends sometimes is very unrecognisable. And I couldn’t catch a moment when it happend. But it happends very little some times.
Grappler Script, only server because client isn't so relevant here
local grapplerRemote = script.Parent.grapplerEvent
local grapplerAttachedSound = game.SoundService.WeaponSounds.grappleConnected
function createGrapplerRope(mousePos, mouseTarget, humanoidRootPart, lenght)
local attachment0 = Instance.new("Attachment")
attachment0.Name = "grapplerBodyAttachment"
attachment0.Position = Vector3.new(0, 0, 0)
attachment0.Orientation = Vector3.new(0, 90, 0)
attachment0.Parent = humanoidRootPart
local attachment1 = Instance.new("Attachment")
attachment1.Name = "grapplerTargetAttachment"
attachment1.Position = mouseTarget.CFrame:PointToObjectSpace(mousePos.Position)
attachment1.Parent = mouseTarget
local referenceToAttachment2 = Instance.new("ObjectValue")
referenceToAttachment2.Name = "referenceToGrapplerTargetAttachment"
referenceToAttachment2.Value = attachment1
referenceToAttachment2.Parent = humanoidRootPart
local ropeConstraint = Instance.new("RopeConstraint")
ropeConstraint.Name = "grapplerRope"
ropeConstraint.Thickness = 0.2
ropeConstraint.Length = lenght
ropeConstraint.Color = BrickColor.Black()
ropeConstraint.Attachment0 = attachment0
ropeConstraint.Attachment1 = attachment1
ropeConstraint.Visible = true
ropeConstraint.Parent = humanoidRootPart
local grapplerConnectedSound = grapplerAttachedSound:Clone()
grapplerConnectedSound.Parent = humanoidRootPart
grapplerConnectedSound.Playing = true
end
function removeGrapplerRope(humanoidRootPart)
local referenceToAttachment2 = humanoidRootPart:FindFirstChild("referenceToGrapplerTargetAttachment")
local ropeConstraint = humanoidRootPart:FindFirstChild("grapplerRope")
local attachment0 = humanoidRootPart:FindFirstChild("grapplerBodyAttachment")
local attachment1 = referenceToAttachment2.Value
local grapplerConnectedSound = humanoidRootPart:FindFirstChild("grappleConnected")
attachment0:Destroy()
attachment1:Destroy()
ropeConstraint:Destroy()
referenceToAttachment2:Destroy()
grapplerConnectedSound:Destroy()
end
function addGrapplerBelt(humanoidRootPart)
local grapplerBelt = game.ReplicatedStorage.grapplerBelt:Clone()
grapplerBelt.Parent = humanoidRootPart
local weld = Instance.new("Weld")
weld.Part0 = humanoidRootPart
weld.Part1 = grapplerBelt
weld.C0 = CFrame.new(0, -0.75, 0)
weld.Parent = grapplerBelt
end
function removeGrapplerBelt(humanoidRootPart)
local grapplerBelt = humanoidRootPart:FindFirstChild("grapplerBelt")
grapplerBelt:Destroy()
end
grapplerRemote.OnServerEvent:Connect(function(player, action, mouseTarget, mousePos, lenght)
local character = player.Character or player.CharacterAdded:Wait()
local humanoidRootPart = character:WaitForChild("HumanoidRootPart")
if action == "grappleStarted" then
createGrapplerRope(mousePos, mouseTarget, humanoidRootPart, lenght)
elseif action == "grappleEnded" then
removeGrapplerRope(humanoidRootPart)
end
if action == "grapplerEquiped" then
addGrapplerBelt(humanoidRootPart)
elseif action == "grapplerUnequiped" then
removeGrapplerBelt(humanoidRootPart)
end
end)
Set Rotation Script
Here is the script that sets the rotation of the player, the parts of the script that actaully sets the rotation is the second two last lines of code:
-- Variables
local uis = game:GetService("UserInputService")
local runService = game:GetService("RunService")
local player = game.Players.LocalPlayer
local camera = workspace.CurrentCamera
local character = player.Character or player.CharacterAdded:Wait()
local humanoidRootPart = character:WaitForChild("HumanoidRootPart")
local humanoid = character:WaitForChild("Humanoid")
local lastState = false
local loadingCompleted = false
local debounce = true
-- GUI
game.StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.Backpack, false)
game.StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.PlayerList, false)
game.Workspace.Camera.FieldOfView = 90
--New Movement Sounds
humanoidRootPart:WaitForChild("Jumping").SoundId = game.SoundService.playerSounds.jumpSound.SoundId
humanoidRootPart:WaitForChild("Running").SoundId = game.SoundService.playerSounds.walkSound.SoundId
--Movement Sound Properties
humanoidRootPart:WaitForChild("Jumping").Volume = 0.5
humanoidRootPart:WaitForChild("Running").Volume = 2
humanoidRootPart:WaitForChild("Jumping").PlaybackSpeed = 1
humanoidRootPart:WaitForChild("Running").PlaybackSpeed = 1
-- Mouse Icon
player:GetMouse().Icon = "http://www.roblox.com/asset/?id=18663286339"
local function isInFirstPerson()
if character.Head.LocalTransparencyModifier == 1 then
return true
else
return false
end
end
local function updateRotation()
if humanoidRootPart then
local cameraDirection = camera.CFrame.LookVector
local newCFrame = CFrame.new(humanoidRootPart.Position, humanoidRootPart.Position + Vector3.new(cameraDirection.X, 0, cameraDirection.Z))
humanoidRootPart.CFrame = newCFrame
end
end
for i, v in pairs(character:GetChildren()) do
if v:IsA("BasePart") and v.Name ~= "Head" and v.Name ~= "Torso" then
v.LocalTransparencyModifier = v.Transparency
v.Changed:Connect(function(property)
v.LocalTransparencyModifier = v.Transparency
end)
end
end
runService.Heartbeat:Connect(function()
humanoid:SetStateEnabled(Enum.HumanoidStateType.FallingDown, false)
-- Crosshair if weapon is equiped
for _, item in pairs(character:GetChildren()) do
if item:IsA("Tool") then
if item:FindFirstChild("IsAWeapon") then
player:GetMouse().Icon = "http://www.roblox.com/asset/?id=17787998274"
debounce = false
else
if not debounce then
player:GetMouse().Icon = "http://www.roblox.com/asset/?id=18663286339"
debounce = true
end
end
else
if not debounce then
player:GetMouse().Icon = "http://www.roblox.com/asset/?id=18663286339"
debounce = true
end
end
end
-- Look in camera direction
local lookDirection = game.Workspace.CurrentCamera.CFrame.LookVector
humanoidRootPart.CFrame = CFrame.new(humanoidRootPart.Position, humanoidRootPart.Position + Vector3.new(lookDirection.X, 0, lookDirection.Z))
end)
Videos
With setting rotation
With setting rotation - Clipped with Medal.tv
Without setting rotation
Without setting rotation - Clipped with Medal.tv
Any help super appreciated!
EDIT:
I didn’t think there was anything important to show in the client script at first, but I realized I forgot to mention that I set the physics state of the humanoid there. Besides that, the client script mainly just sends the keys I press to the server, which is already handled. And yes, the state does change—I’ve checked the code and tested it. So the physics state is already being applied to the player.
I tried setting all the tools to massless, and it made a HUGE difference! The random forces are now almost completely gone. There are still some very, very small forces being applied though, but tbh, they don’t bother me to much. It would be awesome to have them fully gone though! So the issue is not resolved yet.
EDIT AGAIN:
It got solved by an amazing guy on reddit, use bodygyro or align orientation instead of just setting the CFrame on the players rotation.