What do I want to achieve?
I’m trying to make a snow script in StarterCharacterScripts
that will only show the snow particles when a player is not under a part
What’s the problem?
I have no idea how I would do that at all
What do I want to achieve?
I’m trying to make a snow script in StarterCharacterScripts
that will only show the snow particles when a player is not under a part
What’s the problem?
I have no idea how I would do that at all
Here’s a UnderPartDetector
class that you could use that would send you events whenever a part (like the character’s HumanoidRootObject
) goes under any other part. It uses the same raycasting suggestion that @Katrist mentioned, and encapsulates it on a resuable way:
The module script:
local RunService = game:GetService("RunService")
-- Config
local CHECK_DELAY_IN_S = .5
local HEIGHT_ABOVE_PART = 100
-- UnderPartDetector class
local UnderPartDetector = {}
UnderPartDetector.__index = UnderPartDetector
function UnderPartDetector.new(part, descendantsToFilter)
local self = {}
setmetatable(self, UnderPartDetector)
self.part = part
self.underPartEvent = Instance.new("BindableEvent")
self.outsideEvent = Instance.new("BindableEvent")
self.isUnderPart = nil
self.descendantsToFilter = descendantsToFilter
-- Private state
self._lastCheckTime = 0
RunService.Heartbeat:Connect(function()
self:onHeartbeat()
end)
return self
end
function UnderPartDetector:onHeartbeat()
local now = tick()
if now - self._lastCheckTime < CHECK_DELAY_IN_S then
return
end
self._lastCheckTime = now
local hitObject = self:castRayUp()
if hitObject and not self.isUnderPart then
self.underPartEvent:Fire(hitObject)
self.isUnderPart = true
end
if not hitObject and self.isUnderPart then
self.outsideEvent:Fire()
self.isUnderPart = false
end
end
function UnderPartDetector:castRayUp()
-- Set an origin and directional vector
local rayOrigin = self.part.Position
local rayDirection = Vector3.new(0, HEIGHT_ABOVE_PART, 0)
-- Build a "RaycastParams" object and cast the ray
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {self.descendantsToFilter}
raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
local raycastResult = workspace:Raycast(rayOrigin, rayDirection, raycastParams)
if raycastResult then
return raycastResult.Instance
end
return nil
end
return UnderPartDetector
and here’s how you’d use the class in a Script
or LocalScript
:
local ServerScripts = game:GetService("ServerScriptService")
local Players = game:GetService("Players")
local UnderPartDetector = require(ServerScripts:WaitForChild("Utils"):WaitForChild("UnderPartDetector"))
Players.PlayerAdded:Connect(function(player)
local character = player.Character or player.CharacterAdded:Wait()
-- add character as the second arg to filter the raycast from hitting the Head, etc.
local underPartDetector = UnderPartDetector.new(character.HumanoidRootPart, character)
underPartDetector.underPartEvent.Event:Connect(function(part)
print("Under part", part)
end)
underPartDetector.outsideEvent.Event:Connect(function()
print("Outside!")
end)
end)
Alright, that should work, i’ll test it later.