Thanks again! (I really should have tested this more
)
I updated the model and the uncopylocked game. Here is the IndicatorClient code:
New code for: "IndicatorClient"
-- v.1.2
local Workspace = game:GetService("Workspace")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local createNewIndicator = require(script:WaitForChild("CreateNewIndicator"))
local updateIndicatorUI = require(script:WaitForChild("UpdateIndicatorUI"))
local camera = Workspace.CurrentCamera
local player = Players.LocalPlayer
local screenGui = Instance.new("ScreenGui")
screenGui.Name = "IndicatorGui"
screenGui.IgnoreGuiInset = true
screenGui.ResetOnSpawn = false
screenGui.Parent = player:WaitForChild("PlayerGui")
local indicatorTable = {}
-- {attachment, ui, connections}
local function removeIndicator(attachment)
for index, data in ipairs(indicatorTable) do
if data[1] == attachment then
data[2]:Destroy()
for _, connection in ipairs(data[3]) do
if connection then
connection:Disconnect()
end
end
table.remove(indicatorTable, index)
end
end
end
local function processWorkspaceDescendantAdded(descendant)
if descendant:IsA("Attachment") and descendant.Name == "Indicator" then
removeIndicator(descendant)
local newIndicator = createNewIndicator()
local connections = {}
local attributeChanged = descendant.AttributeChanged:Connect(function(name)
if (name == "Image") or (name == "Team") or (name == "Color") or (name == "Enabled") then
updateIndicatorUI(descendant, newIndicator)
end
end)
table.insert(connections, attributeChanged)
local data = {}
data[1] = descendant
data[2] = newIndicator
data[3] = connections
table.insert(indicatorTable, data)
updateIndicatorUI(descendant, newIndicator)
newIndicator.Parent = screenGui
end
end
for _, descendant in ipairs(Workspace:GetDescendants()) do
processWorkspaceDescendantAdded(descendant)
end
Workspace.DescendantAdded:Connect(processWorkspaceDescendantAdded)
local function processWorkspaceDescendantRemoving(descendant)
if descendant:IsA("Attachment") and descendant.Name == "Indicator" then
removeIndicator(descendant)
end
end
Workspace.DescendantRemoving:Connect(processWorkspaceDescendantAdded)
local function updateIndicatorPositions()
local viewportX = camera.ViewportSize.X
local viewportY = camera.ViewportSize.Y
if not indicatorTable[1] then return end
local bufferSize = indicatorTable[1][2].AbsoluteSize.X
local maxBoundsX = viewportX - (bufferSize * 2)
local maxBoundsY = viewportY - (bufferSize * 2)
local camCFrame = camera.CFrame
local screenHypotenuse = math.sqrt((maxBoundsX/2)^2+(maxBoundsY/2)^2)
local cameraForward
do
local cameraForward3D = camera.CFrame.LookVector
cameraForward = Vector2.new(cameraForward3D.X, cameraForward3D.Z).Unit
end
for _, data in ipairs(indicatorTable) do
local indicatorUI = data[2]
if indicatorUI.Visible == false then
continue
end
local position = data[1].WorldPosition
local screenPosition3d, onScreen = camera:WorldToViewportPoint(position)
local xPosition = math.clamp(screenPosition3d.X, bufferSize, viewportX - bufferSize)
local yPosition = math.clamp(screenPosition3d.Y, bufferSize, viewportY - bufferSize)
if (xPosition == screenPosition3d.X) and (yPosition == screenPosition3d.Y) and onScreen then
indicatorUI.ArrowFrame.Visible = false
else
indicatorUI.ArrowFrame.Visible = true
local worldDirection = position - camCFrame.Position
local relativeDirection = camCFrame:VectorToObjectSpace(worldDirection)
local relativeDirection2D = Vector2.new(relativeDirection.X, relativeDirection.Y).Unit
local testScreenPoint = relativeDirection2D * screenHypotenuse
local angle = math.atan2(relativeDirection2D.X, relativeDirection2D.Y)
local screenPoint
if math.abs(testScreenPoint.Y) > maxBoundsY/2 then
screenPoint = relativeDirection2D * math.abs(maxBoundsY/2/relativeDirection2D.Y)
else
screenPoint = relativeDirection2D * math.abs(maxBoundsX/2/relativeDirection2D.X) -- TODO Try flip sin cos
end
xPosition = viewportX / 2 + screenPoint.X
yPosition = viewportY / 2 - screenPoint.Y
indicatorUI.ArrowFrame.Rotation = math.deg(angle)
end
indicatorUI.Position = UDim2.fromOffset(xPosition, yPosition)
end
end
RunService.RenderStepped:Connect(updateIndicatorPositions)
player:GetPropertyChangedSignal("TeamColor"):Connect(function()
for _, data in ipairs(indicatorTable) do
updateIndicatorUI(data[1], data[2])
end
end)
It was a pretty quick fix (I’d forgotten to remove the data table when cleaning up markers). The problem you had is fixed ![:+1: :+1:](https://doy2mn9upadnk.cloudfront.net/images/emoji/twitter/+1.png?v=12)
To make the indicators fade based on distance, place this code
--
local maxDistance = 100
local minDistance = 10
local distance = (position - camCFrame.Position).Magnitude
local transparency = 0
if distance > minDistance then
transparency = math.clamp((distance-minDistance)/(maxDistance-minDistance), 0, 1)
end
data[2].Transparency = transparency
data[2].ArrowFrame.ArrowImage.ImageTransparency = transparency
data[2].IconImage.ImageTransparency = transparency
data[2].LayoutOrder = math.round(distance/(maxDistance - minDistance)*10)
--
under
for _, data in ipairs(indicatorTable) do
local indicatorUI = data[2]
if indicatorUI.Visible == false then
continue
end
local position = data[1].WorldPosition
Example code
local function updateIndicatorPositions()
local viewportX = camera.ViewportSize.X
local viewportY = camera.ViewportSize.Y
if not indicatorTable[1] then return end
local bufferSize = indicatorTable[1][2].AbsoluteSize.X
local maxBoundsX = viewportX - (bufferSize * 2)
local maxBoundsY = viewportY - (bufferSize * 2)
local camCFrame = camera.CFrame
local screenHypotenuse = math.sqrt((maxBoundsX/2)^2+(maxBoundsY/2)^2)
local cameraForward
do
local cameraForward3D = camera.CFrame.LookVector
cameraForward = Vector2.new(cameraForward3D.X, cameraForward3D.Z).Unit
end
for _, data in ipairs(indicatorTable) do
local indicatorUI = data[2]
if indicatorUI.Visible == false then
continue
end
local position = data[1].WorldPosition
--
local maxDistance = 100
local minDistance = 10
local distance = (position - camCFrame.Position).Magnitude
local transparency = 0
if distance > minDistance then
transparency = math.clamp((distance-minDistance)/(maxDistance-minDistance), 0, 1)
end
data[2].Transparency = transparency
data[2].ArrowFrame.ArrowImage.ImageTransparency = transparency
data[2].IconImage.ImageTransparency = transparency
data[2].LayoutOrder = math.round(distance/(maxDistance - minDistance)*10)
--
local screenPosition3d, onScreen = camera:WorldToViewportPoint(position)
local xPosition = math.clamp(screenPosition3d.X, bufferSize, viewportX - bufferSize)
local yPosition = math.clamp(screenPosition3d.Y, bufferSize, viewportY - bufferSize)
if (xPosition == screenPosition3d.X) and (yPosition == screenPosition3d.Y) and onScreen then
indicatorUI.ArrowFrame.Visible = false
else
indicatorUI.ArrowFrame.Visible = true
local worldDirection = position - camCFrame.Position
local relativeDirection = camCFrame:VectorToObjectSpace(worldDirection)
local relativeDirection2D = Vector2.new(relativeDirection.X, relativeDirection.Y).Unit
local testScreenPoint = relativeDirection2D * screenHypotenuse
local angle = math.atan2(relativeDirection2D.X, relativeDirection2D.Y)
local screenPoint
if math.abs(testScreenPoint.Y) > maxBoundsY/2 then
screenPoint = relativeDirection2D * math.abs(maxBoundsY/2/relativeDirection2D.Y)
else
screenPoint = relativeDirection2D * math.abs(maxBoundsX/2/relativeDirection2D.X) -- TODO Try flip sin cos
end
xPosition = viewportX / 2 + screenPoint.X
yPosition = viewportY / 2 - screenPoint.Y
indicatorUI.ArrowFrame.Rotation = math.deg(angle)
end
indicatorUI.Position = UDim2.fromOffset(xPosition, yPosition)
end
end
![Fading Markers](//devforum-uploads.s3.dualstack.us-east-2.amazonaws.com/uploads/original/4X/f/6/5/f656570be02c4ec2f62974e153d8a8aa15d74198.gif)
minDistance
is the distance where all markers will be fully visible. maxDistance
is the distance where the markers will be fully invisible.
Thanks again for helping me fix some bugs ![:happy2: :happy2:](//devforum-uploads.s3.dualstack.us-east-2.amazonaws.com/uploads/original/3X/7/a/7afe231e0669105e61d3a5d107d91883c0e17885.png?v=12)
Edit:
Yep ![:+1: :+1:](https://doy2mn9upadnk.cloudfront.net/images/emoji/twitter/+1.png?v=12)
If there is a new version, you should just be able to copy that code back into the same place (probably).