I have a compass tool that when equipped Instances a glowing arrow on the player. I want this arrow to point to a set position in the game where there is a hidden treasure chest, and rotate around the player as they move to hint at where that treasure is.
The issue I’m having is that I can’t figure out a way to smoothly rotate the arrow to the correct direction without it bugging out the player, like in these videos. I want it to just smoothly spin to the correct position and then wait there without moving or rotating the actual player. The setup for the arrow is the arrow piece is hinged to an anchor part which is welded to the HRP of the player. This setup lets the arrow spin freely around the y-axis, which is what I want, but when I try to change the rotation in code it’s weird.
Here is the code I’m using, it’s on a localscript in the tool:
-- Services
local RS = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
-- References
local tool = script.Parent
local player = Players.LocalPlayer
local skullChest = workspace.SkullChest
local CompassArrow = RS.Objects.CompassArrow
local arrowClone
-- Treasure found flip
local foundTreasure = false
local equipped = false
-- Create glowing arrow
tool.Equipped:Connect(function()
if foundTreasure == false then
equipped = true
arrowClone = CompassArrow:Clone()
arrowClone.Parent = player.Character
arrowClone.Anchor.Position = player.Character.HumanoidRootPart.Position
arrowClone.GlowingArrow.Position = arrowClone.Anchor.Position
local weld = Instance.new("WeldConstraint", arrowClone)
weld.Part0 = player.Character.HumanoidRootPart
weld.Part1 = arrowClone.Anchor
print("created arrow")
end
end)
-- Remove glowing arrow
tool.Unequipped:Connect(function()
if foundTreasure == false then
equipped = false
arrowClone:Destroy()
arrowClone = nil
end
end)
RunService.RenderStepped:Connect(function()
if equipped then
local newAngle = Vector3.new(0, math.deg(math.atan((skullChest.Wood.Position.Z - arrowClone.GlowingArrow.Position.Z) / (skullChest.Wood.Position.X - arrowClone.GlowingArrow.Position.X))), 0)
print(newAngle)
arrowClone.GlowingArrow.Rotation = newAngle
end
end)
Any help would be very appreciated, I’m pretty new to roblox scripting!
ArrowClone already has CanCollide set to false, sorry I should have specified that. I just turned it on in one video to show how it rotated around the hinge.
local Direction = (arrowClone.Position - skullChest.Wood.Position).Unit
arrowClone.CFrame = CFrame.lookAt(arrowClone.Anchor.Position, arrowClone.Anchor.Position + Direction)
—if this points the weong way, switch CFrame.lookAt to CFrame.lookAt(arrowClone.Anchor.Position + Vector3.new(Direction.X,0,Direction.Y), arrowClone.Anchor.Position)
Not sure if something like this is what you’re looking for but this should work well and give a smooth arrow that points towards the skullChest when equipping the Compass, just edit the code to your liking.
local skullChest = game.Workspace.SkullChest
local player = game:GetService("Players").LocalPlayer
local char = player.Character or player.CharacterAdded:Wait()
local tool = script.Parent
local mainPart = CompassArrow.PrimaryPart
local renderConnection
local foundTreasure = false
local equipped = false
CompassArrow.Parent = game.Workspace
-- Create glowing arrow
tool.Equipped:Connect(function()
if foundTreasure == false then
equipped = true
renderConnection = game:GetService("RunService").RenderStepped:Connect(function()
mainPart.CFrame = CFrame.lookAt(char.HumanoidRootPart.Position, game.Workspace.SkullChest.PrimaryPart.Position)
end)
end
end)
-- Remove glowing arrow
tool.Unequipped:Connect(function()
if foundTreasure == false then
equipped = false
renderConnection:Disconnect()
CompassArrow:Destroy()
end
end)
That helped thanks! This is the final code I got, I ended up using a BallSocketConstraint on the CompassArrow model, this let it rotate freely and orient towards the chest without trying to drag or rotate the player. Much better than using a HingeConstraint:
-- Services
local RS = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
-- References
local tool = script.Parent
local player = Players.LocalPlayer
local char = player.Character or player.CharacterAdded:Wait()
local skullChest = workspace.SkullChest
local CompassArrow = RS.Objects.CompassArrow
local arrowClone
local mainPart
local renderConnection
-- Treasure found flip
local foundTreasure = false
local equipped = false
-- Create glowing arrow
tool.Equipped:Connect(function()
if foundTreasure == false then
equipped = true
arrowClone = CompassArrow:Clone()
arrowClone.Parent = char
arrowClone.Anchor.Position = char.HumanoidRootPart.Position
arrowClone.GlowingArrow.Position = arrowClone.Anchor.Position
local constraint = Instance.new("BallSocketConstraint", arrowClone)
constraint.Attachment0 = char.HumanoidRootPart.RootAttachment
constraint.Attachment1 = arrowClone.Anchor.Attachment
mainPart = arrowClone.Anchor
renderConnection = RunService.RenderStepped:Connect(function()
mainPart.CFrame = CFrame.lookAt(mainPart.Position, skullChest.PrimaryPart.Position)
end)
print("created arrow")
end
end)
-- Remove glowing arrow
tool.Unequipped:Connect(function()
if foundTreasure == false then
equipped = false
arrowClone:Destroy()
arrowClone = nil
end
end)