Unanchored part that is sleeping can't wake up fast enough to react to a hit from a players tool

Hello! I am trying to get an unanchored part to interact better with the tools the players use to hit and control the part. The unanchored part I am talking about is a small black cylinder like a hockey puck. The tool used is a “MeshPart” with the appearance of a hockey stick. The puck is the only unanchored part in the entire game (other than the players and tools.)

Currently, issues can occur in the gameplay where the puck will go right through the stick. This occurs when the puck is sleeping. Sometimes the puck is too slow to become awake; hence, the puck doesn’t respond in time, leaving the stick to go right through the puck. When this happens it can take a few hits at the puck to get it to interact again.

Here is an example of what I am talking about…

With about 15 seconds left in this video you can see it happen with “Awake Parts” visualization on.

Last year I implemented ownership into the game. I added a script into the puck that can detect the player who has their stick closest to the puck, and is within a magnitude of 10. I don’t think my ownership script is causing issues considering this was already happening before I coded the script.

Here is the code I used…

Server script:

local nearestPlayer = nil	
local dist = math.huge		

function FindNearestPlayer()		
	for i,v in pairs(game.Players:GetPlayers()) do
		if v.Character then
			local hockeystick = v.Character:FindFirstChild("2020 Hockey Stick")
			if hockeystick ~= nil then
				hockeystick.Blade.Color = Color3.fromRGB(198,157,99)
				local magnitude = (hockeystick.Blade.Position - script.Parent.Position).Magnitude
				if magnitude < 10 and script.Parent.Anchored == false then
					if magnitude < dist  then	
						dist = magnitude	
						nearestPlayer = v.Name
						script.Parent:SetNetworkOwner(v)
						hockeystick.Blade.Color = Color3.fromRGB(0,255,0)
					end
				end
			end
		end
	end
end

while true do
   wait (0.1) 
   FindNearestPlayer()
end

Other things I have tried that failed:

  • Experimenting with the density of the puck and hockey stick.
  • Experimenting with the other “CustomPhysicalProperties” of the puck and hockey stick.
  • Changing the magnitude in the script from distances that are closer or further distances.
  • Changing the while true do wait times from quicker or longer waits.
  • Disabling the script.
  • Messing with the Legacy body movers in the puck.
  • Changing the Legacy body movers to the new constraint ones.
  • Using a regular part instead of a cylinder.

What I noticed was that the better your internet connection was, the quicker the part wakes up. The issue still could occur with 3 bars of internet, but the issue was less frequent than with 2.

I looked at other forum posts. There was a bunch of them that talked about sleeping part issues. The recommendation in those posts seemed to be to give the sleeping part a slight push using force. Yet, when I tested with this you need to give the puck a large push to keep it awake. This is unrealistic for a ice hockey experience. There can’t be mysterious movements that makes the puck look like it has a mind of its own. Everything else seemed to be about the best ways to handle projectiles or driving vehicles. Didn’t really help much with advice in regards to collisions with a single unanchored part.

It would be nice if anybody could offer any advice to help me out. It isn’t the biggest deal in the world if this issue doesn’t get resolved soon. It’s only a minor problem when you consider in a full server scenario the puck is going to be moving a ton anyways. I am just trying to bring the game experience to the next level, and make the game more inclusive for players who might have a weaker internet and/or a lower end digital device. If there is any way to fix my current script, like putting code, or adding a new script to help with sleeping parts; just let me know. Thank you for reading!

2 Likes

Is the force added in the puck (on touch) added on the client or server. If the ownership of the puck is server sided and you add the force on the client, the puck will not interact. By force I mean bodymovers

Or is this entirely physics based.

I put the Legacy Body Movers into the puck. The concept of the game is pretty much entirely physics based.

. The ownership of the puck is server sided.

1 Like

I had a similar problem with sleeping physics in the past. I just made an intermission that lasted about 30 seconds to allow for the sleeping part to wake up.

