So, I basically wanted to make a weather system, which I would make public.
And now I ran into the following issue:
How can I detect if a player is in an enclosed area (inside), in an outside area with a small roof or just completly outside.
I have looked for a devforum post and couldn’t find anything and also already looked trough the API documentation. Also nothing.
One way it could be done is region 3 or “detection bricks”, but that would require a lot of setup and this isn’t an option, since I want it to be a public module.
I would make a RayCast
going from the players head upwards toward the sky, then if it hits a Part you know they are under something.
You could check if a roof is over the player by raycasting a ray upwards. Depending on the number of players though this could quickly become performance expensive. I recommend just using the region3 method. You can still create a module that is user-friendly with region3s if you simply generate them through code so there’s no prior setup needed.
EDIT: The Region3 method I’m talking about is specifically generating a Region3 above the player rather than a Region3 for each and every indoors area.
I decided to actually do testing to determine how expensive raycasting every frame is and I was reached upwards of 2% activity which for a basic task like raining is too expensive. I did testing with a few other wait()
loops which I despise but they seem to be the solution here. The following code resulted in activity less than 0.5% over a 30 second test in a place containing 3387 parts with a few other scripts:
game.Players.PlayerAdded:Connect(function(player)
coroutine.wrap(function()
while wait(0.1) do -- 0.2 is also a good alternative --> resulted in less than 0.3%
local raycastParams = RaycastParams.new();
raycastParams.FilterType = Enum.RaycastFilterType.Blacklist;
raycastParams.FilterDescendantsInstances = {player.Character};
local ray = workspace:Raycast(player.Character.HumanoidRootPart.Position, Vector3.new(0, 1, 0) * 100, raycastParams);
print(ray);
end
end)();
end)
Ah great. Well this is gonna be an interesting journey, considering I never used Raycasting before.
And also, your script just gives me an error. ServerScriptService.Script:7: attempt to index nil with 'HumanoidRootPart'
Yeah this was just a test script you have to actually wait for the character to load before you can index its HumanoidRootPart. A simple way to do that is within the PlayerAdded
event:
player.CharacterAdded:Wait(); -- will wait until CharacterAdded triggers once
Raycasts are the best easy option and raycasts will not be expensive unless you give them a high distance and raycasts every 0.2 milliseconds will result.