Rotate Part in Tool on Vetical Axis using Weld C1

I am trying to make a furniture placement system allowing players to rotate the item on the vertical axis. When the player pickups the item, it is welded to the tool Handle, then I want them to be able to rotate the held item.

The part is attached to the tool using the following:

-- Server Script - WELD Item to CHARACTER Tool HANDLE	
	local PosX = cloneItem.Size.X / 2
	local PosY = cloneItem.Size.Y / 2
	local PosZ = cloneItem.Size.Z / 2
	cloneItem.CFrame = character.PlayerTool.Handle.CFrame
	cloneItem.Position = character.PlayerTool.Handle.Position + Vector3.new(-PosX, PosY, -PosZ)
	local newWeld = Instance.new("Weld")
	newWeld.Part0 = character.PlayerTool.Handle
	newWeld.Part1 = cloneItem
	newWeld.Parent = character.PlayerTool.Handle
	newWeld.C0 = character.RightHand.RightGripAttachment.CFrame
	newWeld.C1 = cloneItem.Attachment.CFrame:ToWorldSpace(CFrame.new(PosX, -PosY, -PosZ))

The above works fine in positioning the picked up item relative to the character. When trying to rotate on the vertical axis, I have tried using various methods including ToWorldSpace(CFrame.Angles) and ToObjectSpace (CFrame.Angles) none of which seem to rotate the Item relative to the character.

local function rotateItem()
	local playerTool = character:WaitForChild("PlayerTool")
	if not playerTool then return end
	local heldItem = playerTool:WaitForChild("Handle"):WaitForChild("Item")
	if not heldItem then return end
-- A list of things tried so far... none of which seem to achieve what I need
	heldItem.CFrame = heldItem.CFrame:ToWorldSpace(CFrame.Angles (0, math.rad(90), 0))	
	heldItem.CFrame = heldItem.CFrame * CFrame.Angles(0,math.rad(90),0)
	heldItem.Parent.Weld.C0 = heldItem.CFrame:ToObjectSpace(heldItem.Parent.Weld.C0 * CFrame.Angles(0, math.rad(90), 0))
	heldItem.Parent.Weld.C1 = heldItem.Attachment.CFrame:ToWorldSpace(CFrame.Angles(0, 0, math.rad(90))) CFrame:ToObjectSpace
	heldItem.Parent.Weld.C1 = heldItem.Attachment.CFrame:ToObjectSpace(heldItem.Attachment.CFrame * CFrame.Angles(0, 0, math.rad(90)))
	heldItem.Parent.Weld.C1 = heldItem.Attachment.CFrame:ToWorldSpace (CFrame.Angles(0, 0, math.rad(90)))
end

Can someone please explain where I am going wrong. It looked like a simple thing to achieve, but is now frustrating me.

ToWorldSpace and ToObjectSpace are both functions of the CFrame class that allow you to convert between the coordinate spaces of two parts. ToWorldSpace converts a CFrame from the coordinate space of one part to the coordinate space of the parent part, while ToObjectSpace does the opposite.

In your code, you are trying to use these functions to rotate the item around the vertical axis, but they are not designed to perform this task. Instead, you can use the CFrame.Angles method to create a new CFrame that represents a rotation around the vertical axis, and then apply this rotation to the item’s CFrame.

Here is an example of how you can use CFrame.Angles to rotate the item around the vertical axis:

local rotationAmount = math.rad(90)  -- Rotate by 90 degrees
local rotationCFrame = CFrame.Angles(0, 0, rotationAmount)  -- Create a CFrame representing the rotation
heldItem.CFrame = heldItem.CFrame * rotationCFrame  -- Apply the rotation to the item's CFrame

This should rotate the item around the vertical axis by the specified amount. You can adjust the rotationAmount variable to control the amount of rotation.

I had actually tried just rotating the welded part. This does achieve rotation of the Item, but the character is also rotated relative to the part, as the Weld remains active fixing the tool Handle to both character and the welded Item. This led me to numerous DevForum posts that advised rotating the Weld C0 or C1, rather than the item itself.

I have just been trying the following to disable the Weld before rotating the part:

	playerTool.Handle.Weld.Enabled = false
	heldItem.Anchored = true
	heldItem.CFrame = heldItem.CFrame * CFrame.Angles(0, math.rad(90), 0)
	playerTool.Handle.Weld.Enabled = true

This does the same thing, rotates the part, but the character seemingly orbits the part as it is rotated.

Previous DevForum posts recommend differing solutions, both of which I have tried but don’t seem to resolve the problem of the simultaneous character rotation:

It was these posts that sent me down the ToWorldSpace and ToObjectSpace route.

If you want to rotate the item around the vertical axis while keeping the character stationary, you can try applying the rotation to the weld’s C0 and C1 properties instead of the item’s CFrame. This should allow the item to rotate while keeping the character stationary, as the weld will remain fixed to the character and the item will rotate relative to the weld.

Here is an example of how you can do this:

local rotationAmount = math.rad(90)  -- Rotate by 90 degrees
local rotationCFrame = CFrame.Angles(0, 0, rotationAmount)  -- Create a CFrame representing the rotation

-- Disable the weld and make the item anchored so it can be rotated
playerTool.Handle.Weld.Enabled = false
heldItem.Anchored = true

-- Apply the rotation to the weld's C0 and C1 properties
playerTool.Handle.Weld.C0 = playerTool.Handle.Weld.C0 * rotationCFrame
playerTool.Handle.Weld.C1 = playerTool.Handle.Weld.C1 * rotationCFrame