This seems to be something roblox missed or hasn’t worked out yet.
I’m sorry I’m not more helpful in this case.

Instead of the awake parts debug, could you enable the “Owners are shown” property and check if the owner of the puck changes by any chance when it is sleeping.

Can confirm that the sleeping part does indeed give ownership. The moment it does that it becomes awake.

1 Like

Something you can try is connecting your FindNearestPlayer to a Stepped loop instead of while. While is more for executing things when a certain condition is met whereas RunService helps you effectively schedule tasks according to a certain time in a frame.

Stepped fires before physics simulation so if you set the network owner of the puck before physics are simulated, it should have around a frame worth of time to make the transfer and change the state of the part between sleeping or awake. Adding a negligible amount of velocity to the part may also help keep it awake because it’ll be actively moving.

Give this a shot.

2 Likes

In regards to your suggestion, isn’t RenderStepped client side only? The script inside the puck is server side. Also isn’t SetNetworkOwner server side only? If this is true I would have to set a remote event that fires every second.

I never said anything about RenderStepped in my post.

That’s what I originally thought. I figured it was Stepped you were talking about, but I couldn’t get my code to work so I took my friends word for it. My apologies.

Here is the code I can’t seem to get to work properly. It works for the first few seconds and then it doesn’t work again for another 20 seconds or so, and it repeats this. I’ll show you with this video…

function FindNearestPlayer()	
	local nearestPlayer = nil	
	local dist = math.huge
	for i,v in pairs(game.Players:GetPlayers()) do
		if v.Character then	
			
			local hockeystick = v.Character:FindFirstChild("GeneralGoalieStick")
			if hockeystick ~= nil then
				hockeystick.BladeTape.Color = Color3.fromRGB(198,157,99)
				local magnitude = (hockeystick.BladeTape.Position - script.Parent.Position).Magnitude
				if magnitude < 50 and script.Parent.Anchored == false then
					if magnitude < dist  then	
						dist = magnitude	
						nearestPlayer = v.Name
						script.Parent:SetNetworkOwner(v)
						hockeystick.BladeTape.Color = Color3.fromRGB(0,255,0)
					end
				end
			end

			local hockeystick2 = v.Character:FindFirstChild("Hockey Stick")
			if hockeystick2 ~= nil then
				hockeystick2.blade.Color = Color3.fromRGB(198,157,99)
				hockeystick2.blade1.Color = Color3.fromRGB(198,157,99)
				local magnitude = (hockeystick2.blade.Position - script.Parent.Position).Magnitude
				if magnitude < 50 and script.Parent.Anchored == false then
					if magnitude < dist  then	
						dist = magnitude	
						nearestPlayer = v.Name
						script.Parent:SetNetworkOwner(v)
						hockeystick2.blade.Color = Color3.fromRGB(0,255,0)
						hockeystick2.blade1.Color = Color3.fromRGB(0,255,0)
						print 'Given ownership'
					end
				end
			end
		end
	end
end

game:GetService('RunService').Stepped:Connect(function()
FindNearestPlayer()	
end)

This is my first time ever using Stepped in a script, so sorry if I didn’t do this right.

No, that should be correct, but it seems like the problem got even worse. I don’t know whether it’s because FindNearestPlayer is expensive, or because Stepped is frame dependent whereas while waits for the code to finish before the next iteration begins or if this is just something impossible to cure. I haven’t quite worked with physics-dependent games.

There is one point I don’t see addressed, which is honestly my last bastion for hoping to contribute anything and that’s to apply a negligible amount of Velocity to the puck so it’s always, in some regard, actively moving but not enough to be “seen” per se.

That’s my final suggestion. If this doesn’t work, I haven’t a clue. Sorry.

1 Like

Thank you for your advice. I definitely will experiment with velocity. It has always been a battle to make “physics-dependent” games on Roblox since 2010. I have seen significant improvement throughout the years. I hope there is more physics updates to come next year so I can strive to take this game to the next level. I appreciate the recommendations you gave me though. If I discover something significant that helps with collision issues, I will let everybody know.

