So I've got the part (which is an arrow) in the player's character, I'm just having trouble with making it point at the object in the workspace, Below I have attached the code I'm using, I figured the last piece of code would make the arrow point at a part called QUESTOBJECTIVEPOS but it just makes the arrow go really far away from the character.
wait(0.1) Player = game.Players.LocalPlayer character = Player.Character arrow = game.ReplicatedStorage.Arrow:Clone() arrow.CFrame = character.HumanoidRootPart.CFrame * CFrame.new(0, 0, -5) * CFrame.Angles(math.rad(0), math.rad(0), math.rad(90)) local Joint = Instance.new("Weld") Joint.Part0 = arrow Joint.C0 = arrow.CFrame:inverse() Joint.Part1 = character.HumanoidRootPart Joint.C1 = character.HumanoidRootPart.CFrame:inverse() Joint.Parent = character.HumanoidRootPart arrow.Parent = character game:GetService("RunService").RenderStepped:connect(function() arrow.LocalTransparencyModifier = 0 end) i = 1, math.huge while wait() do i = i + 1 Joint.C0 = CFrame.Angles(0, 0, math.rad(i)) * Joint.C1 * CFrame.new(game.Workspace.QUESTOBJECTIVEPOS.Position) end
Here's your script. I rewrote it a bit to make it easier to read:
local Player = game.Players.LocalPlayer local Character = Player.Character local Arrow = game.ReplicatedStorage.Arrow:Clone() local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart") local Objective = workspace:WaitForChild("QUESTOBJECTIVEPOS") local Joint = Instance.new("Weld") Joint.Part0 = HumanoidRootPart Joint.Part1 = Arrow Joint.C0 = CFrame.new() --Joint.C1 = ??? -- We'll adjust this in the loop. Joint.Parent = HumanoidRootPart Arrow.Parent = Character game:GetService("RunService").RenderStepped:Connect(function() --Joint.C1 = ??? -- Adjust Weld.C1 here. end)
We're looking to adjust Joint.C1
such that it would make Arrow
point to Objective
. To do that, we need to look at how welds work at a lower level:
Part1.CFrame * C1 == Part0.CFrame * C0
Substitution Part1
for Arrow
, Part0
for HumanoidRootPart
, and C1
and C0
we get:
Arrow.CFrame * Joint.C1 == HumanoidRootPart.CFrame * Joint.C0
We know what Arrow.CFrame
should be (five studs above HumanoidRootPart
, looking at Objective
), and we know what HumanoidRootPart.CFrame
is at any given time. Furthermore, since we set Joint.C0
to CFrame.new()
, anything we multiply to it will remain the same (CFrame.new()
is the identity matrix. Just like 1
in algebra, anything multiplied to it will remain the same), so we can just choose to omit it.
CFrame.new(HumanoidRootPart.Position + Vector3.new(0, 5, 0), Objective.Position) * Joint.C1 = HumanoidRootPart.CFrame
(From here on out, let's call CFrame.new(HumanoidRootPart.Position + Vector3.new(0, 5, 0)
"offset
" to save space)
local offset = CFrame.new(HumanoidRootPart.Position + Vector3.new(0, 5, 0), Objective.Position)
offset * Joint.C1 = HumanoidRootPart.CFrame
We want to isolate Joint.C1 such that it is alone on its side of the equation. To do that, we can multiply the left side of each side by offset:inverse()
(note the :inverse()
part. A matrix (CFrame) multiplied by its inverse will result in an identity matrix (CFrame.new()), which we could then cancel out.
This equation:
local offset = CFrame.new(HumanoidRootPart.Position + Vector3.new(0, 5, 0), Objective.Position)
offset:inverse() * offset * Joint.C1 = offset:inverse() * HumanoidRootPart.CFrame
simplifies to
local offset = CFrame.new(HumanoidRootPart.Position + Vector3.new(0, 5, 0), Objective.Position)
Joint.C1 = offset:inverse() * HumanoidRootPart.CFrame
Viola, we've solved for Joint.C1
.
Here's the final script:
local Player = game.Players.LocalPlayer local Character = Player.Character local Arrow = game.ReplicatedStorage.Arrow:Clone() local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart") local Objective = workspace:WaitForChild("QUESTOBJECTIVEPOS") local Joint = Instance.new("Weld") Joint.Part0 = HumanoidRootPart Joint.Part1 = Arrow Joint.C0 = CFrame.new() Joint.Parent = HumanoidRootPart Arrow.Parent = Character game:GetService("RunService").RenderStepped:Connect(function() local offset = CFrame.new(HumanoidRootPart.Position + Vector3.new(0, 5, 0), Objective.Position) Joint.C1 = offset:inverse() * HumanoidRootPart.CFrame end)
(I'm going to be very honest, since you're changing the CFrame of the arrow every frame anyway, you're better of just not using welds at all and setting the CFrame of the arrow directly.)