Issue with client-side collisions

For context, this is for a singleplayer game so trusting the client is entirely ok

So I have a prop script where a prop is lerped every frame to a certain offset of the camera’s CFrame and stays there (its a bit more complicated than that but I wont go into detail). If you need an example of what I’m attempting to do, see the Source engine prop system

Now, this is done on the client so the server does not know this has happened. I know that much. What I am curious about is why the prop, when picked up, does not collide with other parts, since the NetworkOwner of any parts within a certain radius would be set to the client and therefore surely collisions would still register?

Also, is there any way around this? I don’t want to use the server for this because the prop lags behind it’s intended position significantly, which is not great. From what I can tell, using the client is the only way beside fixing it in place and that’s not really what I want this to do

Any help is appreciated,
Thanks.

1 Like

Bumping this as I’m still stumped

Sorry is this a tool your talking about?

No, it’s not. Having it as a tool would not work in this situation, unfortunately.

I want this to be

  • Compatible with several (tens to hundreds) of props per level that are just scattered around
  • Smoothly lerped from the “rest” position to the camera CFrame offset position
  • Collision-based, i.e. if the prop collides with an object ingame while held, the character cannot move past
  • If breakable, able to be broken when being held by the character
  • Throwable through using VectorForces

At least 3 of these, probably all 5, cannot be achieved with tools (to my knowledge).

1 Like

Just to clarify- you’re looking to make a client-sided object fire a server sided .Touched event?

Ok here we go…

So the client triggers a proximity prompt (server)
This triggers a RemoteEvent and also sets the Part0 of a Motor6D to that prop (server)
The client, after being triggered, gets the prop from this Part0 of the Motor6D (client)
The client then lerps this part to an offset of the camera (client)

The issue I have is that collisions don’t register with this part. This is because the server thinks the part is still in it’s rest position, but the client thinks that the part is in the offset of the camera.

This doesn’t make much sense to me, as NetworkOwnership should mean that all collisions within a certain radius is handled on the client, not the server, so the collidable parts should know that the prop is in front of the camera, where the client thinks it is.

I then want to know why this is happening and how to fix it so that collisions do register

Okay, makes sense. Is the part anchored on the server? Anchored parts with network ownership of the client won’t replicate, it only replicates when the part is unanchored. Network ownership just lets the client have control over a certain part’s CFrame and doesn’t affect collisions since those are done in whichever environment the touched connection is created; if it’s in a server script then it will only fire when the server detects a collision, client-sided collisions only detect collisions on the client.

I have two ideas for solving this:
1- First, create an identifier for this part, can be a GUID, number, whatever really as long as there’s a way to identify it from the server when it’s being destroyed on the client. On the client, create a copy of the part, and on the client destroy the first part, but ensure you’re keeping a reference to the identifier. Now, in a remote while the client is “holding” the part, pass the identifier and the cloned part’s CFrame back to the server, and on the server tween or interpolate the part whose identifier matches the one provided by the client’s CFrame to the CFrame provided by the client. This will handle replication for you and give the illusion that the part is actively moving despite being anchored. As for the collision, when the part reaches the “goal” CFrame, use :GetPartsInPart, :GetTouchingParts or some other like method to find if the part is touching any other parts.

2- If you want true collisions, first unanchor the part on the client if it isn’t unanchored already, then fire a remote to the server indicating that the client wants network ownership of the part, unanchor it on the server and give network ownership of this part. The reason you’d want to first unanchor it on the client is to give the illusion of the client “holding” the part instantly. If you’re fine with latency, you can skip that step. Now, the client will have network ownership of the part until they “let go” of it. Once they let go, fire a remote again to give network ownership of the part back to the server. When this happens, you can set the network owner to nil and anchor the part again unless you need it unanchored. This will allow true collisions to occur and they should still be detected by the server because the server can see the CFrame of the part.

Thanks so much! Will try these and get back to you.