2 Likes

I found out this might not be from the puck falling asleep. Why? Well because I tested with “Allow Sleep” disabled. After testing, I can now confirm the issue still occurs. I started experimenting with my gameplay I used in 2019 and everything was working so much better than my new gameplay for 2020. After hours of testing I think I finally figured out what could actually be causing all of this in the first place. It’s the new rig I created. For some reason when you make this rig as a “StarterCharacter” the collisions significantly decrease in performance.

Also I revisited @colbert2677’s idea of RunService.Stepped and found out I set the collisions groups incorrectly in the server I was testing on. :man_facepalming:

Unfortunately, it made no difference despite running correctly. Here is the current script in the puck now days…

function FindNearestPlayer()	
	local nearestPlayer = nil		
	local dist = math.huge		
	
	for i,v in pairs(game.Players:GetPlayers()) do
		if v.Character then
			local hockeystick = v.Character:FindFirstChild("Hockey Stick 2")
			if hockeystick ~= nil then
				--hockeystick.blade.Color = Color3.fromRGB(198,157,99)
				--hockeystick.blade1.Color = Color3.fromRGB(198,157,99)
				local magnitude = (hockeystick.Hitbox.Position - script.Parent.Position).Magnitude
				if magnitude < 6 and script.Parent.Anchored == false then
					if magnitude < dist  then	
						dist = magnitude	
						nearestPlayer = v.Name
						script.Parent:SetNetworkOwner(v)
						--hockeystick.blade.Color = Color3.fromRGB(0,255,0)
						--hockeystick.blade1.Color = Color3.fromRGB(0,255,0)
					end
				end
			end
					
			local hockeystick = v.Character:FindFirstChild("2020 Hockey Stick")
			if hockeystick ~= nil then
				local magnitude = (hockeystick.Blade.Position - script.Parent.Position).Magnitude
				if magnitude < 6 and script.Parent.Anchored == false then
					if magnitude < dist  then	
						dist = magnitude	
						nearestPlayer = v.Name
						script.Parent:SetNetworkOwner(v)
					end
				end
			end
				
			local hockeystick = v.Character:FindFirstChild("Hockey Stick")
			if hockeystick ~= nil then
				local magnitude = (hockeystick.Blade.Position - script.Parent.Position).Magnitude
				if magnitude < 6 and script.Parent.Anchored == false then
					if magnitude < dist  then	
						dist = magnitude	
						nearestPlayer = v.Name
						script.Parent:SetNetworkOwner(v)
					end
				end
			end
		end
	end
end


game:GetService('RunService').Stepped:Connect(function()
FindNearestPlayer()	
end)

The script has ownership for each stick that I have tested with over the last couple of days. All sticks had the same result depending on what rig I was using. All testing was done with the “Allow Sleep” disabled. It doesn’t matter what option you choose, allowing sleep still had the exact same result.

I set the Default R15 rig with the Robloxian 2.0 Package and set it as a StarterCharacter (copy and pasted the model of my user.) This seemed to be the most successful result. Proven by the video below…

It also important to note the behavior from the physics displayed in the video above is the same when I didn’t set the Default R15 rig as a StarterCharacter. I was just testing to make sure StarterCharacter wasn’t the problem (which it wasn’t.)

This is what it looks like with my new rig I made set as a StarterCharacter.

As you can see, there is a major difference. The puck even went through the glass at the end there. It just seems like the performance is different when it uses this rig for whatever reason.

An idea I got for testing is trying out some random free model R15 rigs and see if the issue occurs with those rigs as well. I am curious to see the results from that.

Another idea I have is possibly changing body parts of the original character to the ones from the rig I made. The issue with this though is the Motor6D’s didn’t end up at the proper spots and they look improper on the character. You can see the script I used for that here…

