Camera Snaps when I change characters

Hello,
So I have been trying to make a sort of change-character system, where the player’s model can change really quickly. A little problem is my solution is kind of held together terribly. Whenever I ‘morph’ my player the camera awkwardly snaps into a straight back-facing camera. There would definitely be better ways to do this, such as maybe only changing the Player’s model.

local oldPlayer = player.Character
local newPlayer = propTransform:Clone()

local oldCFrame = oldPlayer:GetPrimaryPartCFrame()

player.Character = newPlayer
newPlayer.Parent = workspace
newPlayer.Name = player.Name
newPlayer:SetPrimaryPartCFrame(oldCFrame)
oldPlayer:Destroy()

Thanks for anyone who helps, B

When ‘morph’ function is triggered - first send an event to stop the client’s camera in place and when the change is completed trigger an event to release the camera.

Now how would I go about doing that, exactly??

has anyone figured it out? not to necropost but i’d really like the solution

CameraFixer client script:

--!strict

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Workspace = game:GetService("Workspace")
local RunService = game:GetService("RunService")

local ClientConstants = require(ReplicatedStorage:WaitForChild("ClientConstants"))

local player = Players.LocalPlayer

local lastCameraCFrame: CFrame? = nil

local function handleMorphingDuringHeartbeat()
    local camera = Workspace.CurrentCamera
    if not camera then
        return
    end
    if typeof(lastCameraCFrame) == "CFrame" then
        camera.CFrame = lastCameraCFrame
    end

    local character = player.Character
    local humanoid = character and character:FindFirstChildOfClass("Humanoid")
    if character and humanoid then
        camera.CameraSubject = humanoid
    end
end

local function onHeartbeat()
    local camera = Workspace.CurrentCamera
    if not camera then
        return
    end
    local isMorphing = player:GetAttribute(ClientConstants.IS_MORPHING_ATTRIBUTE)
    if isMorphing then
        handleMorphingDuringHeartbeat()
        return
    end
    lastCameraCFrame = camera.CFrame
    local character = player.Character
    if not character then
        return
    end
    local humanoid = character:FindFirstChildOfClass("Humanoid")
    if not humanoid then
        return
    end
    camera.CameraSubject = humanoid
end

local function initialize()
    RunService.Heartbeat:Connect(onHeartbeat)
end

initialize()

ClientConstants client script:

return {
    DISABLE_IS_MORPHING_DELAY = 0.1,
    IS_MORPHING_ATTRIBUTE = "isMorphing",
}

MorphsHandler server script:

--!strict

local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local ServerScriptService = game:GetService("ServerScriptService")
local ServerStorage = game:GetService("ServerStorage")
local Workspace = game:GetService("Workspace")

local ServerConstants = require(ServerScriptService:WaitForChild("ServerConstants"))

local characterTemplates = ServerStorage:WaitForChild("Characters")

local function createDisableIsMorphingAttributeFunction(player: Player)
	return function()
		player:SetAttribute(ServerConstants.IS_MORPHING_ATTRIBUTE, false)
	end
end

local function handleChildDescendantInMorph(descendant: Instance, player: Player)
	if not descendant:IsA("BasePart") then
		return
	end

	descendant.Anchored = false
	descendant.CanCollide = false
	descendant.CanTouch = false
	descendant.CanQuery = false
	descendant.Massless = true
	if descendant:IsDescendantOf(Workspace) and not descendant.Anchored then
		descendant:SetNetworkOwner(player)
	end
end

local function morphPlayer(player: Player, characterTemplate: Model)
	player:SetAttribute(ServerConstants.IS_MORPHING_ATTRIBUTE, true)

	local disableIsMorphingAttribute = createDisableIsMorphingAttributeFunction(player)
	local character = player.Character
	if not character then
		disableIsMorphingAttribute()
		return
	end

	local currentPivot = character:GetPivot()

	local humanoid = character:FindFirstChildOfClass("Humanoid")
	if not humanoid then
		disableIsMorphingAttribute()
		return
	end

	local rootPart = humanoid.RootPart
	if not rootPart then
		disableIsMorphingAttribute()
		return
	end

	local newCharacter = characterTemplate:Clone()
	newCharacter.Name = player.Name
	local newCharacterHumanoid = newCharacter:FindFirstChildOfClass("Humanoid")
	if not newCharacterHumanoid then
		newCharacter:Destroy()
		disableIsMorphingAttribute()
		return
	end
	local newCharacterRootPart = newCharacterHumanoid.RootPart
	if not newCharacterRootPart then
		newCharacter:Destroy()
		disableIsMorphingAttribute()
		return
	end

    newCharacter:SetAttribute(ServerConstants.CURRENT_MORPH_ATTRIBUTE, characterTemplate.Name)

	newCharacter.Parent = Workspace

	player.Character = newCharacter

	task.delay(ServerConstants.DISABLE_IS_MORPHING_DELAY, disableIsMorphingAttribute)

	newCharacterRootPart.Anchored = false
	newCharacter:PivotTo(currentPivot)
	for _, descendant in newCharacter:GetDescendants() do
		handleChildDescendantInMorph(descendant, player)
	end
end

local function onMorphPartPlayerHeartbeat(morphPart: BasePart, player: Player)
	local character = player.Character
	if not character then
		return
	end

	local currentMorph = character:GetAttribute(ServerConstants.CURRENT_MORPH_ATTRIBUTE)
	if player:GetAttribute(ServerConstants.IS_MORPHING_ATTRIBUTE) or currentMorph == morphPart.Name then
		return
	end

	local humanoid = character:FindFirstChildOfClass("Humanoid")
	if not humanoid then
		return
	end

	local rootPart = humanoid.RootPart
	if not rootPart then
		return
	end

	local rootPartYPlanePosition = Vector2.new(rootPart.Position.X, rootPart.Position.Z)
	local morphPartYPlanePosition = Vector2.new(morphPart.Position.X, morphPart.Position.Z)
	local distance = (rootPartYPlanePosition - morphPartYPlanePosition).Magnitude
	if distance > ServerConstants.MORPH_PART_RADIUS then
		return
	end

	local characterTemplate = characterTemplates:FindFirstChild(morphPart.Name)
	if not characterTemplate then
		return
	end

	morphPlayer(player, characterTemplate)
end

local function onMorphPartHeartbeat(morphPart: BasePart)
	for _, player in Players:GetPlayers() do
		onMorphPartPlayerHeartbeat(morphPart, player)
	end
end

local function onHeartbeat()
	local morphPartsModel = Workspace:FindFirstChild("MorphParts")
	if not morphPartsModel then
		return
	end

	local morphParts: { BasePart } = morphPartsModel:GetChildren()
	for _, morphPart in morphParts do
		onMorphPartHeartbeat(morphPart)
	end
end

local function initialize()
	RunService.Heartbeat:Connect(onHeartbeat)
end

initialize()

ServerConstants server script:

--!strict

return {
	MORPH_PART_RADIUS = 2,
	DISABLE_IS_MORPHING_DELAY = 0.1,
	IS_MORPHING_ATTRIBUTE = "isMorphing",
	CURRENT_MORPH_ATTRIBUTE = "currentMorph",
}