Force unanchored part in air to be in certain orientation regardless

I’m trying to force an unanchored to be facing the player camera (Y Axis -90) but it wouldn’t work due to it being unanchored and in midair.

coroutine.wrap(function()
        --heldtarget is the part
	while true do
		if module.IsDragging and baseCamera ~= nil then
			local subjectPosition = baseCamera:GetSubjectPosition()
			if subjectPosition == nil then return end
			local location = userInputService:GetMouseLocation()
			local viewportPointRay = workspace.CurrentCamera:ViewportPointToRay(location.X, location.Y)
			local rayOrigin = viewportPointRay.Origin
			local mousePosition = CFrame.new(rayOrigin, rayOrigin + viewportPointRay.Direction):ToWorldSpace(CFrame.new(0, 0, -1000)).Position
			local targetPosition = CFrame.new(subjectPosition, mousePosition):ToWorldSpace(CFrame.new(0, 0, -DRAG_DISTANCE).Position
			holdTarget.Position = targetPosition
		end
		runService.Heartbeat:Wait()
	end
1 Like

From my idea, there are probably 2 ways to do this, can be more, can be less. But here is what I thought.

  1. Anchor it temporarily, finish what you want, and unanchor it.
  2. Use attachment, and a invisible part that acts like a primary part for that unanchored part : Then you can use weldConstraint to weld that invisible part to an another part midair at the desired position.

But what I’m doing right now is a simple drag part with mouse.
Reference:

From: @GibusWielder

Ohhh, so you are using Dragger? Have you tried using AxisRotate()?

? What is that? That’s not a function in CFrame, Part or Vector. Also I’m using dragger from an open-source game.

Ohh, ok. So please do not consider my earlier post. Have you tried rotating the part immediately after the first few seconds the object is being held?

Yes but doing that makes the part undraggable.

What is your current methodology for rotating the part?

heldTarget.Orientation = Vector.new(0,-90,0)

Can you try chaning CFrame?

heldTarget.CFrame = CFrame.new(Vector3.new(heldTarget.Position), player.Character:FindFirstChild("HumanoidRootPart).Position)

image
It just flings the part to 0,0,0

Looks like a job for AlignOrientation, if you do not want to anchor the part. I also took the liberty of connecting Your code to hearbeat, rather that using an infinite loop.

local riggedPart
local Attachment = Instance.new('Attachment')
Attachment.Orientation = Vector3.new(0,180,0) -- facing camera
local AlignOrientation = Instance.new('AlignOrientation')
AlignOrientation.Mode = Enum.OrientationAlignmentMode.OneAttachment
AlignOrientation.RigidityEnabled = true
AlignOrientation.Attachment0 = Attachment

runService.Heartbeat:Connect(function()

	if module.IsDragging and baseCamera ~= nil then
	
			local subjectPosition = baseCamera:GetSubjectPosition()
			if subjectPosition == nil then return end
			local location = userInputService:GetMouseLocation()
			local viewportPointRay = workspace.CurrentCamera:ViewportPointToRay(location.X, location.Y)
			local rayOrigin = viewportPointRay.Origin
			local mousePosition = CFrame.new(rayOrigin, rayOrigin + viewportPointRay.Direction):ToWorldSpace(CFrame.new(0, 0, -1000)).Position
			local targetPosition = CFrame.new(subjectPosition, mousePosition):ToWorldSpace(CFrame.new(0, 0, -DRAG_DISTANCE)).Position
			holdTarget.Position = targetPosition
	
--check if this is the same part, and if not update. You may also want to disable AlignOrientation once you drop the part.
			if riggedPart ~= holdTarget then
				riggedPart = holdTarget
				Attachment.Parent = riggedPart
				AlignOrientation.Parent = riggedPart
			end
			AlignOrientation.CFrame = workspace.CurrentCamera.CFrame

 	end

end)

Good luck.

EDIT: You may also want to use AlignPosition more realistic physics obeying dragging.

This sadly does not work and it’s just the same effect, part still moves around mid-air when being dragged.

My bad, AlignOrientation CFrame should not be that of the camera now that I think of it.
The proper way is this (no need to adjust the attachment by 180 degree anymore):

	AlignOrientation.CFrame = CFrame.lookAt(riggedPart.Position,Camera.CFrame.Position)

I have tested it along with AlignPosition to make sure it works this time. Here is the full code, you may find it useful:

local Attachment = Instance.new('Attachment')

local AlignOrientation = Instance.new('AlignOrientation')
AlignOrientation.Mode = Enum.OrientationAlignmentMode.OneAttachment
AlignOrientation.RigidityEnabled = true
AlignOrientation.Attachment0 = Attachment

local AlignPosition = Instance.new('AlignPosition')
AlignPosition.Mode = Enum.PositionAlignmentMode.OneAttachment
AlignPosition.RigidityEnabled = true
AlignPosition.Attachment0 = Attachment

local UIS = game:GetService('UserInputService')
local RS = game:GetService('RunService')
local Camera = workspace.CurrentCamera

local RSConnection
local riggedPart
local distance
local RAY_PARAM = RaycastParams.new()
local MAX_DISTANCE = 1000

local function OnHeartBeat()

	local mousePos = UIS:GetMouseLocation()

	local ray = Camera:ScreenPointToRay(mousePos.X, mousePos.Y - 36)

	AlignPosition.Position = ray.Origin + ray.Direction * distance
	AlignOrientation.CFrame = CFrame.lookAt(riggedPart.Position,Camera.CFrame.Position)

end

UIS.InputBegan:Connect(function(input, gpe)
	
	if gpe or riggedPart then return end
	
	if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
		
		local mousePos = UIS:GetMouseLocation()
		local ray = Camera:ScreenPointToRay(mousePos.X, mousePos.Y - 36)
		local rayResult = workspace:Raycast(ray.Origin,ray.Direction * MAX_DISTANCE, RAY_PARAM)
		
		if rayResult and rayResult.Instance:IsA('BasePart') then
			
			riggedPart = rayResult.Instance
			AlignPosition.Parent = riggedPart
			AlignOrientation.Parent = riggedPart
			Attachment.Parent = riggedPart
			distance = (rayResult.Position - ray.Origin).Magnitude
			
			RSConnection = RS.Heartbeat:Connect(OnHeartBeat)
			
		end
		
	end
	
end)

UIS.InputEnded:Connect(function(input,gpe)
	
	if gpe or not riggedPart then return end
	
	if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
		
		RSConnection:Disconnect()
		
		AlignPosition.Parent = script
		AlignOrientation.Parent = script
		riggedPart = nil
		

	end
	
end)

Have a nice scripting session.

EDIT:
Now that I read Your post again, I am no longer certain that you want the part to be facing the camera all the time?

If you want to have the part in certain constant orientation during the drag, simply put target orientation CFrame into the AlignOrientation only once during the InputStarted event, and skip updating it on heartbeat.

			riggedPart = rayResult.Instance
			AlignPosition.Parent = riggedPart
			AlignOrientation.Parent = riggedPart
			AlignOrientation.CFrame = CFrame.lookAt(riggedPart.Position,Camera.CFrame.Position) * CFrame.Angles(0,math.pi/2,0) -- just an example
			Attachment.Parent = riggedPart
			distance = (rayResult.Position - ray.Origin).Magnitude

--on heartbeat remove this line
--	AlignOrientation.CFrame = CFrame.lookAt(riggedPart.Position,Camera.CFrame.Position)

or to preserve original orientation:

AlignOrientation.CFrame = riggedPart.CFrame

This works but I had to make some adjustments because i was able to make myself fly when viewing in first person.

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