local remoteevent = script.Parent:WaitForChild("RemoteEvent")
local ss = game.ServerStorage
local rig = ss:WaitForChild("Bob")

remoteevent.OnServerEvent:connect(function(player)
	local char = player.Character
	local humanoid = char:FindFirstChild("Humanoid")
	humanoid:SetStateEnabled(Enum.HumanoidStateType.Dead, false)
	
	if char then
		if not humanoid then return end
			for _, v in ipairs(rig:GetChildren()) do		
				if v:IsA("BasePart") and v.Name ~= "Part" and v.Name ~= "HumanoidRootPart" and v.Name ~= "Visor" then --hrp
					humanoid:ReplaceBodyPartR15(Enum.BodyPartR15[v.Name], v:Clone()) --:Clone()
				end
			end	
		end

		char.Humanoid:BuildRigFromAttachments()
		char.Humanoid.HipHeight = 2.5
		humanoid:SetStateEnabled(Enum.HumanoidStateType.Dead, true)
end)

I have no idea where to go next other than keep experimenting with other rigs. I could just use the Robloxian 2.0 and call it a day, but I’m determined to use the character that looks more like a hockey player. It would be a disappointment if a physics issue with the rig I created was the reason I couldn’t use it for my game. If anyone has any idea how to fix the collisions with this rig, fix the Motor6D locations of my body morphing, and/or have other ideas on how to fix anything mentioned above let me know.

Cheers!

1 Like

I have been following your topic here, since you first posted, as I find it an interesting issue / problem, and have two comments:

1)
Looking at your latest video, the one that is 25 seconds long, I am starting to think that your issue could be due to “too small collision-boxes”, or perhaps of “too large displacement of collision-boxes between the physics-calculated frames.”

Maybe the video does not have enough ‘high frame rate’ to show it correctly, but to me, when looking from timestamp 10s through to 14s, it could look like the hockey stick’s blade’s collision-box just isn’t touching/hitting the puck’s collision-box, when doing a fast rotation. - It basically “phase through” the puck.

Have you compared your older vs. newer hockey stick’s blade’s collision-boxes sizes?

Relying on game-engine physics calculations using fast moving collision-boxes that are slim/tiny, will always be a problem, due to the time between frames.

From ‘Collision detection’ article on Wikipedia:

[…] On the other hand, a posteriori algorithms cause problems in the “fixing” step, where intersections (which aren’t physically correct) need to be corrected. Moreover, if the discrete step is too large, the collision could go undetected, resulting in an object which passes through another if it is sufficiently fast or small. […]

Perhaps you need to look into “helping” the physics calculations, in the situations where puck is close to the hockey stick and when player-character performs fast movements and/or rotations, then explicitly script a “push the puck”-event?

2)
Seeing your first post’s function of FindNearestPlayer, and then now the newer implementation, they, to me, do not look optimal, as they will, in worst case, change network-ownership multiple times to the next-then-next-then…-nearest player within just the one for-loop.

So I took some time to experiment with refactoring the code, and produced the following.

This ensures, that there won’t be any excess calls to SetNetworkOwner, also when the nearest player has not changed since last Stepped execution. - I also reduced the “duplicated code”, and added a SetHockeyStickColor function (see further below).

(Disclaimer: I have not actually run this code, due to not having any props/objects in Workspace)

local HockeySticks = {
	["Hockey Stick 2"]		= { defaultColor = Color3.fromRGB(198,157,99), nearestColor = Color3.fromRGB(0,255,0) },
	["2020 Hockey Stick"]	= { defaultColor = Color3.fromRGB(198,157,99), nearestColor = Color3.fromRGB(0,255,0) },
	["Hockey Stick"]		= { defaultColor = Color3.fromRGB(198,157,99), nearestColor = Color3.fromRGB(0,255,0) },
}

