I’m working on a criminal game in which there are police characters. I want to make it so if a police officer sees you committing a crime, you automatically get given a wanted level.
How would I accomplish a sort of “ray” to span (let’s say 60 degrees) from the officer’s head, if you are within this ray and committing a crime, you would become wanted.
Would I use raycasting? How many rays would I need to create? And so on.
How I would approach this is I would only create rays while a player is committing a crime (assuming you have a method of distinguishing). So while any player is committing a crime, raycast between the officer and the player. If there is a direct line of sight (perhaps put a limit on how far the officers can see, say 300 studs or something), then apply the wanted level to the player, otherwise let the player carry on.
-- pseudocode within the officers --
local committing_crimes = {} -- array of players who are currently committing crimes
for _, player in pairs(committing_crimes) do
local ray = Ray.new(officer.Head.CFrame.p,
(officer.Head.CFrame.p - player.Character.Head.CFrame.p).unit * 300 )
local part, position = workspace:FindPartOnRay(ray) -- check whether in line of sight
if part and part == player.Character.Head then -- if no obstacles between officer and player
player.Character:ApplyWanted() -- make the player wanted
end
end
I’m planning on creating a large open world multiplayer game, which would include a lot of police NPCs- on top of this I plan on making citizens “call” the police if a crime is being committed.
Would there be a way to do this on the client?
E.g. Check to see if there are any police within a large radius and then create rays?
Alternatively could I have a ray on each officer and report which players are being detected by them?
This is flawed in that an officer could be looking the opposite way and this return true. What you could do after this calculation is take the angle in between the officer’s head’s LookVector and the vector originally used for the ray and see if it is within limits.
@OP
Never trust the client. If you do raycasting on the client, it would be better for the server but an exploiter can easily bypass this.
So I would scan every witness and see if they are within sight of a player, if they can see that player, is that player committing a crime, if so, set bounty.
I would do it like this:
When a player initiates a crime, send a message to the server. Then, the server would check if any policeman can see them (using rays and angle checking) every few seconds (if policeman are stationary just check on robbery initiation). If test returns positive, increase bounty.
Also found this article explaining how to get the angle between vectors.
OP can’t just use dot product, because they need to make sure the NPC can actually see the player (ex: if guard was facing a wall, and right behind the wall was the player).
Probably the best response which pointed me in the right direction the most, so I gave this post the solution.
All the replies (and things like scripting discord servers) helped me solve this, but I gave this one the solution as it was the reply here that helped me the most.
It uses Dot to figure out if the player is within the angle (in my case, 70 degrees) and then uses a Ray (with both the player and officer’s characters on the ignore list) to determine if the player is within the line of sight.
Both of these checks must pass for the game to determine the player is visible to the officer.
Note: If you’re trying this, Dot does not return degrees, you’ll need to convert degrees to radians, I did this by using math.rad(70/2)) as part of the Dot checker function.