FYI, for potential future responses:

  • The part isn’t anchored, physics still need to affect it when in “rest” position, for example from being moved by the player or NPCs.
  • I am attempting to avoid latency, I want the prop to move smoothly with the player not lag behind. I have a system that works already but with latency it’s unbearable.

Just to be clear, with solution 2, I’d need to fire a RemoteEvent from the server to the client to notify that the prompt is triggered and to pass what the part is to the client, then fire a second from client to server to transfer NetworkOwnership of that part, or can NetworkOwnership be given on the prompt trigger?

Depends, if you’re giving network ownership of all parts around the character to that character’s player/client, you wouldn’t really need to rely on a remote event, that remote thing was assuming you were going to dynamically give the client the part and release it (ex. lumber tycoon 2’s part “grabbing” mechanic where you click and drag to move the part) through some way that wasn’t a proximity prompt. This mainly stems from your mention of wanting something performant, so I was assuming you’d let the server do much of the physics handling and let the client move/manipulate the part as needed.

Since you are using a proximity prompt, you wouldn’t need a remote, you could just pass network ownership of the part to the client when the prompt is triggered, this would be better practice if anything because there should be minimal unnecessary communication between the client and server.

That’s right, assuming you want to give network ownership back to the server when the client doesn’t need to change its CFrame anymore. If the client needs network ownership of the part at all times/you’re setting network ownership based on proximity and only proximity, you wouldn’t need that part. Regardless, as long as the client has network ownership of the part, the part shouldn’t lag for the client who is moving the part as they have full control over the CFrame, however it’s totally possible and probably guaranteed that high latency will cause the movements to appear choppy for the server and further choppiness to other clients depending on that other client’s ping. That’s pretty much inevitable though, unless you’re smoothly interpolating each of these parts which could be another performance issue, especially if they’re interpolating hundreds of CFrames many times per second.

That’s what I thought, just wanted to clarify

This doesn’t affect me, this is for a singleplayer game so as long as it looks smooth for the client controlling it, that’s all I care about

Thanks for your help, if I have any issues implementing it I’ll let you know. That’ll have to wait for tomorrow though, it’s getting late for me.

1 Like

I know this was ages ago but I took a small break from this project cause I was getting bored of it, but I’m back to it now.

So what you said works! Force-setting the NetworkOwner seems to be the only way. The problem I now have is that anchored parts are still on the server and the prop still needs to collide with anchored things like walls.

Any solutions for this would be great, if you have them, as my only ones here is to either unanchor everything and weld it all to one singular anchored part, or weld an unanchored collision hull to every single anchored part.

Thanks for your help so far though, I appreciate it massively!

1 Like

As long as one of the parts is unanchored, it should still register the collisions on the server. The only thing, though, is that I believe the touches have to be done by physics so setting the part’s CFrame on RenderStep or some like method won’t work. Instead, something like an AlignPosition with RigidityEnabled should work, although I’m not sure how well it would work in your case. It works with wall collisions as well as anything blocking it will prevent it from going to the mouse’s position.

I’ve made a small demo using this method if you want to take a look, it does register the collisions as well:
collisions.rbxl (38.7 KB)

1 Like

This actually looks perfect for what I want. Just one query, if I have a part (PropPosition) which is constantly lerped to an offset of the camera’s CFrame, then use AlignPosition to align the prop to the PropPosition part, will this still work? (logically I’d say yes, just wanna check)

Yeah it should work as long as you’re making the AlignPosition’s Position property a Vector3. Only thing though is that it will be freely rotating as in my demo so if you want to incorporate the rotational aspect of the CFrame, you could use an AlignOrientation, something like

local rX,rY,rZ = workspace.CurrentCamera.CFrame:ToOrientation()
rX,rY,rZ = math.deg(rX), math.deg(rY), math.deg(rZ)
alignOrientation.Orientation = Vector3.new(rX,rY,rZ)
1 Like

Yeah this works, I still have some stuff to sort out but I think the whole collisions thing is solved now (hopefully!) so I’ll mark your previous one as solution.

Thanks so much for your help, it would have taken me much longer to figure out this solution if you hadn’t mentioned those new constraints.