local function FindNearestHockeyStick(puckPosition)
	-- Structure containing several properties, that will be returned from this function
	local nearest = {
		distance = 6,	-- Distance must be less than this, to be even considered
		player = nil,
		hockeyStickObj = nil,
	}
	
	local hockeyStickObj, magnitude
	
	for _,player in ipairs(game.Players:GetPlayers()) do
		if player.Character then
			for hockeyStickName,_ in pairs(HockeySticks) do
				hockeyStickObj = player.Character:FindFirstChild(hockeyStickName)
				if hockeyStickObj then
					break
				end
			end
			
			if hockeyStickObj then
				if nil ~= hockeyStickObj.Hitbox then
					magnitude = (hockeyStickObj.Hitbox.Position - puckPosition).Magnitude
				else
					magnitude = (hockeyStickObj.Blade.Position - puckPosition).Magnitude
				end
				if magnitude < nearest.distance then
					nearest.distance = magnitude
					nearest.player = player
					nearest.hockeyStickObj = hockeyStickObj
				end
			end
		end
	end
	
	return nearest
end

-- Structure containing the current player (if any) and hockeystick, that is closest to the puck
local currentNearest = {
	player = nil,
	hockeyStickObj = nil,
}

local function SetPuckOwnershipToNearest(puck)
	local nearest = FindNearestHockeyStick(puck.Position)
	
	-- Has nearest player changed, since last check?
	if nearest.player ~= currentNearest.player then
		-- Reset blade color of the previous nearest hockeystick
		SetHockeyStickColor(currentNearest.hockeyStickObj, "defaultColor")
		
		-- Update structure to the new nearest player
		currentNearest = nearest 
		
		-- Update network owner. Will automatically set to server (i.e. `nil`), if there is no nearest player
		puck:SetNetworkOwner(currentNearest.player) 
		
		-- Set blade color of this new nearest hockeystick
		SetHockeyStickColor(currentNearest.hockeyStickObj, "nearestColor")
	end
end

--
local puck = script.Parent

game:GetService("RunService").Stepped:Connect(function()
	if puck.Anchored == false then
		SetPuckOwnershipToNearest(puck)
	end
end)

This is the function used, to update a hockey stick object’s color:

local function SetHockeyStickColor(hockeyStickObj, colorFieldName)
	if not hockeyStickObj then
		return
	end

	local hockeyStickColors = HockeySticks[hockeyStickObj.Name]
	if not hockeyStickColors then
		error(("Hockeystick with name '%s' was not defined in `HockeySticks` table"):format(hockeyStickObj.Name))
	end
	
	local newColor = hockeyStickColors[colorFieldName]
	if not newColor then
		error(("Field `%s` was not defined for element '%s' in `HockeySticks` table"):format(colorFieldName, hockeyStickObj.Name))
	end
	
	if nil ~= hockeyStickObj.blade then
		hockeyStickObj.blade.Color = newColor
	end
	if nil ~= hockeyStickObj.blade1 then
		hockeyStickObj.blade1.Color = newColor
	end
end
1 Like

1.) How can you explain the first video though? It was working really well. I think you are on the right track though. It does seem like sometimes the physics engine can’t calculate fast enough to respond to the speed the player hits the puck. How come this happens more frequent with certain rigs than others though? I have tested with all sorts of shapes and sizes. I tried big blades, small blades, big pucks, small pucks. I also tried wedges, regular parts, cylinders. I tried different rigs as well. it doesn’t seem to make a difference.

I created a place for everyone to try out my old hockey stuff. It’s for anybody to get a feel of how the physics respond to the player whacking at the puck with a tool. Feel free to take anything in that place for yourself and create your own tests and experiments. I got all sorts of unique pucks and hockey sticks in it. It also includes all the ownership scripts we have tested with up to this point. Also it has the rig that I have been explaining that works even worse than the Default R15 Robloxian 2.0 rig.

A ““ push the puck ”-event” script is something I will consider. I am worried it might make it too difficult to get the appropriate power on the shots needed because of the specific force that will always be applied to the puck. The puck won’t be able to accelerate appropriately.

