Hello!
As the title suggests, I would like to tween the camera from 2D to 3D when the player touches a part.
I already got the camera switching part down, but I want the camera to transition to that position instead of just snapping to it as seen in the video:
Because of the way I set up the script the only way I think I could go about making this work is if I make the tweening part a seperate function, which I then call in whenever the player touches the part.
The issue is that I don’t know how I would do this because my knowledge about scripting is very limited, and I’ve never used tween on the camera before.
It’s only one local script handling all of it with the 2 parts being located in Workspace.
I did try looking for solutions but I couldn’t find any definitive solutions to make this work. Some straight up didn’t work, others worked for the situation of the OP but not for me while the rest either required me to rewrite the entire script or I couldn’t understand anything about what was said in the post.
So for anyone willing to help, thank you in advance.
local localPlayer = game.Players.LocalPlayer
local camera = workspace.CurrentCamera
local part2D = workspace:WaitForChild("2D")
local part3D = workspace:WaitForChild("3D")
local function TweenCamera(newCFrame, newFOV)
local tweenInfo = TweenInfo.new(
1,
Enum.EasingStyle.Linear,
Enum.EasingDirection.InOut,
0,
false
)
local tween = game.TweenService:Create(
camera,
tweenInfo,
{
CFrame = newCFrame,
FieldOfView = newFOV
}
)
tween:Play()
return tween
end
local lastCamState = nil
local function UpdateCamera(newCamState)
if newCamState ~= lastCamState then
local rootPart = localPlayer.Character:FindFirstChild("HumanoidRootPart")
if rootPart then
if newCamState == "2D" then
task.spawn(function()
local function newCFrame()
return CFrame.new(rootPart.Position + Vector3.zAxis * 60)
end
camera.CameraType = Enum.CameraType.Scriptable
rootPart.Anchored = true
TweenCamera(newCFrame(), 40).Completed:Wait()
rootPart.Anchored = false
while newCamState == lastCamState do
camera.CFrame = newCFrame()
task.wait()
end
end)
elseif newCamState == "3D" or newCamState == nil then
local rpCF = rootPart.CFrame
local newCFrame = CFrame.new(
rpCF.Position - rpCF.LookVector * 20 + rpCF.UpVector * 10,
rpCF.Position
)
camera.CameraType = Enum.CameraType.Scriptable
rootPart.Anchored = true
TweenCamera(newCFrame, 75).Completed:Wait()
rootPart.Anchored = false
camera.CameraType = Enum.CameraType.Custom
end
end
end
lastCamState = newCamState
end
part2D.Touched:Connect(function(hitPart)
local player = game.Players:GetPlayerFromCharacter(hitPart.Parent)
if player then UpdateCamera("3D") end
end)
part3D.Touched:Connect(function(hitPart)
local player = game.Players:GetPlayerFromCharacter(hitPart.Parent)
if player then UpdateCamera("2D") end
end)
localPlayer.CharacterAdded:Connect(UpdateCamera)
This will tween the camera from to the desired state when touching either the 2D or 3D part. You set the camera to a new state by doing UpdateCamera("3D") or UpdateCamera("2D")
You can adjust the tweening properties to your liking of course.
A problem that i could not find a solution to is that the camera snaps slightly at the end of tweening from 2D to 3D as the CameraType changes from Scriptable to Custom. I don’t think it’s possible to do anything about this sadly… (Unless you want to code your own 3D camera system)
This one works, the sudden jump you pointed out doesn’t happen on my end, so this works and I’ll mark it as a solution.
However I also screwed up when writing this post because I didn’t point out that I wanted the camera to transition while the player is still moving, to that this was the solution that I managed to scramble together with trial and error, though the transition is not as smooth as the one with your code.
local player = game.Players.LocalPlayer
local camera = workspace.CurrentCamera
local TweenService = game:GetService("TweenService")
Camera2D = false
player.CharacterAdded:Wait()
player.Character:WaitForChild("HumanoidRootPart")
camera.CameraSubject = player.Character.Head
camera.CameraType = Enum.CameraType.Attach
camera.FieldOfView = 75
local RunService = game:GetService("RunService")
local tweenInfo = TweenInfo.new(
1.2, -- Time
Enum.EasingStyle.Linear, -- EasingStyle
Enum.EasingDirection.In, -- EasingDirection
0, -- RepeatCount (when less than zero the tween will loop indefinitely)
false, -- Reverses (tween will reverse once reaching it's goal)
0 -- DelayTime
)
local function onUpdate()
if player.Character and player.Character:FindFirstChild("HumanoidRootPart") and Camera2D == true then
camera.CFrame = CFrame.new(player.Character.Head.Position) * CFrame.new(0,5,20) * CFrame.fromOrientation(-0.2,0,0)
else
camera.CameraSubject = player.Character.Head
camera.CameraType = Enum.CameraType.Custom
camera.FieldOfView = 75
end
end
workspace.CameraTo3D.Touched:Connect(function(hit)
if game.Players.LocalPlayer == game.Players:GetPlayerFromCharacter(hit.Parent) then
local Goal = player.Character.Head.CFrame
camera.FieldOfView = 120
if Camera2D == true then
local tween = TweenService:Create(camera, tweenInfo, { CFrame = Goal })
tween:Play()
end
Camera2D = false
wait(0.5)
camera.FieldOfView = 75
camera.CameraType = Enum.CameraType.Custom
camera.CameraSubject = player.Character.Head
end
end)
workspace.CameraTo2D.Touched:Connect(function(hit)
if game.Players.LocalPlayer == game.Players:GetPlayerFromCharacter(hit.Parent) then
Camera2D = true
camera.FieldOfView = 75
end
end)
RunService:BindToRenderStep("Camera", Enum.RenderPriority.Camera.Value, onUpdate)