Tween CFrame according to local space


I want to tween the gun according to local space, because if I use world space and move during the tween, the final position will be wrong (as shown in the video). I would appreciate any help for this, thank you!

runService:BindToRenderStep("ViewmodelPivot", Enum.RenderPriority.Last.Value, function()
		viewModel:PivotTo(camera.CFrame)
end)

local endCF = viewModel.HumanoidRootPart.FinalPosition.WorldCFrame
local tweenInfo = TweenInfo.new(.7, Enum.EasingStyle.Back, Enum.EasingDirection.InOut)
local tween = tweenService:Create(weaponModel.PrimaryPart, tweenInfo, {CFrame = endCF})
tween:Play()
1 Like

You could probably do something to make it happen.

This might work for you: https://www.youtube.com/watch?v=RYzj4TjiMyE

But I recommend you use animations.

2 Likes

Your approach to how you handle weapons is really bad, handling props outside animations is painfully hard, and you get results like these.

I would put the gun inside the actual viewport rather than animating it globally.
Or probably weld the gun to the player, though this solution is not recommended.

2 Likes

But I’m not using any animations, I’m using IKControl for my viewmodel rig to make it feel more natural, and I believe I’ve achieved that, plus I now no longer need to handle each gun differently, so that’s a lot less effort on my end

1 Like

Thank you for the suggestion, I’ll check it out in a bit to see if it works

1 Like

Oh, my bad, I didn’t know :melting_face:

I guess I would try welding then, or just mess around with math and RunService, idk honestly.

1 Like

No hard feelings, the solution I’m actually trying to reach here is math, but I’m very stupid and don’t know how to do that, so I’m asking for help

2 Likes


I tried this and found that it could work, but I don’t have an idea on how to make it not be floating away from the hand. If you could point me which setting to change, I’d appreciate it!

local currentCF = weaponModel.PrimaryPart.CFrame
	local currentVelocity = Vector3.zero
	local smoothTime = .4
	local maxSpeed = nil

while task.wait() do
			local targetCf = viewModel.HumanoidRootPart.FinalPosition.WorldCFrame

			currentCF, currentVelocity = tweenService:SmoothDamp(
				currentCF,
				targetCf,
				currentVelocity,
				smoothTime,
				maxSpeed
			)

			weaponModel:PivotTo(currentCF)
		end
1 Like

Try pivoting to

weaponModel:PivotTo(CFrame.new(targetCf.Position) * currentCF.Rotation)

This should ignore the position and only keep the rotation.

2 Likes


It seems to immediately snap to target instead of moving to it. This is not really ideal for me, is there anyway for the gun to move to the intended position?

Yeah, at this point it would be best to just rig the weapon so it is attached to the hand. Then, you can apply the CFrame changes to the arms model. And since the weapon is rigged to the arms, it should work properly. Look into rigging for animations with Motor6D.

1 Like

I’ll look into it. Thank you for the help!

After taking a break for a few days, I came to the conclusion that the simplest way to do this would be to create a custom tweening function just for this specific purpose. I found the function itself through this post, but found that the gun was still floating away when character moved. I fixed this by adding a duration offset (I think that’s how it’s called) , which gave me this result (I used 0.35 here):

How it looks without the duration offset:

I think this duration offset thing is a bit hacky so if anyone has a better solution, please let me know.

local function CustomTween(part, toPart: Attachment, duration)
	local startCframe : CFrame = part:GetPivot()
	local startTime = tick()
	
	local Task
	Task = task.spawn(function()
		local durationOffset = 0
		while task.wait() do
			local t = math.clamp(((tick() - startTime) / duration) + durationOffset, 0, 1)
			local alpha = tweenService:GetValue(t, Enum.EasingStyle.Back, Enum.EasingDirection.InOut)
			
			part:PivotTo(startCframe:Lerp(toPart.WorldCFrame, alpha)) 

			if t == 1 then
				break
			end
		end
	end)
	
	task.delay(duration + 0.1, function()
		task.cancel(Task)
	end)
	
end
1 Like

I think you will want both the startCframe and the goalCFrame to be relative to the targetPart.

Try this:

local function CustomTween(part, toPart: Attachment, duration)
	local relativeStartCF : CFrame = part:GetPivot():ToObjectSpace(toPart.WorldCFrame)
	local startTime = tick()
	
	local Task
	Task = task.spawn(function()
		while task.wait() do
			local t = math.clamp(((tick() - startTime) / duration), 0, 1)
			local alpha = tweenService:GetValue(t, Enum.EasingStyle.Back, Enum.EasingDirection.InOut)
			local startCF = toPart.WorldCFrame * relativeStartCF

			part:PivotTo(startCF:Lerp(toPart.WorldCFrame, alpha)) 

			if t == 1 then
				break
			end
		end
	end)
	
	task.delay(duration + 0.1, function()
		task.cancel(Task)
	end)
	
end
1 Like


This is what happens, do you know how to fix it?

I do not. I feel like I’d need a more full view of the code and models to understand. If the code you have before my post works, I’d suggest sticking to that.

1 Like

I could try sending all the model’s part and positions but I feel that would be taking up too much time. Thank you for the reply, though. I definitely see how that could work for my case.

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