Tweening not working properly [help needed]

I have a script that should make a model move based on keybinds.
When I press a key, the model moves in a certain direction, in this case, it is rotating in one angle.
When I release it, it stops moving entirely.
What I want from this script is to make a spotlight model rotate smoothly with the use of tweening, when I press and release a key, by gradually speeding/increasing up to a number, let’s say 1, then upon release, slow/lower down back to 0.

Yet, this script which I have been trying to tweak and ask for help to fix, hasn’t been successful in getting it to work, which is why I’m coming here again to try and get this script fixed.

Currently, there is an error shown with the current code it has gotten to, which I will show below.

local userInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local TweenService = game:GetService("TweenService")
local SpotlightHead = game.Workspace.Spotlight.Arm.Head
local UpdateCon

local SpotlightPos = SpotlightHead.primaryPart
local SpotlightCurrentPos = SpotlightPos.Position

local moveStart = SpotlightCurrentPos
local moveEnd = SpotlightCurrentPos * CFrame.Angles(1, 0, 0)

local tweenInfo = TweenInfo.new(
	0.5,
	Enum.EasingStyle.Quad,
	Enum.EasingDirection.Out,
	-1,
	true,
	0
)

local tweenStart = TweenService:Create(SpotlightHead, tweenInfo, {moveStart = moveEnd})
local tweenStop = TweenService:Create(SpotlightHead, tweenInfo, {moveEnd = moveStart})

userInputService.InputBegan:Connect(function(input, gameProcessedEvent)
	if input.UserInputType ~= Enum.UserInputType.Keyboard then return end
	if input.KeyCode ~= Enum.KeyCode.KeypadEight then return end

	if UpdateCon then
		UpdateCon:Disconnect()
		UpdateCon = nil
	end

	UpdateCon = RunService.Heartbeat:Connect(function(dt)
		tweenStart:Play()
		SpotlightHead:SetPrimaryPartCFrame(moveStart)
	end)
end)

userInputService.InputEnded:Connect(function(input, gameProcessedEvent)
	if input.UserInputType ~= Enum.UserInputType.Keyboard then return end
	if input.KeyCode ~= Enum.KeyCode.KeypadEight then return end
	if not UpdateCon then return end
	
	tweenStop:Play()

	UpdateCon:Disconnect()
	UpdateCon = nil
end)

Here is a video of the original movement of the spotlight:

If anyone is able to clean this code up or provide solutions as to what I can do to get this script working, please let me know.
Any help is greatly appreciated. :slight_smile:

(While not entirely necessary, it would also be easy to work this out on easier methods of communication, if the topic gets filled up too much)

3 Likes

Make sure your model (SpotlightHead) has a PrimaryPart at all, Maybe it’s nil.
And if it has one my best guess is you can try adding:

if not game:IsLoaded() then game.Loaded:Wait() end

At the top of the script, Since it’s a LocalScript.

2 Likes

Same issue, it being nil, even if the targeted primary part is there.

2 Likes

Hmm, Try printing at line 9 the SpotlightPos.

2 Likes

Not sure why, but I can’t get anything to print, and the same error still occurs.

2 Likes

I see, Does the SpotlightHead.PrimaryPart is anchored? Or at least have collision?

2 Likes

Yes, the primary part it’s using is anchored and has CanCollide enabled.

2 Likes

Try running the game, And manually checking with the explorer to see if it still exists.

1 Like

It does still exist when running the game.

1 Like

Isn’t SpotlightPos already a position? Why do you add .Position to it?

If SpotlightPos is a part, add
repeat SpotlightPos = SpotlightHead.primaryPart task.wait()until SpotlightPos~=nil after local SpotlightPos = SpotlightHead.primaryPart

then try testing it

1 Like

Nah, SpotlightPos is a primary part and they want to get the position from that part.

2 Likes

One thing might be because you’re using a lowercase P for PrimaryPart? Although I thought the error would be like primaryPart isn’t a property or something. or is primary part a part named primaryPart?

1 Like

if it weren’t a property it would say "primaryPart" isnt a valid member of SpotlightHead

1 Like

There’s seems to be a lot wrong with this script…

You’re trying to get a position from a PrimaryPart that’s nil (Make sure you’ve set it in properties panel or during runtime) or do something like what these other people suggest: spotLightModel:GetPropertyChangedSignal("PrimaryPart"):Wait()

You’re setting a default position which later you’ll use as a CFrame 3/4 times:

