[Tutorial] Changing Character while ingame with Custom Rigs:

This is a tutorial for you to create your custom rig in roblox. (Note: does not work with single-mesh / bone characters)

– for anyone still using this tutorial for development, please note that this method causes some methods of the Player, that are related to the character, to not work properly.

First, if your custom char structure does look like normal R6 (or R15), you just need to use HumanoidDescription, it is very useful. But if it doesn’t, it is tricky, luckly i’ve made a game with it before, here’s how I made:

Usually, people try to keep changing StarterCharacters in “StarterPlayer” during the game, I was doing it until I find out that it leads to lots of weird bugs all over the char, with plenty of APIs not working as it should. To prevent this bugs I had to make it the hard but rewarding way:

First you will need to disable CharacterAutoLoads in server script with

game.Players.CharacterAutoLoads = false

Then you will make a custom Loading function for your custom rig:

local function LoadChar(Player, DesiredSpawnPosition, CharName)
    spawn(function()

        -- clone body from server storage (simulating it is there):
        local body = game.ServerStorage.Characters[CharName]:Clone()
        body.Parent = workspace

        -- Move the body for desired position:
        body:SetPrimaryPartCFrame(CFrame.new(DesiredSpawnPosition))

        -- Define Char Model Name:
        body.Name = Player.Name

        -- kill old char if there is one:
        if Player.Character then
        	Player.Character:Destroy()
        end

        -- Define Player's new Char:
        Player.Character = body

        -- Put things from StarterCharacterScripts inside the char,
        -- cause it will not do automatically:
        for i, v in pairs(game.StarterPlayer.StarterCharacterScripts:GetChildren()) do
	        v:Clone().Parent = body
        end

        -- Here, local scripts wont run if
        -- they are inside a Tool or Accessory in the char.
        -- You can fix this by setting .Disabled = true and then
        -- .Disabled = false again in the LocalScript. 
        -- It is an engine bug.

        -- Default Player.CharacterAdded event wont run here,
        -- so create a custom one with a BindableEvent instance
        -- called CharacterAdded in ReplicatedStorage:
	    game.ReplicatedStorage.CharacterAdded:Fire(Player.Character)
    end)
end

Then you can use this function on PlayerAdded event or anywhere when you want to change your Character, like this:

game.Players.PlayerAdded:Connect(function(Player)
    -- Calling the function to add char:
    LoadChar(Player, Vector3.new(0,50,0), "MyCustomRigName")

    -- Listen to the CharacterAdded Custom Event:
    game.ReplicatedStorage.CharacterAdded.Event:Connect(function(Character)
        -- after spawn
        print("CharAdded")

    end)
end)

Next you will need to set up a Respawning system for when the player dies sinse CharacterAutoloads is disabled inside CharacterAdded.Event:

  game.ReplicatedStorage.CharacterAdded.Event:Connect(function(Character)

        local Humanoid = Character:WaitForChild("Humanoid")

        Humanoid.Died:Connect(function()
            wait(3) -- seconds between death and respawn
            LoadChar(Player,  Vector3.new(0,50,0), "MyCustomRigName")
        end)
    end)

After this, when you spawn, your camera will be detached from your Character. You can easily re-attach it by setting Camera.CameraSubject in the beggining of a local script inside of your custom char (or probably one that were in StarterCharacterScripts) like this:

-- Normal Player variables:
local Players = game.Players
local LocalPlayer = Players.LocalPlayer
local Character = LocalPlayer.Character or LocalPlayer:CharacterAdded:Wait()
local Humanoid = Character:WaitForChild("Humanoid")
local Head = Character:WaitForChild("Head")

-- Camera:
local Camera = workspace.CurrentCamera
Camera.CameraSubject = Head -- You may think it would be ok to use Humanoid 
--here, but it bugs sometimes. A "Head" is an obrigatory character's Instance for 
--Humanoid to work. I've never tried with a character with no Humanoid though.
Camera.CameraType = Enum.CameraType.Custom

