When I am a regular character, the character turns normally (snapping without smoothing) when shift locking or first person locking.
When I turn into a morph into the custom rig, it starts smoothing out which is unintended behavior.
I want to remove this unintended smoothing in shift lock and first person on the custom rig.
Video:
Custom Rig:
rig-with-shift-lock-bug.rbxm (50.3 KB)
Place Where You Can Replicate Bug:
smooth-shift-lock-bug.rbxl (106.4 KB)
MorphHandler (server) script:
--!strict
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local ServerScriptService = game:GetService("ServerScriptService")
local ServerStorage = game:GetService("ServerStorage")
local Workspace = game:GetService("Workspace")
local ServerConstants = require(ServerScriptService:WaitForChild("ServerConstants"))
local characterTemplates = ServerStorage:WaitForChild("Characters")
local function createDisableIsMorphingAttributeFunction(player: Player)
return function()
player:SetAttribute(ServerConstants.IS_MORPHING_ATTRIBUTE, false)
end
end
local function handleChildDescendantInMorph(descendant: Instance, player: Player)
if not descendant:IsA("BasePart") then
return
end
descendant.Anchored = false
descendant.CanTouch = false
if not descendant.CanCollide then
descendant.CanQuery = false
end
descendant.Massless = true
if descendant:IsDescendantOf(Workspace) and not descendant.Anchored then
descendant:SetNetworkOwner(player)
end
end
local function morphPlayer(player: Player, characterTemplate: Model)
player:SetAttribute(ServerConstants.IS_MORPHING_ATTRIBUTE, true)
local disableIsMorphingAttribute = createDisableIsMorphingAttributeFunction(player)
local character = player.Character
if not character then
disableIsMorphingAttribute()
return
end
local currentPivot = character:GetPivot()
local humanoid = character:FindFirstChildOfClass("Humanoid")
if not humanoid then
disableIsMorphingAttribute()
return
end
local rootPart = humanoid.RootPart
if not rootPart then
disableIsMorphingAttribute()
return
end
local newCharacter = characterTemplate:Clone()
newCharacter.Name = player.Name
local newCharacterHumanoid = newCharacter:FindFirstChildOfClass("Humanoid")
if not newCharacterHumanoid then
newCharacter:Destroy()
disableIsMorphingAttribute()
return
end
local newCharacterRootPart = newCharacterHumanoid.RootPart
if not newCharacterRootPart then
newCharacter:Destroy()
disableIsMorphingAttribute()
return
end
newCharacter:SetAttribute(ServerConstants.CURRENT_MORPH_ATTRIBUTE, characterTemplate.Name)
newCharacter.Parent = Workspace
player.Character = newCharacter
task.delay(ServerConstants.DISABLE_IS_MORPHING_DELAY, disableIsMorphingAttribute)
newCharacterRootPart.Anchored = false
newCharacter:PivotTo(currentPivot)
for _, descendant in newCharacter:GetDescendants() do
handleChildDescendantInMorph(descendant, player)
end
end
local function onMorphPartPlayerHeartbeat(morphPart: BasePart, player: Player)
local character = player.Character
if not character then
return
end
local currentMorph = character:GetAttribute(ServerConstants.CURRENT_MORPH_ATTRIBUTE)
if player:GetAttribute(ServerConstants.IS_MORPHING_ATTRIBUTE) or currentMorph then
return
end
local humanoid = character:FindFirstChildOfClass("Humanoid")
if not humanoid then
return
end
local rootPart = humanoid.RootPart
if not rootPart then
return
end
local rootPartYPlanePosition = Vector2.new(rootPart.Position.X, rootPart.Position.Z)
local morphPartYPlanePosition = Vector2.new(morphPart.Position.X, morphPart.Position.Z)
local distance = (rootPartYPlanePosition - morphPartYPlanePosition).Magnitude
if distance > ServerConstants.MORPH_PART_RADIUS then
return
end
local characterTemplate = characterTemplates:FindFirstChild(morphPart.Name)
if not characterTemplate then
return
end
morphPlayer(player, characterTemplate)
end
local function onMorphPartHeartbeat(morphPart: BasePart)
for _, player in Players:GetPlayers() do
onMorphPartPlayerHeartbeat(morphPart, player)
end
end
local function onHeartbeat()
local morphPartsModel = Workspace:FindFirstChild("MorphParts")
if not morphPartsModel then
return
end
local morphParts: { BasePart } = morphPartsModel:GetChildren()
for _, morphPart in morphParts do
onMorphPartHeartbeat(morphPart)
end
end
local function initialize()
RunService.Heartbeat:Connect(onHeartbeat)
end
initialize()