2.) I tried out the script you made and the puck was stuttering when in motion. I had a similar thing like that happen when I set the magnitude of the puck to a higher number. The higher the magnitude, the more the puck started to stutter when in motion.

1)
I took a quick look at what you have shared, though could not play it via Roblox Studio due to animations failed to load. So equipped hockey sticks never reached the ice floor.

Playing the place online, I found best results with the largest ‘2011 Puck’, though there were still issues when doing fast rotations/movements of hockey stick attempting to push the puck.

I see that the physical sizes of the younger puck objects, have become smaller, to the point of 0.6 x 0.28 x 0.6, which is a very tiny object, considering physics calculations.

Perhaps make it 1 x 0.5 x 1 (or larger), and then instead scale the mesh part down, so it visually looks smaller than what it is. - Yes this will make it look like the hockey stick blade does not directly touches the puck, but it should help the physics calculations a bit more, to detect when puck and blade (their larger) collision-boxes intersect.

2)
Regarding the stuttering of the puck, that is probably caused by switching network-ownership very often. - When ownership changes, some synchronization of “who knows what properties-and-values” needs to occur, which, depending on network-latency and such, will take some fractions of a second to complete.

I do not know what other ‘magnitude’ you are referring to, if it is not the .Magnitude distance calculation in the OwnershipScript script.

3)
I also noticed that CollisionGroupId for the pucks and hockey sticks were set to not be zero, though the pucks has value ‘3’, where as the hockey sticks have ‘5’.

I don’t see you mentioning having experimented with collision-groups, so I am a bit confused as of why the CollisionGroupId properties are set as they are.

Though it gave me an idea; what if there were two pucks in the game. One visible normal sized puck, and another invisible much larger puck.

The visible puck should be set to only collide with the ice/walls/goals, never with players or hockey sticks, and must “follow closely” the invisible larger puck. Some fancy scripting or perhaps a short rope-constraint will be needed to make that happen.

For the invisible and larger puck, this is the actual one that can collide with anything. - Having a larger collision-box (even when it is invisible) helps the physics-engine to better determine when objects collide.

1 Like

A relatively simple solution would be to trick the game into not letting the puck sleep. You could do this by setting velocity to be non zero on Heartbeat I believe:

local RunService = game:GetService("RunService")
RunService.Heartbeat:Connect(function()
	puck.Velocity = Vector3.new(math.max(math.abs(puck.Velocity.X), 0.01) * math.sign(puck.Velocity.X), math.max(math.abs(puck.Velocity.Y), 0.01) * math.sign(puck.Velocity.Y), math.max(math.abs(puck.Velocity.Z), 0.01) * math.sign(puck.Velocity.Z))
end)

This should stop physics from sleeping for the puck since it should always be simulating physics. Since it’s an important object to not have sleeping this kind of makes sense to do and it shouldn’t impact performance at all although it might be considered a little hacky.

3 Likes

Seemed like a good idea. I tried it out, and there was three noticeable issues.

  • The pucks velocity was delayed. I am worried it might be too noticeable for the players.
  • Also if you watch the video you can see the puck doesn’t always respond to the collisions.

  • Finally, when I checked with the “Awake Parts” visualization it was showing that the puck was still falling asleep.

1.) My bad! I didn’t even think of that. At least you were still able to try it out online. I agree that the “2011 Puck” probably had the best reaction to the collisions. It still wasn’t 100% perfect though.

As the years went by I tried to reduce the size of the puck to make it seem more realistic. Now it might be too small though. I might make the puck slightly bigger.

I am also considering to do the mesh illusion method you mentioned where you “scale the mesh part down”. I’ll get some players to try it out and see if they would be comfortable with the puck not being directly on the blade.

2.) I figured it was along the lines of network ownership. Would there be a way to edit the script so that it could decrease the amount of stuttering?

For the magnitude I was talking about the calculation between the distance of the stick blade and the puck…

