My actual goal here is to make a manual stirring process. I’ve spent like 5 hours trying to find a helpful post in this forum and eventually ended up giving the built in AI a try with this one (It was painful) and this was the best result I could get:
Having the cursor too close to the primary part ruins the immersion
The primary part locks onto the cursor whenever it is pressed, I want it to spin along with it rather than snapping onto it
Fixing the jumpy rotation error might be simple but I’m really struggling with getting this work without the model snapping onto my cursor.
The Function Im currently stuck with
function UpdateModel()
if rotatable then
local currentMousePosition = UserInputService:GetMouseLocation()
local ray = workspace.CurrentCamera:ScreenPointToRay(currentMousePosition.X, currentMousePosition.Y)
local planePosition = model.PrimaryPart.Position
local planeNormal = Vector3.new(0, 1, 0) -- Assuming the part is on a horizontal plane
local denominator = ray.Direction:Dot(planeNormal)
if math.abs(denominator) > 1e-6 then -- Check if the ray is not parallel to the plane
local t = (planePosition - ray.Origin):Dot(planeNormal) / denominator
local intersectionPoint = ray.Origin + t * ray.Direction
local direction = (intersectionPoint - planePosition).Unit
if direction.Magnitude > 0 then
local targetCFrame = CFrame.lookAt(planePosition, planePosition + direction)
model:SetPrimaryPartCFrame(targetCFrame)
end
end
else
return
end
end
The easiest strategy for these kinds of things is to just use a drag detector. In your case, I might set its drag style to rotate axis and measure drag frame to determine when the player has stirred enough. To get the spoon to stay at the edge of the pot, I’d offset the origin of the spoon’s model so that rotating the model’s pivot ends up at the center while the spoon itself appears to be at the edge of the pot.
Thanks for pointing that out! I didnt know such thing was there
I’ll leave the code here if anyone wishes to use it as well:
Code
local dragDetector = workspace:WaitForChild("spin").wheel.DragDetector
local previousRotationX = nil
local Ongoing = false
local halfwaydone = false
local loopamount = 0
local requiredloops = 3
dragDetector.DragStart:Connect(function()
Ongoing = true
end)
dragDetector.DragEnd:Connect(function()
Ongoing = false
halfwaydone = false
--loopamount = 0 Doesn't make sense but It's an option
previousRotationX = nil
end)
dragDetector.DragContinue:Connect(function(dragFrame)
local rotationX, _, _ = dragDetector.DragFrame:ToEulerAnglesXYZ()
local currentRotationX = math.deg(rotationX)
if previousRotationX then
-- print(math.floor(currentRotationX))
if (math.floor(currentRotationX) >= -180 and math.floor(currentRotationX) <= -170) or (math.floor(currentRotationX) <= 180 and math.floor(currentRotationX) >= 170) and Ongoing then
--[[
the reason I didn't do == 180's is because the degrees are so janky it can skip the exact number sometimes.
After this point, the current rotation will be reversed to minus and will drastically go down to zero
! You should also keep in mind the player might spin the other way around from here !
]]--
halfwaydone = true
end
if (math.floor(currentRotationX) >= -10 and math.floor(currentRotationX) <= -0) or (math.floor(currentRotationX) <= 10 and math.floor(currentRotationX) >= 0) and Ongoing then
if halfwaydone == true then
halfwaydone = false
loopamount = loopamount + 1
warn("loop amount: "..loopamount)
if loopamount >= requiredloops then
warn("Complete")
dragDetector.Enabled = false
dragDetector.Parent["victory.wav"]:Play()
end
end
end
else
previousRotationX = currentRotationX
end
end)