Camera Tweening

Hello!
How could I tween the character’s camera around 30-40 studs above there head.
To make there camera face down towards them.
Maybe angle it around 40 degrees or so, so its not directly aiming down?


I want to do this for my Airstrike system.

You need to change camera.CFrame.

You firstly need to set camera.CameraType to “scriptable” because otherwise your changes will be overwritten by default camera script.

Then, you will need to set it’s CFrame to what you want:

-- example (x, y, z are your values)
camera.CFrame = CFrame.new(x, y, z) * CFrame.Angles(math.rad(x), math.rad(y), math.rad(z))

You can read more here.

For smoother transitions you can use TweenService.

I’m trying to make it follow you’re mouse like shown here.

1 Like

You can make a loop so it updates every second (frame). Use either while or runService. Inside of a loop you can write:

camera.CFrame *= CFrame.new(Vector3.new(0, 10, 0), Vector3.new(mouse.Hit))

or if you don’t want camera to stay above your head, maybe fallow the marker, you can do:

camera.CFrame = mouse.Hit * CFrame.new(0, 10, 0)

I assumed the marker follows your mouse, if not just replace the mouse.Hit with marker.CFrame

-- // Services \\ -- 
local Players 				= 		game:GetService("Players")
local RunService 			= 		game:GetService("RunService")
local TweenService 			= 		game:GetService("TweenService")
local ReplicatedStorage 	= 		game:GetService("ReplicatedStorage")

-- // Variables \\ -- 
local LocalPlayer 			= 	 	Players.LocalPlayer
local Character 			= 		LocalPlayer.Character or LocalPlayer.CharacterAdded:Wait()
local Humanoid 				= 		Character:WaitForChild("Humanoid")
local HumanoidRootPart 		= 		Character:WaitForChild("HumanoidRootPart")

local Camera 				= 		workspace.CurrentCamera

local Tool 					=		script.Parent
local CircleUI				=		ReplicatedStorage:WaitForChild("Circle")
local CircleArrowUI 		=		ReplicatedStorage:WaitForChild("Arrow")


Tool.Equipped:Connect(function(Mouse: Mouse)
	CircleUI.Parent = workspace
	Mouse.TargetFilter = CircleUI
	
	CircleUIPositionConnector = RunService.Heartbeat:Connect(function(DeltaTime: number)
		CircleUI.Position = Mouse.Hit.Position
	end)
	
	Mouse.Button1Down:Connect(function()
		CircleUIPositionConnector:Disconnect()
		CircleUIPositionConnector = nil
		
		
		CircleArrowUI.Parent = workspace
		CircleArrowUI.Position = CircleUI.Position
		
		CircleUIArrowPositionConnector = RunService.Heartbeat:Connect(function(DeltaTime: number)
			Camera.CFrame *= CFrame.new(Vector3.new(0, 10, 0), Vector3.new(Mouse.Hit))
		end)
	end)
end)


Tool.Unequipped:Connect(function()
	if CircleUIPositionConnector then -- // If CircleUIPositionConnector (position selector) exists then kill it!
		CircleUIPositionConnector:Disconnect()
		CircleUIPositionConnector = nil
	end
	
	CircleUI.Parent = ReplicatedStorage -- // Set CircleUI back into ReplicatedStorage!
	CircleArrowUI.Position = ReplicatedStorage -- // Set CircleArrowUI back into ReplicatedStorage!
end)

