Im trying to make a stealth game, im trying to make the detection meter gui position in the direction of the enemy, but it only works for one enemy. The rest just show up as regular ui on your screen.
https://gyazo.com/31d6fa50929e5ad3c956f6cd488dd1c8
I cannot provide my class module script as its too long so here is the tutorial i followed: https://devforum.roblox.com/t/how-to-make-a-stealth-system/926417
Stealth Controller:
-- Controller
local StealthController = {}
-- Roblox Services
local RunService = game:GetService("RunService")
-- Modules
local Enemy
-- Table to store our enemies
local enemies = {}
-- The folder with the models of our enemies
local enemyFolder = workspace:WaitForChild("enemies"):GetChildren()
local plr: Player? = (RunService:IsClient()) and game:GetService("Players").LocalPlayer
local Markers = {}
local Screen = plr:WaitForChild("PlayerGui"):WaitForChild("DetectionUIS"):WaitForChild("Holder").AbsoluteSize
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local T = game:GetService("TweenService")
-- Types
-- this is poggers men!
type Enemy = {
-- Properties
enemy: Model,
OnDetected: RBXScriptSignal,
detected: boolean,
detecting: boolean,
distance: number,
detectionMeter: number,
player: Player?,
combatSettings: {
damage: number,
attackCooldown: number,
range: number
},
animations: {
fire: AnimationTrack,
reload: AnimationTrack,
walk: AnimationTrack
},
detectionSettings: {
FOV: number,
maxDistance: number,
minDetection: number,
maxDetection: number,
DISTANCE_CONSTANT: number
},
-- Objects
detectionBar: Frame?,
-- Methods
new: (Model) -> Enemy,
DoChecks: () -> nil,
MoveToNextPoint: () -> nil,
-- Private methods
_behindObstacle: () -> boolean,
_withinFOV: () -> boolean,
_withinDistance: () -> boolean,
_updateGUI: () -> nil,
Init: () -> nil
}
-- Controller initialization
function StealthController:Init()
-- Assign enemy
Enemy = self.Shared.Enemy
end
function ClampMarkerToBorder(X,Y,Absolute)
X = Screen.X - X
Y = Screen.Y - Y
local DistanceToXBorder = math.min(X,Screen.X-X)
local DistanceToYBorder = math.min(Y,Screen.Y-Y)
if DistanceToYBorder < DistanceToXBorder then
if Y < (Screen.Y-Y) then
return math.clamp(X,0,Screen.X-Absolute.X),0
else
return math.clamp(X,0,Screen.X-Absolute.X),Screen.Y - Absolute.Y
end
else
if X < (Screen.X-X) then
return 0,math.clamp(Y,0,Screen.Y-Absolute.Y)
else
return Screen.X - Absolute.X,math.clamp(Y,0,Screen.Y-Absolute.Y)
end
end
end
function StealthController:Start()
-- Loop through the enemies's models
for enemyIndex: number, enemy: Model in ipairs(enemyFolder) do
-- Create an instance of the Enemy class
local newEnemy = Enemy.new(enemy)
-- Create a key for our new Enemy object
enemies[enemy.Name .. enemyIndex] = newEnemy
local Marker = plr:WaitForChild("PlayerGui").DetectionUIS.detectionBar
Marker.Parent = plr:WaitForChild("PlayerGui"):WaitForChild("DetectionUIS").Holder
game:GetService("RunService").Heartbeat:Connect(function()
--if plr.PlayerGui:WaitForChild("DetectedUI").Enabled == true then return end
local Location = enemy.Head
--Marker.Visible = Location.Config.Enabled.Value
local MarkerPosition = game.Workspace.CurrentCamera:WorldToScreenPoint(Location.Position)
local MarkerRotation = game.Workspace.CurrentCamera.CFrame:Inverse()*Location.CFrame
local MarkerAbsolute = plr:WaitForChild("PlayerGui"):WaitForChild("DetectionUIS").Holder:FindFirstChild("detectionBar").AbsoluteSize
local MarkerPositionX = MarkerPosition.X - MarkerAbsolute.X/2
local MarkerPositionY = MarkerPosition.Y - MarkerAbsolute.Y/2
if MarkerPosition.Z < 0 then
MarkerPositionX,MarkerPositionY = ClampMarkerToBorder(MarkerPositionX,MarkerPositionY,MarkerAbsolute)
else
if MarkerPositionX < 0 then
MarkerPositionX = 0
elseif MarkerPositionX > (Screen.X - MarkerAbsolute.X) then
MarkerPositionX = Screen.X - MarkerAbsolute.X
end
if MarkerPositionY < 0 then
MarkerPositionY = 0
elseif MarkerPositionY > (Screen.Y - MarkerAbsolute.Y) then
MarkerPositionY = Screen.Y - MarkerAbsolute.Y
end
plr:WaitForChild("PlayerGui"):WaitForChild("DetectionUIS").Holder:FindFirstChild("detectionBar").RotateLabel.Rotation = 90 + math.deg(math.atan2(MarkerRotation.Z,MarkerRotation.X))
plr:WaitForChild("PlayerGui"):WaitForChild("DetectionUIS").Holder:FindFirstChild("detectionBar").Position = UDim2.new(0,MarkerPositionX,0,MarkerPositionY)
--T:Create(Marker,TweenInfo.new(.5),{ImageColor3 = Location.Config.MarkerColor.Value}):Play()
--T:Create(Marker.RotateLabel.Arrow,TweenInfo.new(.5),{ImageColor3 = Location.Config.MarkerColor.Value}):Play()
end
end)
-- Connect the .OnDetected event
local onDetected: RBXScriptConnection
onDetected = newEnemy.OnDetected:Connect(function()
print("Detected!")
plr:WaitForChild("PlayerGui")
local detectedui = plr.PlayerGui:WaitForChild("DetectedUI")
detectedui.Enabled = true
detectedui.TextLabel.Text = (plr.Name.. " was seen!")
onDetected:Disconnect()
return
end)
end
-- Function to be run every heartbeat
local function heartBeat(_: number)
-- Loops through our enemies
for _: string, enemy: Enemy in pairs(enemies) do
-- If enemy has been detected, skip the iteration to not call the method
if (enemy.detected) then continue end
enemy:DoChecks()
end
end
RunService.Heartbeat:Connect(heartBeat)
end
return StealthController
