CFrame Experts I need You

  1. What do you want to achieve?
    I want to spin a part in front of the player’s camera view.
  2. What is the issue?
    I don’t know how to do it properly, it glitches out.
  3. What solutions have you tried so far?
    Not that many since I’m not sure how I’m supposed to do this while using TweenService for smooth spinning.

So this is what happens with my current spinning method:


Here’s the code:

workspace.Pet.Parent = workspace.Camera
local tweenService = game:GetService('TweenService')
local tweenInfo = TweenInfo.new(0.15, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut)
local tweenInfo2 = TweenInfo.new(0.5, Enum.EasingStyle.Quart, Enum.EasingDirection.Out)
local pet = workspace.Camera.Pet

workspace.Camera.Changed:Connect(function()
	workspace.Camera.Pet.CFrame = workspace.Camera.CFrame * (pet.CFrame - pet.CFrame.Position) + (workspace.Camera.CFrame.LookVector * Vector3.new(1.1,1.1,1.1))
	spawn(function()
		local tween1 = tweenService:Create(pet, tweenInfo, {CFrame = pet.CFrame * CFrame.Angles(0,math.rad(-90),0)})
		local tween2 = tweenService:Create(pet, tweenInfo,  {CFrame = pet.CFrame * CFrame.Angles(0,math.rad(0),0)})
		local tween3 = tweenService:Create(pet, tweenInfo,  {CFrame = pet.CFrame * CFrame.Angles(0,math.rad(90),0)})
		local tween4 = tweenService:Create(pet, tweenInfo2,  {CFrame = pet.CFrame * CFrame.Angles(0,math.rad(180),0)})

		tween1:Play()
		tween1.Completed:Connect(function()
			tween2:Play()
		end)
		tween2.Completed:Connect(function()
			tween3:Play()
		end)
		tween3.Completed:Connect(function()
			tween4:Play()
		end)
		tween4.Completed:Connect(function()
			tween1:Play()
		end)
	end)
end)

This is how it works with no spinning:


Here’s the code:

workspace.Pet.Parent = workspace.Camera
local tweenService = game:GetService('TweenService')
local tweenInfo = TweenInfo.new(0.15, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut)
local tweenInfo2 = TweenInfo.new(0.5, Enum.EasingStyle.Quart, Enum.EasingDirection.Out)
local pet = workspace.Camera.Pet

workspace.Camera.Changed:Connect(function()
	workspace.Camera.Pet.CFrame = (workspace.Camera.CFrame * CFrame.Angles(0, 
        math.rad(90), 0)) + (workspace.Camera.CFrame.LookVector * Vector3.new(1.1,1.1,1.1))
end)
1 Like

TweenService is going to struggle with anything involving camera movement because the goal point is serialized and unchangeable upon creation of a Tween. The only way to change it is to make a new tween.

By hooking into Camera.Changed, your code is firing every time the camera changes. When doing anything other than simply positioning the pet, that means many instances of your code are running on top of each other, resulting in undesirable behavior.

This code will allow you to spin a pet:

local render_stepped = game:GetService("RunService").RenderStepped

local camera = workspace.CurrentCamera

local ROTATION_OFFSET = CFrame.Angles(0,0,0)	--Modify this if your model does not face the correct orientation.

local SPIN_DURATION = 0.6	--Duration of time in seconds to complete one rotation.
local SPIN_DISTANCE = 1.1	--Studs away from camera to have the model spin.

local pi_2 = 2*math.pi

local spin_connection

local function spin_pet(pet)
	if spin_connection then return end
	pet.Parent = camera

	local current_time = 0
	spin_connection = render_stepped:Connect(function(delta_time)
		pet.CFrame = (camera.CFrame + (camera.CFrame.LookVector * SPIN_DISTANCE)) *
			CFrame.Angles(0,pi_2*(current_time/SPIN_DURATION),0) *
			ROTATION_OFFSET
		current_time = (current_time + delta_time) % SPIN_DURATION
	end)
end

local function stop_spin()
	if spin_connection then
		spin_connection:Disconnect()
		spin_connection = nil
	end
end

This code uses two functions to handle movement: spin_pet(pet) and stop_spin(). spin_pet() requires a reference of the pet to spin to be passed to it, but stop_spin() requires nothing. Usage could look something like this:

local pet = workspace.Pet
spin_pet(pet)
task.wait(3)
stop_spin()

This would spin the pet for three seconds. There are a few things to bear in mind with this code, though:

  1. Only one pet can be spun at a time. stop_spin() must be called before a new pet can be spun.
  2. stop_spin() doesn’t do anything besides stopping the spin. The pet will still be parented under workspace.CurrentCamera and simply floating in space. What happens after stopping the spin will need to be handled by your code.
  3. If your pets are not facing the correct direction when using this code, changing the angles of ROTATION_OFFSET will allow you to modify the default orientation of the objects. Moreover, the spin speed and distance from camera can be modified by changing SPIN_DURATION and SPIN_DISTANCE, respectively.
2 Likes