`local magnitude = (hockeystick.blade.Position - script.Parent.Position).Magnitude`
if magnitude < 5 and script.Parent.Anchored == false then

When you change the magnitude distance from “<5” to say something like “<20” the puck stuttered often because more players were within range of the puck, so the script would be changing who gets ownership of the puck more often. When the distance was less than 5 only the players really close to the puck could win over the ownership. It would stutter when the players fight for the puck, but it was less noticeable because the players and their sticks were blocking the view of the puck. It looked more natural.

The downside to this is that the passing took a hit because the ownership can’t transfer quick enough to the receiving player who needs the physics to get the puck to collide properly with his stick. Five magnitude distance usually isn’t enough time for the ownership to transfer; that is unless you make a slow enough pass to the other player. It also depends on internet connection and computer ability of course.

3.) The collisions groups are something that was critically needed for the 2019 gameplay.

0- Default: Everything else.
1- TheIce: To identify the ice, the lines on the ice, the circles, logos, etc.
2- DontTouchTheIce: For everything I don’t want to collide with the ice.
3- ThePuck: To identify all the pucks in the game.
4- DontTouchThePuck: For everything I don’t want to collide with the puck.
5- TheSticks: To identify all tools used by the characters.

All the collision groups mix and match for the most comfortable experience for the user. It helps prevent players from getting stuck, from players accidentally kicking the puck and making it fling into oblivion, and tools getting stuck.

Every player that joins the game has their HumanoidRootPart’s set to CollisionGroupId 3. It uses the following code…

local puckGroup = "ThePuck"
local hrp = player.Character:WaitForChild("HumanoidRootPart")

for _,v in pairs(game:GetService("PhysicsService"):GetCollisionGroups()) do
	if v.name == "DontTouchThePuck" then
		PhysicsService:SetPartCollisionGroup(hrp, v.name)
	end
end

The purpose for this is to prevent players from flinging the puck into space when they touched it with their character. Worked like a charm.

Finally, to your last recommendation. I love this idea. I am definitely going to give this a try. I think first approach would be to try a weld. I’ll let you know how it goes.

Not sure if sleep is really your issue, but here’s what I did to address it.

I’m rotating a cannon connected to a motorised hinge constraint with left and right “buttons” (just parts) on the gun. I’m using the UserInputService in a localscript to work out when the user is holding the left mouse button (and when they release) and sending this via a bindableEvent to a server side buttonControl script which moves/stops the hinge by setting the AngularVelocity (i.e. to 1, 0 or -1).

This works fine for the most part unless I release and click again around 0.5 second later. In that case I can see that the angular speed of the hinge is getting set but the hinge doesn’t move. Walking up to the cannon while still holding the mouse button wakes the gun up and it starts moving. So it’s a sleep issue. I can verify this by highlighting awake parts in settings.

My fairly dodgy workaround for this was to make a new part called Waker and weld it to the gun. Make it transparent and turn off collisions. Add a bindable event and a script. In the script add a loop that toggles the Waker’s Massless attribute every 0.4 seconds on a loop (20 loops seems long enough for my purposes). Then just trigger the Waker’s bindable event when I click the left/right buttons on the cannon. Other attributes like Anchored have same effect, i.e. they wake the physics for that object and any attached to it. Massless seemed the most innocuous for a small object.

Since the buttons are used by the player for fine left and right aiming they are generally clicked reasonably rapidly, hence I encounter the sleep issue if the next click is within about 0.5 seconds of the last. Using this method I keep the cannon awake for a longer period than is normal and it successfully responds to all my rapid clicks i.e. setting the AngularVelocity actually has an effect every time. I really hate this workaround but either the sleep settings are just too aggressive or I’m doing something in a dumb way. Until there’s a fix, this is what I’ll do.

In your case, you could try using this method to keep the puck awake all the time instead of just for a short period like I am. Might not be your issue but worth a try. You might want to set the Waker’s Density way down so it doesn’t affect the puck too much when it’s not Massless.

1 Like