I am making a 2D “Platformer game” which requires the arm to follow the cursor.
Here’s my code:
local rs = game:GetService("ReplicatedStorage")
local plrs = game:GetService("Players")
local run = game:GetService("RunService")
local player = plrs.LocalPlayer
local mouse = player:GetMouse()
local function setupCharacter(character)
local torso = character:WaitForChild("Torso")
local rightArm = character:WaitForChild("Right Arm")
local event = rs:WaitForChild("events"):WaitForChild("LightsaberMove")
local armWeld = Instance.new("Weld")
armWeld.Part0 = torso
armWeld.Part1 = rightArm
armWeld.Parent = rightArm
local armOffset = torso.CFrame:Inverse() * rightArm.CFrame
local rotCFrame
local armPos
run.RenderStepped:Connect(function()
if not torso or not rightArm then return end
local torsoPos = torso.Position
local mouseHit = mouse.Hit.Position
-- keep the x position of the mouse aligned with the torso
mouseHit = Vector3.new(torsoPos.X, mouseHit.Y, mouseHit.Z)
-- create a cframe that makes the torso look at the mouse
local lookAtCFrame = CFrame.lookAt(torsoPos, mouseHit)
rotCFrame = CFrame.new(torsoPos) * CFrame.Angles(lookAtCFrame:ToEulerAnglesXYZ())
-- calculate the arm's position relative to the torso
armPos = rightArm.CFrame.Position - torso.CFrame.Position
-- update the weld with the new rotation
armWeld.C0 = armOffset * torso.CFrame:toObjectSpace(rotCFrame)
end)
local function sendData()
if rotCFrame and armPos then
event:FireServer(rotCFrame, armPos, torso.CFrame)
end
end
-- repeat
while true do
sendData()
wait(0.05)
end
end
-- setup character when the player spawns
setupCharacter(player.Character or player.CharacterAdded:Wait())
-- handle character respawn and setup
player.CharacterAdded:Connect(function(newCharacter)
newCharacter:WaitForChild("Torso")
newCharacter:WaitForChild("Right Arm")
setupCharacter(newCharacter)
end)
The arm is not in the original RightArm position, instead it is in the torso of the player.
How can I fix this?
Below is an older version of the script, which had the correct arm placement, but had a problem with respawning, which is fixed in the script on the original post.
local rs = game:GetService("ReplicatedStorage")
local plrs = game:GetService("Players")
local run = game:GetService("RunService")
local player = plrs.LocalPlayer
local char = player.Character or player.CharacterAdded:Wait()
local mouse = player:GetMouse()
local torso = char:WaitForChild("Torso")
local rightArm = char:WaitForChild("Right Arm")
local event = rs:WaitForChild("events"):WaitForChild("LightsaberMove")
local armOffset = torso.CFrame:Inverse() * rightArm.CFrame
-- weld to attach right arm to torso
local armWeld = Instance.new("Weld")
armWeld.Part0 = torso
armWeld.Part1 = rightArm
armWeld.Parent = rightArm
local rotCFrame -- store rotation data
local armPos -- store arm position relative to torso
-- update arm's position and rotation every frame
run.RenderStepped:Connect(function()
local torsoPos = torso.Position
local mouseHit = mouse.Hit.Position
-- lock movement to y-z plane
mouseHit = Vector3.new(torsoPos.X, mouseHit.Y, mouseHit.Z)
-- calculate direction to mouse
local lookAtCFrame = CFrame.lookAt(torsoPos, mouseHit)
rotCFrame = CFrame.new(torsoPos) * CFrame.Angles(lookAtCFrame:ToEulerAnglesXYZ())
-- store arm's relative position
armPos = rightArm.CFrame.Position - torso.CFrame.Position
-- update weld with new rotation
armWeld.C0 = armOffset * torso.CFrame:toObjectSpace(rotCFrame)
end)
-- send rotation and position data to server
local function sendData()
if rotCFrame and armPos then
event:FireServer(rotCFrame, armPos, torso.CFrame)
end
end
-- run continuously
while true do
sendData()
wait(0.05)
end