Changing Rig mid-game

Can anyone help me with this?

I want to put two buttons on screen, R15 & R6. Upon clicking them, the player changes rigs mid-game without the need to respawn, reset or whatever.

Obviously what the player is wearing needs to be kept, so applying HumanoidDescription after rig change too.

Also, I gotta mention that this must be server-sided as it is a multiplayer game.

1 Like

ServerScriptService

-- ServerScriptService: RigChangeServerScript

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RigChangeEvent = ReplicatedStorage:WaitForChild("RigChangeEvent")

-- Define R6 and R15 rigs
local R6Model = ReplicatedStorage:WaitForChild("R6")
local R15Model = ReplicatedStorage:WaitForChild("R15")

RigChangeEvent.OnServerEvent:Connect(function(player, rigType)
	-- Ensure the rig type is valid
	if rigType == "R6" or rigType == "R15" then
		-- Clone the desired rig based on rigType
		local newCharacter
		if rigType == "R6" then
			newCharacter = R6Model:Clone()
		elseif rigType == "R15" then
			newCharacter = R15Model:Clone()
		end

		if newCharacter then
			-- Save humanoid description
			local humanoidDescription = player.Character.Humanoid:Clone()

			-- Destroy current character
			if player.Character then
				player.Character:Destroy()
			end

			-- Set the new character as the player's character
			newCharacter.Parent = game.Workspace
			player.Character = newCharacter

			-- Apply saved humanoid description to the new character
			humanoidDescription.Parent = newCharacter
		else
			warn("Rig not defined:", rigType)
		end
	end
end)

R6 Local Script:

-- LocalScript: R6ButtonLocalScript

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RigChangeEvent = ReplicatedStorage:WaitForChild("RigChangeEvent")

script.Parent.MouseButton1Click:Connect(function()
	RigChangeEvent:FireServer("R6")
end)

R15 Local Script:

-- LocalScript: R15ButtonLocalScript

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RigChangeEvent = ReplicatedStorage:WaitForChild("RigChangeEvent")

script.Parent.MouseButton1Click:Connect(function()
	RigChangeEvent:FireServer("R15")
end)

image

But the scripts have problems, obviously, I don’t know how to fix them.

Hey, share the place file, I’ll see what I can do for ya

Appreciate it. Here’s the place:
RigChangePlace.rbxl (92.0 KB)

RigChangePlace.rbxl (66.1 KB)

2 Likes

Amazing! Thank you for the help :slight_smile:

Yee, also, if you want to fix the camera just have like a server to client event, & set the current camera cframe to it’s last position before the rig type changing

-- ServerScriptService: RigChangeServerScript

local Players = game:GetService('Players')
local ReplicatedStorage = game:GetService('ReplicatedStorage')
local RigChangeEvent = ReplicatedStorage:WaitForChild("RigChangeEvent")
local RigFinishedEvent = ReplicatedStorage:WaitForChild("RigFinished")
local GetCameraPositionEvent = ReplicatedStorage:WaitForChild("GetCameraPositionEvent")

-- Function to set the SavedCameraCFrame attribute for a player
local function setupSavedCameraCFrame(player)
	player:SetAttribute("SavedCameraCFrame", nil) -- Initialize as nil
end

-- Set up SavedCameraCFrame attribute for players already in the game
for _, player in ipairs(Players:GetPlayers()) do
	setupSavedCameraCFrame(player)
end

-- Handle players joining the game
Players.PlayerAdded:Connect(function(player)
	setupSavedCameraCFrame(player)
end)

-- Request the camera position from the client
local function requestCameraPosition(player)
	GetCameraPositionEvent:FireClient(player)
end

RigChangeEvent.OnServerEvent:Connect(function(player, rigType)
	-- Check if the player has a character
	if not player.Character then
		return
	end

	-- Request the camera position from the client
	requestCameraPosition(player)

	local humanoid = player.Character:FindFirstChildOfClass("Humanoid")
	if not humanoid then
		return
	end

	local humanoidDescription = humanoid.HumanoidDescription
	if not humanoidDescription then
		return
	end

	local Morph
	if rigType == 'R15' then
		Morph = game.Players:CreateHumanoidModelFromDescription(humanoidDescription, Enum.HumanoidRigType.R15)
	else
		Morph = game.Players:CreateHumanoidModelFromDescription(humanoidDescription, Enum.HumanoidRigType.R6)
	end

	-- Make sure the player's character exists and has a primary part
	local primaryPart = player.Character.PrimaryPart
	if primaryPart then
		Morph:SetPrimaryPartCFrame(primaryPart.CFrame)
	end

	Morph.Name = player.Name
	player.Character = Morph
	Morph.Parent = workspace

	-- Fire the RigFinished event once the rig is loaded
	RigFinishedEvent:FireClient(player)
end)

-- Listen for camera position from client and store it
GetCameraPositionEvent.OnServerEvent:Connect(function(player, cameraPosition)
	player:SetAttribute("SavedCameraCFrame", cameraPosition)
end)

I’ve made a small improvement that will instead use the character in-game instead of loading from player ID and will leave it here in-case someone in the future wants to use this post as help for development :smile:

Edit: Made a camera fix too.

StarterPlayerScripts (CameraFix):

-- LocalScript: RigChangeLocalScript

local Players = game:GetService('Players')
local ReplicatedStorage = game:GetService('ReplicatedStorage')
local GetCameraPositionEvent = ReplicatedStorage:WaitForChild("GetCameraPositionEvent")
local RigFinishedEvent = ReplicatedStorage:WaitForChild("RigFinished")

-- Function to set up SavedCameraCFrame attribute for the local player
local function setupSavedCameraCFrame()
	local player = Players.LocalPlayer
	player:SetAttribute("SavedCameraCFrame", true) -- Initialize with a value indicating that the camera's CFrame is saved
end

-- Set up SavedCameraCFrame attribute for the local player
setupSavedCameraCFrame()

-- Send camera position to the server
local function sendCameraPosition(cameraPosition)
	GetCameraPositionEvent:FireServer(cameraPosition)
end

-- Request the camera position when asked by the server
GetCameraPositionEvent.OnClientEvent:Connect(function()
	local player = Players.LocalPlayer
	local camera = workspace.CurrentCamera
	if camera then
		local cameraPosition = camera.CFrame
		sendCameraPosition(cameraPosition)
	end
end)

-- Apply camera changes when the rig is finished loading
RigFinishedEvent.OnClientEvent:Connect(function()
	local player = Players.LocalPlayer
	local savedCameraCFrame = player:GetAttribute("SavedCameraCFrame")
	if savedCameraCFrame then
		local camera = workspace.CurrentCamera
		if camera then
			-- Continuously check if the camera's CFrame has changed
			local initialCameraCFrame = camera.CFrame
			repeat
				wait()
			until camera.CFrame ~= initialCameraCFrame

			-- Restore both the orientation and position of the camera
			camera.CFrame = savedCameraCFrame
		end
	end
end)
2 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.