If you have done it all until here, it is very possible that you would want to disable the custom walking sound that haunts your rig if it is something like a dragon or an alien - Why would it have that spongebob’s boots sound while walking or climbing?

To change or mute default character sounds you will have to fork RbxCharacterSounds and edit it:

  1. Hit Play button.
  2. Go to Players Folder > Your Player > PlayerScripts
  3. Copy “RbxCharacterSounds”
  4. Hit Stop button.
  5. Paste it in StarterPlayer > StarterPlayerScripts
  6. Open it and find the SOUND_DATA table, it contains sound ID’s and Volume.
  7. If you want to delete the sound, you can go for deleting the whole walking and climbing sound object from the table (and you will have to find delete all of its calls in the whole script) OR you can just mute it by setting Volume to 0, and muted the SOUND_DATA table should look like this:
local SOUND_DATA = {
	Climbing = {
		SoundId = "rbxasset://sounds/action_footsteps_plastic.mp3",
		Looped = true,
		Volume = 0,
	},
	Died = {
		SoundId = "rbxasset://sounds/uuhhh.mp3",
	},
	FreeFalling = {
		SoundId = "rbxasset://sounds/action_falling.mp3",
		Looped = true,
	},
	GettingUp = {
		SoundId = "rbxasset://sounds/action_get_up.mp3",
	},
	Jumping = {
		SoundId = "rbxasset://sounds/action_jump.mp3",
	},
	Landing = {
		SoundId = "rbxasset://sounds/action_jump_land.mp3",
	},
	Running = {
		SoundId = "rbxasset://sounds/action_footsteps_plastic.mp3",
		Looped = true,
		Pitch = 1.85,
		Volume = 0,
	},
	Splash = {
		SoundId = "rbxasset://sounds/impact_water.mp3",
	},
	Swimming = {
		SoundId = "rbxasset://sounds/action_swim.mp3",
		Looped = true,
		Pitch = 1.6,
	},
}

You can also try to change the default sound URL for another URL (but then keep its volumes as it was before).


And finally, for the custom animations for actions that are automatic on roblox, like walking, swim, jump, climb and etc, you’ll need to fork the “Animations” script from you Character:

  1. Hit Play button.
  2. Open your Character in Explorer
  3. Copy the local script called “Animate”
  4. Hit Stop button.
  5. Paste it in StarterPlayer > StarterCharacterScripts
  6. Inside the script (instance, not its text) there are values with the action name, go inside the value with name of the animation you want to put yours, click on the Animation object inside it and change it’s ID in properties to your animation’s ID. Attention here: Although there is a “walk” and a “run” animation, the actual normal walking sistem is only using the walk anim, changing “run” seems to rave no effect. And more important: Never use the same animation ID for walk and run animations because it will stop the animations from replicating to server.

And it’s done!
If you tried and got any problems or need more info please feedback.

29 Likes

Oh wow! this is very helpful! Usually, i would just change the mesh inside the character during game! Thanks!

2 Likes

Thank you so much, I’ve been looking everywhere for an example like this :+1:

2 Likes

Ive been updating this post with some more tips.

3 Likes

Thanks, i am looking for this!

1 Like

Whats the .Event after the CharacterAdded in the two different scripts supposed to mean? i dont think events have .Event:Connect(function(param) ?

it is a Bindable Event object created in Replicated Storage. Bindable events works between client-to-client or server-to-server. It Allows to create custom events.

https://developer.roblox.com/en-us/api-reference/class/BindableEvent

The CharacterAdded.Event:Connect is in the same script then the LoadChar function.

This is cool. Btw I think this is a typo. That last “)” should be after the first end, not the second, since it should be wrapping the spawn function.

1 Like

I have a question, is it possible to go back to your normal character once you reset / die?

Not by this system described above. You should explore the Players:GetCharacterAppearanceAsync API to implement it.