Hi! I wanna make “.Touched”/“.TouchEnded” as RayCast from Attachments:
I have already done “.Touched”:
local v = script.Parent
local touched = {}
while wait() do
for _, att:Attachment in pairs(v:GetChildren()) do
if att:IsA("Attachment") then
local params = RaycastParams.new()
params.FilterDescendantsInstances = {}
params.FilterType = Enum.RaycastFilterType.Exclude
local ray = workspace:Raycast(att.Position+v.Position, att.CFrame.UpVector*100, params)
if ray ~= nil and ray.Instance ~= nil then
local char:Model = ray.Instance.Parent
local plr = game.Players:GetPlayerFromCharacter(char)
if plr ~= nil and not table.find(touched, plr.Name) then
print(plr.Name.." touched")
table.insert(touched, plr.Name)
game.ReplicatedStorage.Events.OpenFrame:FireClient(plr, v.Name, true)
end
end
end
end
end
Similar to how you connected the .Touched event, create a new event handler for .TouchEnded.
Use the TouchEnded event to detect when a player stops touching the attachment.
Disconnect the Event:
Inside the .TouchEnded event handler, you’ll want to disconnect the .Touched event.
This ensures that the .Touched event doesn’t continue firing after the player stops touching the attachment.
Here’s an example of how you can modify your existing code to include .TouchEnded:
Lua
local v = script.Parent
local touched = {}
while wait() do
for _, att:Attachment in pairs(v:GetChildren()) do
if att:IsA("Attachment") then
local params = RaycastParams.new()
params.FilterDescendantsInstances = {}
params.FilterType = Enum.RaycastFilterType.Exclude
local ray = workspace:Raycast(att.Position + v.Position, att.CFrame.UpVector * 100, params)
if ray ~= nil and ray.Instance ~= nil then
local char:Model = ray.Instance.Parent
local plr = game.Players:GetPlayerFromCharacter(char)
if plr ~= nil and not table.find(touched, plr.Name) then
print(plr.Name .. " touched")
table.insert(touched, plr.Name)
game.ReplicatedStorage.Events.OpenFrame:FireClient(plr, v.Name, true)
end
end
end
end
end
-- Add the .TouchEnded event handler
att.TouchEnded:Connect(function()
-- Perform any necessary actions when touch ends
-- For example, reset state or stop an animation
print("Touch ended")
-- Disconnect the .Touched event to prevent further firing
att.Touched:Disconnect()
end)
Remember to replace the placeholder comments with your actual logic for handling the .TouchEnded event. You can adjust the behavior inside the .TouchEnded handler based on your specific requirements.
Before we continue, seeing that you fire OpenFrame signal on touch, is there a particular reason you are not using Touched and TouchEnded, or spatial query like GetPartsInPart() and GetPartBoundsInBox()?
Sample (spatial query in an invisible box)
local Players = game:GetService("Players")
local v = script.Parent
local _detected = {}
local touching = {}
local params = OverlapParams.new()
params.FilterDescendantsInstances = {}
params.FilterType = Enum.RaycastFilterType.Exclude
while true do
local parts = workspace:GetPartBoundsInBox(v.CFrame, v.Size, params)
table.clear(_detected)
-- Collect players currently touching the box
for _,part in parts do
local player = Players:GetPlayerFromCharacter(part.Parent)
if player then
_detected[player] = true
end
end
-- Reconcile the list of touching players
for _,player in Players:GetPlayers() do
local i = table.find(touching, player)
if _detected[player] and i == nil then
print(player.Name.." touched")
table.insert(touching, player)
elseif _detected[player] == nil and i ~= nil then
print(player.Name.." touch ended")
table.remove(touching, table.find(touching, player))
end
end
task.wait()
end