Raycasting on the server prevents the exploit (if OP is using raycasting to detect if anything is being hit) of parts being spammed into 1 position.
Another issue is you keep triggering your SendPlacementStatus connection every time the button is pressed. You are constantly creating more and more connections… and I was writing this I just found out your issue.
You are creating insane amounts of connections every time the button is pressed. These connections are causing major client desyncs that start slow but end off high. You need to rewrite and properly organize your code as I can’t understand what goes where.
No, I only did a few tower defense systems (Enemy, placement system) and I’m sure no other scripts affect the baseplate in any way (because the entire project is just those 2 systems as of now)
Plus the baseplate is automatically created in the template
EDIT:
This issue happens when I place the tower for the 1st time.
You don’t need to be ray-casting on the server as it does not make any sort of difference. To prevent parts being spammed into one position you can attempt implementing something like a cool down and you can save the coordinates the player has previously placed to verify it’s a legitimate position, as-well as having any other checks.
Something like this:
function BuildUtil.GetMousePosition(IgnoreList)
local NewRay = Ray.new(Camera.CFrame.Position, (Mouse.Hit.Position - Camera.CFrame.Position).Unit * 300);
local _, Position, SurfaceNormal = workspace:FindPartOnRayWithIgnoreList(NewRay, IgnoreList);
local EditedPosition = Position + SurfaceNormal;
return EditedPosition.X, EditedPosition.Y, EditedPosition.Z
end
You can use a method like that in some utility module to get X, Y, Z coordinates from the mouse hit. You can then send those coordinates to the server and the server can go through multiple checks and whatever you need before placing it. (You can probably use Workspace:Raycast() instead) One of the main things involved in those checks Is the os.time() to check they are not constantly spamming the remote, as-well as doing that on the client. As far as I know, exploits don’t really matter when it comes to ray-casting on the server rather than the client? Maybe I’m wrong…?
You can also put a whitelist in the RaycastParams and only set it to some sort of build-plot, which saves you from having to check the result if it hit a Baseplate.
In a game I’m currently working on, it uses a system like this, you can check the game out: Monster Blast! - Roblox
You definitely don’t need a “SendPlacementStatus” remote to tell the client if they’re able to place, as you are able to do those types of checks on the client.
(Let me note that you can actually place the block on the client first before you fire the remote to tell the server you want to place a block, and then destroy that block in 1-2 seconds. This helps make network lag look like nothing with placement systems)
(The logic I’ve just explained is all used in the game linked)
Note that most of the work for placement systems is the actual dragging of the object. You want it to be updated wherever you hover, and then when you click send those coordinates to the server to verify and eventually place. Logic really comes into play here, brainstorming of the system.
You can see that in my game it actually uses a spring library to move around the model. The system has not experienced any issues with exploiters to my knowledge and has not had any issues lagging/network lag is not visible.
(Sorry I keep editing, I just keep thinking of things) (Using a whitelist for the rays is really good with these types of things because it can limit your ray’s vision to ONLY the specified whitelist)
My honest suggestion is that you start this system from scratch and just read up on tutorials & check out some of the advice I mention above. I know there are a couple really good tutorials on this stuff on the forums. Unfortunately most of them don’t really account for any kind of lag though.
Alright, I’ll keep my current system in a folder and redo my 2 days of (broken) work. I’m not really looking for performance boosts though, this is just a little project, and I don’t have any current plans for making it a game.
My current system isn’t even lagging a bit. I’ll set an FPS counter and see how bad performance is. If it isn’t that laggy, I might consider fixing my current code. (I mean I did fix it myself a bunch of times, I’ll take your solutions for both of these options and see if they work.)
This is also a HUGE issue. You are firing a remote every frame.
You realize you can just hook the connection up to a “Mouse.Move”?
There’s not really much I can do in terms of helping other than guiding you onto making the code better – the type of system you have right now is pretty messed up
Consider making the Mouse.Move and then raycasting out and positioning a “Ghost” model of the current model you have, then when the user wants to request a placement, send it to the server to make the placement and do some checks.
Thank you for your help. I haven’t solved my problem yet, but I still wonder why is the baseplate nil? No other scripts affect the baseplate in any way, so I’m pretty confused.
EDIT: So the problem is not the baseplate, but the raycast itself. What’s wrong here?
Haha. You are raycasting 10 studs down
Either that, or it’s because there is something wrong with the blacklist you provided and it’s getting confused.
When you raycast, you give it the ORIGIN and you give it the DIRECTION. The origin is where the ray is meant to start, and then you give it a Vector3 Direction which is where you want the ray going.
You are currently using the origin as the Mouse.Hit, which is wrong because that would have to mean the ray starts in the target position they click.
This is where client comes into play, you can use the function I gave you above to get a normalized mouse position (X, Y, Z) and send that to the server when they want to place. (You can use the Camera.CFrame.Position as the origin point and then raycast in the direction) (Or if you want to keep it simple, you can send the server the Mouse.Hit.Position and then have the server Model:SetPrimaryPartCFrame(CFrame.new(Hit.X, Hit.Y, Hit.Z)) (You could also, if you want to keep the server raycasting for whatever reason, send the server the starting position (origin) and give it the direction for the server to initialize a ray)
Using the Camera.CFrame.Position as the origin worked! (I set the direction to face 100 studs down 10 studs down just wasn’t enough) Thanks for the help!
I think this is the time where you should just consider reworking it all. Getting the normalized mouse position on the client, sending coordinates to the server.
Using a Mouse.Move event to determine where to drag the model to. (On the client)
Alternatively, you can use this for the raycasting:
local Direction = (MouseHitPosition - CameraPosition).Unit * 300
local Ray = game.Workspace:Raycast(CameraPosition, Direction, RaycastParams)
Don’t forget, you are doing (what should be done on the client), on the server, so there are bound to be issues.