Today I come to you seeking assistance. I’ll try to keep it short. I’ve been trying to make a ‘Heartbeat sensor’ for my game, however I’m having trouble figuring out how to convert the 3D positions of players into 2D positions on this screen. I’ve already been able to determine that the enemy players are close enough to you using .magnitude and Dot with lookVector to determine they are ‘in front’ of you and not behind you.
My goal is to have only players in front of you show up, and I’ve successfully nullified the Y axis in the .magnitude part. By that I mean I want to have an enemy player to show up on the Heartbeat Sensor as 5 studs away from you for example, even if they’re 5 studs away from you but 100 feet below or above you.
Anyway, I have no idea how to convert these 3D positions into 2D positions on this screen. How would you go about this? I appreciate any and all replies!
Here’s an example of my ideal final result. Lower player is ‘you’, and the green dot on the screen is you as well.
This sounds great! However, I can’t help, but I just came here to give you feedback! The monitor looks nice! Gives us a good detail of how it’s going to work! I hope you will get some help!
Get the object space of the object relative to the player, transform that by the monitor’s parameters, remove all those that aren’t in the FOV of the scanner i.e. if they’re behind you
Here’s something I just quickly threw together, edit it for your implementation:
local Screen = game.Workspace.Part.SurfaceGui
local Point = Screen.Frame --> Needs to have a AnchorPoint of 0.5, 0.5
local A, B = game.Workspace.A, game.Workspace.B
game:GetService("RunService").Heartbeat:connect(function ()
local abs = Screen.AbsoluteSize * 0.5
local a, b = A.CFrame, B.CFrame
local rel = a:toObjectSpace(b)
Point.Position = UDim2.new(
0.5 + rel.x/abs.x,
0,
0.5 + rel.z/abs.y,
0
)
end)
Obviously you would need to offset the Y axis for your implementation as you have the centre point at the bottom of the SurfaceGui.
Hey, thanks for the code! I’ve been messing around with what you gave me but my results seem to be positions like UDim2.new(2.503, 0, -0.533, 0), which don’t appear on the screen. I set the frame AnchorPoint to 0.5,0.5 but the dot never showed up. Setting it to 0,0 at least gave me the result shown below, although the range is much less than 250.
local abs = gui.Bg.AbsoluteSize * 0.5
for _,v in pairs(game.Players:GetChildren()) do
local vChar = v.Character
if vChar and vChar ~= char then --checking if both characters exist
local vCharCF = vChar.PrimaryPart.CFrame
vCharCF = vCharCF + Vector3.new(0, (charCF.p.Y - vCharCF.p.Y), 0) --setting enemy player Y to same as client
local vec = (charCF.p - vCharCF.p)
local dot = -(vec:Dot(charCF.lookVector) / vec.magnitude)
if vec.magnitude < 250 and dot > 0 then --checking enemy is closer than 250 studs and is in 'front' of you
local newP = gui.Player:Clone()
local rel = charCF:toObjectSpace(vCharCF)
newP.Position = UDim2.new(0.5 + rel.x / abs.x, 0, 0.5 + rel.z / abs.y, 0) --Isocortex's code
newP.Visible = true
newP.Parent = gui.Bg.Frame
end
end
end
Again, I’m still using the anchor point at 0.5, 0.5 - I’m assuming yours doesn’t appear as your using Scale to resize the Frame object?
The reason your dot disappears on your video though is surely because of the LookVector operation. Don’t forget to account for the Y offset as mentioned in my previous post though, you need to lower the centre point to match your texture
Ah, thanks for that! The demo helps a lot. I’m having trouble though getting the center point of the sensor to be at the bottom center rather than the center of the screen. How would you change the numbers to enact this?
local Screen = game.Workspace.Part.SurfaceGui
local Point = Screen.Frame --> Needs to have a AnchorPoint of 0.5, 0.5
local A, B = game.Workspace.A, game.Workspace.B
local SCAN_DISTANCE = 250
local HEIGHT = 0.75
game:GetService("RunService").Heartbeat:connect(function ()
local abs = Screen.AbsoluteSize * 0.5
local a, b = A.CFrame, B.CFrame
local rel = a:toObjectSpace(b)
local vec = a.p - b.p
local dot = -(vec:Dot(a.lookVector) / vec.magnitude)
if vec.magnitude < 250 and dot > 0 then
Point.BackgroundColor3 = Color3.new(1, 1, 1)
Point.Position = UDim2.new(
0.5 + rel.x/(abs.x * ((SCAN_DISTANCE*2)/abs.x)),
0,
HEIGHT + rel.z/(abs.y * ((SCAN_DISTANCE*2)/abs.y)),
0
)
else
Point.BackgroundColor3 = Color3.new(1, 0, 0)
end
end)
Although this assumes that you have anchorpoint of 0.5,0.5 - will be 1 - HEIGHT if you have 0, 0.
Hope that’s finally provided you with the solution