So I just created a script that opens a gui when the player comes close to a part. I just did the part for an initial test but I don't know how i'll adjust it for npc's. I was thinking to create a ray that detects if an npc is in it's vicinity but I don't know how to go about making that vicinity and I don't how to do it with multiple npc's at once.
LocalScript in StarterPack in a tool
local playergui = game.Players.LocalPlayer.PlayerGui
gui = Instance.new("ScreenGui", playergui)
image = Instance.new("ImageLabel", gui)
image.BackgroundColor3 = Color3.new(255, 255, 255)
image.BorderColor3 = Color3.new(27, 42, 53)
image.Position = UDim2.new(0.46, 0,0.423, 0)
image.Size = UDim2.new(0, 100,0, 100)
image.ImageColor3 = Color3.new(255, 255, 255)
while wait(.01) do
local mag = (game.Workspace.Part.Position - game.Players.LocalPlayer.Character.HumanoidRootPart.Position).magnitude
local playergui = game.Players.LocalPlayer.PlayerGui
local val = 10
if mag < val then
print("gfsdgsdfgsdfgsdfg")
gui.Parent = playergui
else
gui.Parent = nil
end
end

3 comments
https://forum.scriptinghelpers.org/topic/763/how-magnitude-works-in-layman-s-terms
Checking magnitude every 0.01 seconds is going to lag the crap out of your game, especially if you end up having more than one npc.
I answered bellow