I have found a bug in my game which seems to be caused by changes in physics ownership. Basically I am creating an NPC on the server and then telling it to follow a path of Vector3s. This works fine to start with but as soon as a player comes near enough that the physics ownership transfers from the server to the client, the humanoid stops walking. If the player moves away and the server regains ownership, the humanoid continues walking again.
Here is a video which demonstrates this using the studio physics option “AreOwnersShown”:
And here is the code which makes the NPC and then tells it to walk around:
function class:makeCharacterJoints(model)
local joints = {}
joints.root = weld("RootJoint", model.HumanoidRootPart, model.Torso)
joints.neck = weld("Neck", model.Torso, model.Head)
joints.leftHip = weld("Left Hip", model.Torso, model["Left Leg"])
joints.rightHip = weld("Right Hip", model.Torso, model["Right Leg"])
joints.leftShoulder = weld("Left Shoulder", model.Torso, model["Left Arm"])
joints.rightShoulder = weld("Right Shoulder", model.Torso, model["Right Arm"])
joints.eyes = weld("Eyes", model.Head, model.Eyes, nil, model.Eyes.CFrame:toObjectSpace(model.Head.CFrame))
return joints
end
function class:createNpc(name, walkSpeed)
local npc = {}
npc.character = assets.Character:Clone()
npc.character.Name = name
npc.humanoid = npc.character.Humanoid
npc.joints = self:makeCharacterJoints(npc.character)
npc.humanoid.WalkSpeed = walkSpeed or 12
self:changeEyeColor(npc.character, clothes.eyeColor)
self:changeSkinColor(npc.character, clothes.skinColor)
local function reverseTable(init)
local reversed = {}
for i, v in next, init do
reversed[#init - i + 1] = v
end
return reversed
end
function npc:startPath(path, loopMode)
for i, node in next, path do
if node.dur then
wait(node.dur)
end
local torsoPos = self.character.Torso.Position
repeat
torsoPos = self.character.Torso.Position
self.humanoid:Move((Vector3.new(node.pos.X, torsoPos.Y, node.pos.Z) - torsoPos).unit)
wait(.1)
until (Vector3.new(node.pos.X, torsoPos.Y, node.pos.Z) - torsoPos).magnitude <= 5
end
if loopMode == "Loop" then
npc:startPath(path, loopMode)
elseif loopMode == "PingPong" then
npc:startPath(reverseTable(path), loopMode)
end
end
function npc:spawn(pos)
self.character.Parent = workspace
self.character:MoveTo(pos)
game.ReplicatedStorage.Events.Animate:FireAllClients("Play", npc.character, "Idle", clock.Value)
end
npc.humanoid.Running:connect(function(speed)
if speed > 0 then
game.ReplicatedStorage.Events.Animate:FireAllClients("Crossfade", npc.character, "Walk", clock.Value, 0.2)
else
game.ReplicatedStorage.Events.Animate:FireAllClients("Crossfade", npc.character, "Idle", clock.Value, 0.2)
end
end)
return npc
end
....
local path = {
{
pos = Vector3.new(10, 3, 10)
},
{
pos = Vector3.new(30, 3, 10)
},
{
pos = Vector3.new(30, 3, 30)
},
{
pos = Vector3.new(10, 3, 30)
},
}
local bob = CharacterHandler:createNpc("Bob")
bob:spawn(path[1].pos)
bob:startPath(path, "Loop")
Lastly, here is a repro place for the mods (contains some game assets, not showing to general public)
EDIT: Just found out this was already reported here but this deserves a bump anyways!