local moveStart = SpotlightCurrentPos -- // Is a vector3, not a cframe
-- // This would error due to Position to CFrame multiplication, you can only do CFrame * Position not the other-way-round
local moveEnd = SpotlightCurrentPos * CFrame.Angles(1, 0, 0)

-- // You're setting what I would assume to be the CFrame
-- // (Although you set them to a position) of the primaryPart otherwise this wouldn't turn and would error since you're trying to tween a model
-- // Make sure things are also welded... 
-- // Setting 'moveStart' property? Which I don't think exists?
local tweenStart = TweenService:Create(SpotlightHead, tweenInfo, {moveStart = moveEnd})
-- // Similar case here
local tweenStop = TweenService:Create(SpotlightHead, tweenInfo, {moveEnd = moveStart})

image

-- // You're continuously playing the same tween every frame
-- // Causing it to just repeat the beginning and never continue to the end
-- // You probably don't actually need the heartbeat
UpdateCon = RunService.Heartbeat:Connect(function(dt)
	tweenStart:Play()
    -- // This contradicts the tween and sets it back to it's original position
    -- // Plus you should be using :PivotTo() instead
    -- // (Obligatory mention of you setting the CFrame to a Vector3 here as well)
	SpotlightHead:SetPrimaryPartCFrame(moveStart)
end)

Lastly, when you go to end the tween, you never stop the “TweenStart” so you might want to call tweenStart:Cancel() This way you know for certain the tween has stopped and you can continue your tweenStop:Play(). Similarly doing this in the run function, checking whether the stop tween is playing and stop it if it is, otherwise continue…


Minor fixes you might want to try:

Setting the variable to the correct type (CFrame)
local moveStart = spotLightHead:GetPivot() -- // this works without the primary part

Correcting the property names so the tween functions, along with the tweened part

-- // Changed the property names to better suit the situation
-- // Should totally rename the primaryPart variable so it doesn't have "Pos" in it
local tweenStart = TweenService:Create(SpotlightPos, tweenInfo, {CFrame = moveEnd})
local tweenStop = TweenService:Create(SpotlightPos, tweenInfo, {CFrame = moveStart})

Checking if the tween is playing, otherwise continue like normal

-- // Assume this is inside the start function you have

-- // My poor programming habits but shows what I meant specifically
if (tweenStop.PlaybackState == Enum.PlaybackState.Playing) then
    tweenStop:Cancel()
end

-- // Since it's already playing, might as well not start another tween
if (tweenStart.PlaybackState == Enum.PlaybackState.Playing) then
    return
end

tweenStart:Play()

There might be more but hopefully some of this helps you.

I know that but does a lowercase P work?

Thankfully this did remove some errors, but now it shows a new one.

Not that good at replacing or fixing up stuff when I confused myself with how messy this script got :smiling_face_with_tear:

Not sure if every change you provided was implemented correctly, but only issues were placing the tween cancel stuff correctly (which I couldn’t), and I don’t know what to replace Heartbeat with, as I’ve been told many times to do.

Here’s the script now:

if not game:IsLoaded() then game.Loaded:Wait() end

local userInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local TweenService = game:GetService("TweenService")
local SpotlightHead = game.Workspace.Spotlight.Arm.Head
local UpdateCon

local moveStart = SpotlightHead:GetPivot()
local moveEnd = moveStart * CFrame.Angles(1, 0, 0)

local tweenInfo = TweenInfo.new(
	0.5,
	Enum.EasingStyle.Quad,
	Enum.EasingDirection.Out,
	-1,
	true,
	0
)

local tweenStart = TweenService:Create(SpotlightHead, tweenInfo, {CFrame = moveEnd})
local tweenStop = TweenService:Create(SpotlightHead, tweenInfo, {CFrame = moveStart})

userInputService.InputBegan:Connect(function(input, gameProcessedEvent)
	if input.UserInputType ~= Enum.UserInputType.Keyboard then return end
	if input.KeyCode ~= Enum.KeyCode.KeypadEight then return end

	if UpdateCon then
		UpdateCon:Disconnect()
		UpdateCon = nil
	end

	UpdateCon = RunService.Heartbeat:Connect(function(dt)
		tweenStart:Play()
		SpotlightHead:SetPrimaryPartCFrame(moveStart)
	end)
end)

userInputService.InputEnded:Connect(function(input, gameProcessedEvent)
	if input.UserInputType ~= Enum.UserInputType.Keyboard then return end
	if input.KeyCode ~= Enum.KeyCode.KeypadEight then return end
	if not UpdateCon then return end
	
	tweenStop:Play()

	UpdateCon:Disconnect()
	UpdateCon = nil
end)