How to switch player to different character (custom rig) mid-game

Overview

I have seen a number of posts over the years on the proper way to switch over a player’s character model to a different rig. The primary issue is that once the changeover happens, local scripts will not execute, which breaks animations and any other local scripts that have been added.

In this tutorial, I will show you how to properly switch the player’s character model to a different/custom rig mid-game and still have all the animations work.

Procedure Outline

The outline will give you the basic method on what to do. The new character will be referred to as NewChar while the player’s original character will be referred to as OldChar.

Procedure
  1. Get the player’s current character.
  2. Unequip any tool(s) the player may have equipped.
  3. Clone the new rig from either ReplicatedStorage, ServerStorage, or wherever you have your custom rigs stored.
  4. Clone all scripts from OldChar to NewChar.
    • If you get a LocalScript named “Animate”, make sure to to disable it.
  5. Set the name of NewChar to Player.Name.
  6. On NewChar, get the Humanoid reference.
  7. Set Humanoid.DisplayName to Player.DisplayName.
  8. Wait 1 frame using task.wait().
  9. Set Player.Character to NewChar.
  10. Destroy OldChar.
  11. Get the reference to the LocalScript “Animate”.
  12. Enable Animate.
  13. Set the parent of NewChar to game.Workspace.
  14. Reequip any tools the player might have had equipped.

By following this procedure, you will be able to switch the player to a new rig mid-game and not break local scripts in the new rig.

Code

Here’s some basic code for you to work from.

Code
-- Switches the player's rig to the given new rig.
local function switchPlayerChar(player: Player, newRig: Model)

	-- Step 1: Get the player's character.
	local oldChar = player.Character
	local count = 10
	while oldChar == nil and count > 0 do
		count -= task.wait()
		oldChar = player.Character
	end
	if oldChar == nil then
		warn("Player's character failed to load before the timeout.")
		return
	end

	-- Step 2: Unequip any tools the player has equipped.
	local tool = oldChar:FindFirstChildOfClass("Tool")
	if tool ~= nil then
		tool.Parent = player.Backpack
	end

	-- Step 3: Clone the new rig.
	local newChar = newRig:Clone()

	-- Step 4: Clone all scripts to new rig.
	local list = oldChar:GetChildren()
	for _, item in ipairs(list) do
		if item:IsA("Script") or item:IsA("ModuleScript") then
			local newItem = item:Clone()
			newItem.Parent = newChar
		elseif item:IsA("LocalScript") then
			local newItem = item:Clone()
			newItem.Parent = newChar
			if newItem.Name == "Animate" then
				newItem.Enabled = false
			end
		end	
	end
	
	-- Step 5: Set Rig Name
	newChar.Name = player.Name

	-- Steps 6 & 7: Set Display Name
	local newHuman = newChar:WaitForChild("Humanoid", 10)
	newHuman.DisplayName = player.DisplayName

	-- Step 8: Wait 1 Frame
	task.wait()

	-- Step 9: Change Character
	player.Character = newChar

	-- Step 10: Destroy Old Character
	oldChar:Destroy()
	oldChar = nil

	-- Steps 11 & 12: Enable Animations
	local animate = newChar:FindFirstChild("Animate")
	animate.Enabled = true

	-- Step 13: Make the new character visible.
	newChar.Parent = game.Workspace

	-- Step 14: Reequip tool if needed.
	if tool ~= nil then
		tool.Parent = newChar
	end
end

Additional Information

  • The order things are done must remain the same. If the order changes, then local scripts will break.
  • You have to add all scripts to the NewChar before you set Player.Character to NewChar.
  • You have to set Player.Character before you parent the character to game.Workspace.
  • You can add attributes to Humanoid for things like if you are going to remove all tools, or if the previously equipped tool is to be reequipped or not.
  • What I do is get the player’s UserId and set a UserId attribute on both the character model and the Humanoid.
7 Likes