-- Re-enable the weld and unanchor the item
playerTool.Handle.Weld.Enabled = true
heldItem.Anchored = false

This should allow you to rotate the item around the vertical axis while keeping the character stationary. You can adjust the rotationAmount variable to control the amount of rotation.

Thanks for your input on this. I had a play about with your suggestion and the held item did finally rotate, but only if C0 or C1 was updated, but not both. I think when both were updated they cancelled each other out.

When testing your suggestion, I tried just updating the CFrame of the held Item once it was Anchored and the Weld was Disabled.

	playerTool.Handle.Weld.Enabled = false
	heldItem.Anchored = true
	heldItem.CFrame = heldItem.CFrame * CFrame.Angles(0,math.rad(90),0)
	task.wait(1)
	playerTool.Handle.Weld.Enabled = true
	heldItem.Anchored = false

Now the part just rotates around it’s centre and no weirdness occurs, but only for as long as the Wait and the part is Anchored. Once the part is unanchored, the Weld kicks in and returns the part to it’s original position.

It sounds like you have found a solution that works for your use case. Updating the CFrame of the held item while the weld is disabled and the item is anchored allows you to rotate the item around its own center without affecting the character.

If you want the item to stay rotated after the weld is re-enabled and the item is unanchored, you can try updating the weld’s C0 and C1 properties with the new rotation, as I suggested earlier. This should allow the item to stay rotated even after the weld is re-enabled and the item is unanchored.

Here is an example of how you can do this.

local rotationAmount = math.rad(90)  -- Rotate by 90 degrees
local rotationCFrame = CFrame.Angles(0, 0, rotationAmount)  -- Create a CFrame representing the rotation

-- Disable the weld and make the item anchored so it can be rotated
playerTool.Handle.Weld.Enabled = false
heldItem.Anchored = true

-- Rotate the item around its own center
heldItem.CFrame = heldItem.CFrame * rotationCFrame

-- Update the weld's C0 and C1 properties with the new rotation
playerTool.Handle.Weld.C0 = playerTool.Handle.Weld.C0 * rotationCFrame
playerTool.Handle.Weld.C1 = playerTool.Handle.Weld.C1 * rotationCFrame

-- Re-enable the weld and unanchor the item
playerTool.Handle.Weld.Enabled = true
heldItem.Anchored = false

This should allow the item to stay rotated even after the weld is re-enabled and the item is unanchored. You can adjust the rotationAmount variable to control the amount of rotation.

I tried that and also destroying then recreating the Weld with the original parameters.

Updating C0 & C1 still resulted in the item snapping back to it’s original position once it was unachored, almost as if the Weld updates made no difference.

Destroying and recreating the Weld resulted in the character snap orbiting the item again.

It’s getting late, so I’ll look at it again tomorrow with a clearer mind. Thanks for you help so far.

It sounds like you are still experiencing some issues with rotating the item around the vertical axis. Here are a few things you can try:

  • Make sure that you are updating the weld’s C0 and C1 properties with the same rotation amount. If you update one but not the other, the weld may not behave as expected.
  • Check that the item’s Attachment property is set correctly. This property determines the point on the item that the weld is attached to. If the Attachment is not set correctly, the item may not behave as expected when the weld is enabled or disabled.
  • Make sure that the item is not being affected by any other forces or constraints that could cause it to return to its original position. For example, if the item has a BodyForce applied to it, it may return to its original position when the weld is re-enabled.
  • Consider using a different method for rotating the item, such as using a Motor6D constraint. This type of constraint allows you to rotate an object around a specific axis, which may be more suitable for your use case.

I hope these suggestions are helpful. Let me know if you have any questions or if there is anything else I can do to help.

I am not great with Welds and CFrames, so it looks like I have made a fundamental mistakes in both the initial positioning of the part relative to the character and also how I have done the Welds.

I have gone back to the drawing board and am now rewriting the entire code around the pickup, drop and rotate functions.

I’ve finally solved it after rebuilding the functions. I have simplified the Item to Character weld by welding direct to the HRP, rather than the held Tool and by using the Items absolute CFrame rather than referencing an Attachment.

-- Server funciton to Weld the Item to the characters HumanoidRootPart
	local cloneItem = storageFolder:FindFirstChild(item.Name):Clone()
	
-- WELD Cloned Item to CHARACTER Tool HANDLE	
	local PosX = cloneItem.Size.X / 2
	local PosY = cloneItem.Size.Y / 4
	local PosZ = cloneItem.Size.Z / 2
	
	local newWeld = Instance.new("Weld")
	newWeld.Part0 = HRP 
	newWeld.Part1 = cloneItem
	newWeld.Parent = cloneItem
	newWeld.C0 = HRP.CFrame
	newWeld.C1 = HRP.CFrame + Vector3.new(0, -PosY, PosZ + 1.5)

I was concerned that the order of priority was messing with whether Part0 or Part1 was the primary part in the Weld. By using the HRP in Part0 this argument becomes null and void as the HRP is the Primary{art for the entire character model and so becomes primary part for the welding.

The rotation script then becomes very simple, no anchoring, no disabling of welds or recreating them:

	local additionalRotation = heldItem.Weld.C1:Inverse()*CFrame.Angles(0, math.rad(-90), 0)*heldItem.Weld.C1
	heldItem.Weld.C0 *= additionalRotation

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.