How to change custom character during game

I’m working on a game where all the characters for the player is custom made, (i.e. pumpkin, ghost, burger).

What I have tried via script is I’m parenting the Character Model to Starter Character folder that didn’t work, I’ve also tried to parent the model to local player in Game.Player but didn’t work. BTW I’m using remote event to tell server to reload the character.

14 Likes

Parent the Character Model to game.StarterPlayer and make sure that the model is named StarterCharacter. You could also go to the player and set their character from there.

Some custom character has different HipHeight so changing same player model is not a good idea. Also I know I would have to rename model to StarterCharacter to make it work, so would it work during gameplay?

1 Like

You can just do:

player.Character = [Model] -- Simply reference your custom character.
2 Likes

I tried following method but it’s not working.

On button click , an event is fired to server to spawn the character with name of the custom model.

selectButton.MouseButton1Click:Connect(function()
	local model
	for _, char in pairs(location:GetChildren()) do
		if char:IsA("Model") then
			model = char:Clone()
			break
		end
	end
	respawnEvent:FireServer(model.Name)
end)

On server side, A model is given to plr.Character and then plr:LoadCharacter() function is triggered.

local function respawnPlayer(plr, char)
	local model = replicatedStorage.Characters:FindFirstChild(char)
	print("Model from Server is " .. tostring(model)) -- This tells the name of model correctly...
	plr.Character = model
	plr:LoadCharacter()
end
respawnEvent.OnServerEvent:Connect(respawnPlayer)
2 Likes

On your client side, you can use :FindFirstChildWhichIsA to get your model:

selectButton.MouseButton1Click:Connect(function()
    local model = location:FindFirstChildWhichIsA("Model")
    assert(model, "model does not exist for this location!")

    respawnEvent:FireServer(model.Name)
end)

On your server-side, I think you are making a misconception of what player.Character and player:LoadCharacter are supposed to do. .Character gives you the current character, and :LoadCharacter only respawns the character, nothing else is done.

The default control and camera scripts are not dependent on character changes like this, I would only be potentially worried about network ownership.

You should be able to just set player.Character directly on the server without having to use :LoadCharacter, but I am rather unfamiliar with the mechanics of loading a character through setting a property like this. I would believe it to be like so:

local function respawnPlayer(plr, modelName)
    local model = replicatedstorage.Characters:FindFirstChild(modelName)
    print("Model from server is", model)

    local oldModel = plr.Character
    local newModel = model:Clone()

    local oldCFrame = oldModel:GetPrimaryPartCFrame()

    plr.Character = newModel
    newModel.Parent = workspace -- [1] this follows current character loading behavior
    newModel:SetPrimaryPartCFrame(oldCFrame)
    oldModel:Destroy()
end
respawnEvent.OnServerEvent:Connect(respawnPlayer)

[1] Avatar Loading Event Ordering Improvements

39 Likes

Maybe try something like this in a server script:

local model = -- character model
local plr = -- player

Gui.MouseButton1Click:Connect(function()
model.Parent = game.Workspace
model.PrimaryPart.CFrame = plr.Character.PrimaryPart.CFrame -- Teleport model to old character location
plr.Character = model
model.Humanoid.HipHeight = -- required hipheight
end)

You might need something to remove the old character. And the new probably needs the core scripts for things like health and animations adding in too.

2 Likes

Thanks for your time.

So far your script does replace the character BUT there is an issue.

Your script change the model only so all the scripts that were applied to model are removed, no animation and no any custom script. I tried copying all scripts from StarterCharacterScripts folder and it worked fine, so modified your scripts and make it clones all scripts from that folder and put it into character in workspace.

Second issue is, when character dies and respawns, the old model reloads, to prevent it, I’ll have to uncheck CharacterAutoLoads and let server handle it and keep the newmodel in workspace.

But it seems like these approaches doesn’t look stardard to me.

9 Likes

Hi! So I picked up on all of this, and successfully made a player change into a custom character! The only problem is that… Well, It doesn’t pick up any input and send that information over the to the player. So this new custom character cannot move, chat, etc…
I did use your approach and copy down all everything in StarterCharacterScripts, but that only accounts for animations and health… So, I was just wondering how you managed to bind the player scripts to the new custom character?

Maybe It’s because your new character is anchored

Client-Side

local Debris = game:GetService("Debris")

local RS = game:GetService("ReplicatedStorage")
local RE = RS["Remote Events"].Game.AvatarChanged
local Sounds = RS.Sounds

local Module = require(RS.NotificationModule)

local Camera = game:GetService("Workspace").CurrentCamera
local Player = game:GetService("Players").LocalPlayer
local Leaderstats = Player:WaitForChild("leaderstats").avatars
        
local Character
local NewCharacter

local Avatar = "snowman"
local Data = {}

for _, Button in pairs (script.Parent:GetDescendants()) do
        if Button:IsA("TextButton") then
                Button.MouseButton1Up:Connect(function()
                        NewCharacter = Button.Parent:FindFirstChildOfClass("Model")
                        
                        if Leaderstats.inventory:WaitForChild(NewCharacter.Name).Value then
                                Sounds.Click:Play()

                                RE:FireServer(NewCharacter)
                        else
                                Sounds.Wrong:Play()
                                
                                Module.Notify("You don't own this avatar!")
                        end
                end)
        end
end

RE.OnClientEvent:Connect(function()
        Camera.CameraSubject = Player.Character
end)

Server-Side

        local Leaderstats = Player:WaitForChild("leaderstats").avatars
        local Character = Player.Character

        Leaderstats.using.Value = Data.Name
        local NewCharacter = Data:Clone()

        NewCharacter.Parent = game:GetService("Workspace")
        NewCharacter.HumanoidRootPart.CFrame = Character.HumanoidRootPart.CFrame + Vector3.new(0.0, 3.0, 0.0)
        NewCharacter.Name = Character.Name

        Debris:AddItem(Character, 0.5)

        Player.Character = NewCharacter
        Character = NewCharacter
        
        local Folder = script.Player:Clone()
        
        Folder.Parent = Character
        
        Folder.Settings.Sound["Horn Listener"].Enabled = true
        Folder.Settings.Sound.Player.Enabled = true
        
        Folder.Settings.Orientation.Enabled = true
        Folder.Settings.Client.Enabled = true
        
        Folder.Animate.Enabled = true
        Folder.Health.Enabled = true

        REs.Avatar:FireClient(Player)

This is the code I use and it works, just that the player doesn’t respawn for some reason after changing avatars.

5 Likes

This works, but I have another problem. The character in the workspace is named whatever the model name is. It isn’t assigned the new player name.

You have to change the name of the model to the player. Make sure to destroy the old model first.

1 Like