#character pivot position after swapping characters

1 messages · Page 1 of 1 (latest)

spiral nexus
#

i am attempting to replicate the genshin character swapping mechanic, but the issue is that after swapping characters, the player's pivot point locks in place and no longer follows the model (video). this breaks future swaps as well as parkour mechanics, and i don't know why. vaulting also seems to reset the pivot point. how can i fix this?

client:

Switch = function() events.Combat.Switch:FireServer(chr:GetPivot()) end,
#

server:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")
local events = ReplicatedStorage.Events

local CharacterStats = require(ServerStorage.CharacterStats)
local PlayerWatcher = require(ServerStorage.PlayerWatcher)

local function Transfer(old, new)
    for _, i in pairs(old:GetChildren()) do
        if i:IsA("BaseScript") then
            i.Parent = new
        end
    end
end

events.Combat.Switch.OnServerEvent:Connect(function(plr, location: CFrame)
    local chr = plr.Character
    local hum = chr:FindFirstChildOfClass("Humanoid")
    local Player = PlayerWatcher:GetPlayer(plr)
    if not Player.CanSwitchCharacters then return end
    
    PlayerWatcher:Update(plr, "CanSwitchCharacters", false)
    PlayerWatcher:Update(plr, "CurrentCharacter",  (Player.CurrentCharacter % 3) + 1)
    plr:SetAttribute("Switching", true)
    
    task.delay(1, function()
        PlayerWatcher:Update(plr, "CanSwitchCharacters", true)
    end)
    
    local NextName = CharacterStats.Characters[Player.CurrentCharacter].Name
    local found: Model = ServerStorage.Characters:FindFirstChild(NextName == "Player" and plr.Name or NextName):Clone()
    
    local ScriptHolder = Instance.new("Folder")
    ScriptHolder.Parent, ScriptHolder.Name = script, plr.UserId
    hum.Parent = script
    Transfer(chr, ScriptHolder)
    for _, ToArchive in pairs(found:GetDescendants()) do ToArchive.Archivable = true end
    found:PivotTo(location)
    chr:ClearAllChildren()
    for _, instance in pairs(found:GetChildren()) do instance.Parent = chr end
    hum.Parent = chr
    Transfer(ScriptHolder, chr)
    found:Destroy()
    ScriptHolder:Destroy()
    
    plr:SetAttribute("Switching", false)
end)
#

this is the vaulting logic as well, i don't know what could be reseting the pivot point to the new location here

Jump = function()
        if not plr:GetAttribute("CanJump") then return end
                
        if plr:GetAttribute("Sprinting") then
            local hrp: Part = chr:WaitForChild("HumanoidRootPart")
            local lv = hrp.CFrame.LookVector
            
            local params = RaycastParams.new()
            params.FilterDescendantsInstances = {chr}
            params.FilterType = Enum.RaycastFilterType.Exclude
            
            local step = 0.5
            local dLen = 1.26
            local studs = 8
            
            local p = hrp.Position - Vector3.new(0, dLen, 0)
            local VaultCheck = workspace:Raycast(p, lv * (studs - 2), params)
            visualize.Line(p, VaultCheck and VaultCheck.Position or p + (lv * (studs - 2)))
            
            local VaultCheck2 = workspace:Raycast(p + Vector3.new(0, dLen, 0), lv * (studs - 2), params)
            visualize.Line(p + Vector3.new(0, dLen, 0), VaultCheck2 and VaultCheck2.Position or (p + Vector3.new(0, dLen, 0)) + (lv * (studs - 2)))
            if VaultCheck2 and VaultCheck2.Position then hum.JumpPower = 50 return end
            
            if VaultCheck and VaultCheck.Position then
                visualize.Point(VaultCheck.Position)
                
                local CheckPart = Instance.new("Part")
                CheckPart.CanCollide, CheckPart.CanTouch, CheckPart.CanQuery = false, false, false
                CheckPart.Transparency = 1
                CheckPart:PivotTo(CFrame.new(VaultCheck.Position + Vector3.new(0, dLen, 0)) * hrp.CFrame.Rotation)
                CheckPart.Rotation = hrp.Rotation
                CheckPart.Parent = workspace
                
                local CheckPos = CheckPart.Position
                visualize.Point(CheckPos)
                
                local CanVault, endPos

#
for i = 0, studs / step, 1 do
                    local sPos = CheckPos + lv * i * step
                    local ray = workspace:Raycast(sPos, lv * step, params)
                    local ePos = ray and ray.Position or sPos + lv * step
                    visualize.Line(sPos, ePos)

                    if ray and ray.Position then
                        CanVault, endPos = true, ePos
                        visualize.Point(ePos)
                        break
                    else
                        local sPos2 = ePos
                        local down = workspace:Raycast(sPos2, Vector3.new(0, -dLen, 0), params)
                        local ePos2 = down and down.Position or sPos2 + Vector3.new(0, -dLen, 0)

                        visualize.Line(sPos2, ePos2)

                        if not down then
                            CanVault, endPos = true, sPos2
                            break
                        else visualize.Point(ePos2); continue end
                    end
                end

                if CanVault and endPos then
                    plr:SetAttribute("CanJump", false)
                    plr:SetAttribute("Vaulting", true)
                    chr:PivotTo(CheckPart:GetPivot())
                    local VaultOver, elapsed = nil, 0
                    VaultOver = RunService.Heartbeat:Connect(function(dt)
                        if not hrp then VaultOver:Disconnect() return end
                        elapsed += dt * 5
                        if elapsed > 1 then VaultOver:Disconnect() end
                        chr:PivotTo(CheckPart.CFrame:Lerp(CFrame.new(endPos) * CheckPart.CFrame.Rotation, elapsed))
                    end)
                    task.delay(0.5, function()
                        plr:SetAttribute("CanJump", true)
                    end)
                else hum.JumpPower = 50 end
                CheckPart:Destroy()
            else hum.JumpPower = 50 end
        else hum.JumpPower = 50 end
    end,
cinder owl
#

i'd imagine you could duplicate the new charactermodel, set its pivot to the same as the current player character, change the model name, then just do

player.Character = *yourcharactermodel*
#

afterwards delete the old character model

spiral nexus
#

that would trigger stuff that happens on .CharacterAdded

torpid timber
#

*selecting

#

it seems like you arent

#

try selecting it again after switching

spiral nexus
torpid timber
spiral nexus
cinder owl
torpid timber
#

ah

spiral nexus
#

that would also reset the gui

cinder owl
spiral nexus
#

what about the red vignette that appears on death

cinder owl
spiral nexus
#

the vignette that appears for like 1 frame upon death would ruin the immersion

cinder owl
solemn idol
# spiral nexus i am attempting to replicate the genshin character swapping mechanic, but the is...
#

i mean you would prob use plr.Character = newModel

#

that way roblox camera and stuff would rebind to the new model

spiral nexus
cinder owl
solemn idol
#

i remember making a custom death vignette last time

#

heck it was 10x better because of custom tweening

cinder owl
spiral nexus
spiral nexus
solemn idol
waxen joltBOT
#

studio** You are now Level 5! **studio

cinder owl
spiral nexus
#

its more convenient to have the advanced stuff in one event

#

rather than having to change everything else

solemn idol
spiral nexus
#

i just said that making a custom vignette would be more work since all other systems will need to be rework

spiral nexus
#

one line.

#

one

#

fucking line

#
chr.PrimaryPart = chr:WaitForChild("HumanoidRootPart")
#

💔

solemn idol
#

oh that worked?

#

W