So I am trying to make player’s arm to point at mouse position, but my script doesn’t really work.
Video with the issue: robloxapp-20220812-1158370.wmv (1.2 MB)
For some reason it moves with whole player and even the player is not really looking at mouse’s position and I have no idea why. If anyone can explain why is it happeing and/or suggest way to fix it would be great.
Script I am surrently using for my hand:
repeat wait(0.5) until game:IsLoaded()
local player = game.Players.LocalPlayer
local char = player.Character or game.Players.LocalPlayer.CharacterAdded:Wait()
local RightShoulder = char:WaitForChild("RightUpperArm")
local wpEquipped = false
script.Parent.Equipped:Connect(function()
wpEquipped = true
end)
script.Parent.Unequipped:Connect(function()
wpEquipped = false
end)
local function lookDirection()
if wpEquipped == true then
RightShoulder.CFrame = CFrame.lookAt(RightShoulder.Position, player:GetMouse().Hit.Position)
end
end
game["Run Service"].Heartbeat:Connect(lookDirection)
You can’t just use CFrame in this way to change the position or rotation of the arm. This is because the arm is attached via a joint, and attempting to modify CFrame directly will almost always cause problems like this, and therefore you should directly modify the C0/C1 CFrame of the joint which will require some mathematics like inverse kinematics (IK) to find out what value will rotate and/or move the joint to desired position.
“Inverse kinematics is the use of kinematic equations to determine the motion of a robot to reach a desired position. For example, to perform automated bin picking, a robotic arm used in a manufacturing line needs precise motion from an initial position to a desired position between bins and manufacturing machines.” - What Is Inverse Kinematics? - MATLAB & Simulink
Here are some resources to get you started with IK:
Isn’t there a simpler way to reach my goal? Like don’t get me wrong everything you just sent is amazing and I read it all, but it really seems rather complicated and advanced unlike what I am trying to do. This “inverse kinematics” are for advanced hand movement with multiple parts working together, but I just need the whole arm to rotate around the shoulder axis
Since what you sent is made for R6 models, I have rewritten it to be R15 instead, but it really seems it was not made to support R15 because the character doesnt really look the way I want: robloxapp-20220812-1333478.wmv (599.1 KB)
I dont really understand the math in this script so maybe I overlooked something important that makes the character look somewhere else. If you care enough, you can read my “changed” script:
repeat wait(0.5) until game:IsLoaded()
local replicated = game:GetService("ReplicatedStorage")
local player = game.Players.LocalPlayer
local char = player.Character or game.Players.LocalPlayer.CharacterAdded:Wait()
local origRightS = char:WaitForChild("RightUpperArm"):WaitForChild("RightShoulder").C0
local origLeftS = char:WaitForChild("LeftUpperArm"):WaitForChild("LeftShoulder").C0
local origNeck = char:WaitForChild("Head"):WaitForChild("Neck").C0
local wpEquipped = false
local m = player:GetMouse()
script.Parent.Equipped:Connect(function()
wpEquipped = true
end)
script.Parent.Unequipped:Connect(function()
wpEquipped = false
end)
local function lookDirection()
if wpEquipped == true then
if char.RightUpperArm:FindFirstChild("RightShoulder") then
char.RightUpperArm["RightShoulder"].C0 = char.RightUpperArm["RightShoulder"].C0:Lerp(CFrame.new(1, .65, 0) * CFrame.Angles(-math.asin((m.Origin.p - m.Hit.p).unit.y), 1.55, 0, 0) , 0.1)
end
if char.LeftUpperArm:FindFirstChild("LeftShoulder") then
char.LeftUpperArm["LeftShoulder"].C0 = char.LeftUpperArm["LeftShoulder"].C0:Lerp(CFrame.new(-1, .65, 0) * CFrame.Angles(-math.asin((m.Origin.p - m.Hit.p).unit.y), -1.55, 0, 0) , 0.1)
end
if char.Head:FindFirstChild("Neck") then
char.Head["Neck"].C0 = char.Head["Neck"].C0:Lerp(CFrame.new(0, 1, 0) * CFrame.Angles(-math.asin((m.Origin.p - m.Hit.p).unit.y) + 1.55, 3.15, 0), 0.2)
end
else
if char.RightUpperArm:FindFirstChild("RightShoulder") then
char.RightUpperArm["RightShoulder"].C0 = char.RightUpperArm["RightShoulder"].C0:lerp(origRightS, 0.1)
end
if char.LeftUpperArm:FindFirstChild("LeftShoulder") then
char.LeftUpperArm["LeftShoulder"].C0 = char.LeftUpperArm["LeftShoulder"].C0:lerp(origLeftS, 0.1)
end
if char.Head:FindFirstChild("Neck") then
char.Head["Neck"].C0 = char.Head["Neck"].C0:lerp(origNeck, 0.1)
end
end
end
replicated.RemoteEvent.Look.OnClientEvent:Connect(function(PlrAgain, neckCFrame, RsCFrame, LsCFrame)
local Neck = PlrAgain.Character.Head:FindFirstChild("Neck", true)
local Rs = PlrAgain.Character.RightUpperArm:FindFirstChild("RightShoulder", true)
local Ls = PlrAgain.Character.LeftUpperArm:FindFirstChild("LeftShoulder", true)
if Neck then
Neck.C0 = neckCFrame
end
if Rs then
Rs.C0 = RsCFrame
end
if Ls then
Ls.C0 = LsCFrame
end
end)
game["Run Service"].RenderStepped:Connect(lookDirection)
while wait(0.5) do
replicated.RemoteEvent.Look:FireServer(char.Head["Neck"].C0, char.RightUpperArm["RightShoulder"].C0, char.LeftUpperArm["LeftShoulder"].C0)
end
Yeah, I am unsure. But using my IKB resource as mentioned earlier, it does the job without a problem.
local Players = game:GetService("Players")
local Player = Players.LocalPlayer
local R15ALIK = require(script.IKB.R15.AL)
local Character = Player.Character or Player.CharacterAdded:Wait()
local UpperTorso = Character:WaitForChild("UpperTorso")
local Mouse = Player:GetMouse()
local RightArmIK = R15ALIK.new(Character, "Right", "Arm")
Mouse.Move:Connect(function()
RightArmIK:Solve(Mouse.Hit.Position)
end)
-- Make sure to use RightArmIK:Destroy() once you're done using :Solve() function
This works perfectly! One last thing, is there a way to limit player from pointing his arm to certain angles? Or do I have to manullay check if mouse position is too much behind players torso and manually stop the arm movement?
Hold on another thing popped up, the arm now returns to its previous position, but when I then select the tool again, its broken again: robloxapp-20220812-1456514.wmv (966.3 KB)
oh I forgot Anyways it works now with no problems, I will try to work out those limits for hand rotation, but the most important thing works now thanks to you. I really appriciate your help, you are a great person. Have a great day
You can try playing with some of the Motor6D properties:
local obj = put your IKInstance here
obj._UpperJoint.Transform = CFrame.identity
obj._LowerJoint.Transform = CFrame.identity
obj._UpperJoint.C0 = Vector3.zero
obj._LowerJoint.C0 = Vector3.zero