Updating CFrame of part relative to other part with BodyMover produces weird behavior, via Heartbeat

  1. What do you want to achieve? I have a humanoid being moved by a BodyPosition mover in a dashing mechanic. I want to briefly spawn a cylinder, and attach position-updating logic to RunService.Heartbeat such that the cylinder follows the unit.

  2. What is the issue? The cylinder spawns in the correct position, and both pieces of my puzzle move. The issue is that the cylinder updates near instantly while the body lags behind by about .4 seconds or something!

Important info:

  • The interaction is server side.
  • I have tried deriving the position from the PrimaryPart and Torso
  • In the gif I’ve provided, I’m using the same method on the client side for the player and it works fine, although it’s connected to RunService.RenderStepped
  • I have tried putting the cylinder creation logic before the dash, and it still moves before the dummy.
  • Whether or not the cylinder is Massless doesn’t matter either
hitbox.positionUpdater = game:GetService("RunService").Stepped:Connect(function()
		hitbox:UpdatePosition()
	end)
function DashHitbox:UpdatePosition()
	if not self.Owner:FindFirstChild("Torso") then return end
	local character = self.Owner
	local rootPart = character.PrimaryPart
	local rootPos = rootPart.CFrame.Position
	local offsetFrame = CFrame.new(rootPos.X, self.Part.Size.Y/2, rootPos.Z)
	self.Part.CFrame = offsetFrame * CFrame.Angles(0, 0, math.rad(-90))
function DashEnemy:Dash()
local mover = Instance.new('BodyPosition')
	mover.MaxForce = maxForce
	mover.P = force
	mover.D = dampening
	mover.Position = offsetFrame.Position
	self.Model.HumanoidRootPart.Anchored = false
	mover.Parent = self.Model.HumanoidRootPart

	self.DashHitbox = Hitbox.new(self.Model)

	game:GetService("Debris"):AddItem(mover, 2)
end

I’m a little stumped, especially considering the same thing is implemented successfully client-side.

2 Likes

Could you run it slower?
What I mean is instead of heartbeat or renderstep use a loop with a wait then add some prints to see what value you have for the positions.

1 Like

It looks a little like a network latency problem. If this sounds correct, how about you make a local script to handle the hotbox rendering on the client? So the targeted player draws his own hotboxes that appear to be in sync.

Unless your problem is not the appearance, but the actual hitbox and you are worried about the impact it will have. I think the only solution is to either hope nobody notices, or do the hitbox client side and trust that nobody takes advantage of it.

1 Like

Hey @RamJoT! Thanks for your time.

Per your suggestion I wrapped the position updating logic inside coroutine.wrap()() with a 0.1 wait. What this produced was similar to the gif in the OP but lower ‘framerate’ in appearance. Still moves before the humanoid.

@JarodOfOrbiter I appreciate you taking the time to respond.

I don’t think it’s a network latency issue. I have my incoming replication lag set to 0 in that gif. Even when turning that setting to 0.4 (higher than what most users will experience, if I understand correctly) the same behavior happens.

1 Like

If you increase the wait for the cylinder does it lag behind?

1 Like

Nope :frowning:

Increasing it to large amounts (.4) will make it sort of just appear slightly after the dash is finished, but it’s not actively traveling along the dash path.

Any amount of time near what makes it function as desired has it moving before the humanoid.

Ok so it it appears to not be a timing problem how about a distance one.
How do you keep the cylinders position in relation to the player?
I am assuming using a calculation between their positions getting the magnitude.
Can you track the magnitude and see how it varies?

The logic for updating the cylinder position is in the OP. I simply update the position of the CFrame’s X and Z coordinates to match that of the HumanoidRootPart of the model it’s tracking. And that’s actually the only place it grabs its info from.

I’m beginning to think there’s something weird going on with BodyPosition instances. I’m going to table this bug for now as it’s not show-stopping, but when I attempt to go at it in the future I’ll probably derive a function to determine the dash and update the position based on the math in Heartbeat to do the movement. Might have to decouple the cylinder from the humanoid.

Hopefully someone will know what’s going on before then, though

1 Like