First you can just create a cframe, like
Offset=CFrame.New(Vector3.new(40,40,40),Vector3.new(0,0,0)
which can be modified but I recommend keeping the 2nd Vector at 0,0,0
and because Heartbeat is always 1 frame behind, It is usually better to use RenderStepped.
and in the RenderSteppedFunction keep the Position from the previous frames and then you can use LerpedVector3=PreviousVector3:Lerp(CurrentVector3,.3)
.3 is just a random number but you can increase it to make the thing faster.
and then you can create a new CFrame using the Vectors we lerped. like
Camera.Position=CFrame.new(LerpedVector3)*Offset

Also the Mouse.Button1Down Connection should have a debounce.

This works!

local player = game.Players.LocalPlayer

local runService = game:GetService("RunService")
local replicatedStorage = game:GetService("ReplicatedStorage")
local marker = replicatedStorage:WaitForChild("Marker"):Clone() -- clones the marker

local mouse = player:GetMouse()
mouse.TargetFilter = marker -- ignores the marker so it hits the surface below
local camera = workspace.CurrentCamera

marker.Parent = workspace -- sets the marker parent to somewhere in the workspace

repeat wait() until player.Character -- waits until the character is added
local char = player.Character
local rootPart = char.HumanoidRootPart

camera.CameraType = Enum.CameraType.Scriptable -- sets it afterwards the charcater is added because the default scripts automatically overwrite cameraType

runService.RenderStepped:Connect(function()
	if mouse.Target ~= nil then
		marker.Position = mouse.Hit.Position -- moves the marker
	end
	
	camera.CFrame = camera.CFrame:Lerp(CFrame.new(rootPart.Position + Vector3.new(0, 50, 50)), 0.1) -- sets it above players rootPart
	
	camera.CFrame = camera.CFrame:Lerp(CFrame.new(Vector3.new(0, 50, 0), marker.Position), 0.1) -- follows the marker
end)

If you want slower or faster transitions (lerps) you can change the 0.1 to lower or higher number.

:open_mouth:
This is really cool!
It seems tho the head can snap to far causing some problems and seizing of the camera.
What’s the best way I could add possible limits so they can seize there camera // place the marker 100’s of feet infront of them.

Its also not as snappy as the original version made by Criminality

Is that good or bad?

You can check the magnitude between rootPart and mouse or camera and mouse (no difference).

local player = game.Players.LocalPlayer

local runService = game:GetService("RunService")
local replicatedStorage = game:GetService("ReplicatedStorage")
local marker = replicatedStorage:WaitForChild("Marker"):Clone() -- clones the marker

local mouse = player:GetMouse()
mouse.TargetFilter = marker -- ignores the marker so it hits the surface below
local camera = workspace.CurrentCamera

marker.Parent = workspace -- sets the marker parent to somewhere in the workspace

repeat wait() until player.Character -- waits until the character is added
local char = player.Character
local rootPart = char.HumanoidRootPart

camera.CameraType = Enum.CameraType.Scriptable -- sets it afterwards the charcater is added because the default scripts automatically overwrite cameraType

runService.RenderStepped:Connect(function()
	if mouse.Target ~= nil and (rootPart.Position - mouse.Hit.Position).Magnitude < 200 and (rootPart.Position - mouse.Hit.Position).Magnitude > 10 then -- checks if the mouse is to far away or to close to the player (gets the distance between rootPart and mouse)
		marker.CFrame = marker.CFrame:Lerp(mouse.Hit, 0.1) -- moves the marker
		marker.Orientation = Vector3.new(0, 0, 0) -- rotates it (you can put whatever you want)
	end
	
	camera.CFrame = camera.CFrame:Lerp(CFrame.new(rootPart.Position + Vector3.new(0, 50, 50)), 0.1) -- sets it above players rootPart
	
	camera.CFrame = camera.CFrame:Lerp(CFrame.new(rootPart.Position + Vector3.new(0, 50, 50), marker.Position), 0.1) -- follows the marker
end)

I also changed how marker moves, now it’s with lerp() so it is more smooth and it also adds a delay to look like its following your mouse (I added it because when the mouse is out of range the marker stops moving and when it enters the range the marker snaps to the mouse and it looks bad, now it smoothly moves to it)

I like the snappy and tweenyeness of the Criminality one,
It also feels like its tweening to parts Infront of the players camera just because it tween’s to the same position on both side of the player (left,right)

It also looks like it focus’s in on one location.