I've come up with a new design which solves the one major drawback my previous method had, which was the 1 frame delay between updates so our nameplate would lag behind the real one.
Lua Code:
local Nameplates, PreviousWorldChildren = {}, 0
WorldFrame:HookScript('OnUpdate', function(self)
local currentWorldChildren = self:GetNumChildren()
if currentWorldChildren ~= PreviousWorldChildren then PreviousWorldChildren = currentWorldChildren
for _, plate in pairs({self:GetChildren()}) do
if not Nameplates[plate] then
local name = plate:GetName()
if name and strmatch(name, '^NamePlate%d+$') then
local f = CreateFrame('frame', nil, WorldFrame)
Nameplates[plate] = f
f:SetSize(1, 1)
for i = 1, 500 do -- Make a bunch of regions for a stress test
local fs = f:CreateFontString(nil, nil, 'GameFontNormalHuge')
fs:SetText('LAG')
fs:SetPoint('CENTER', f, math.random(-50,50), math.random(-12,12))
end
-- Attach a frame to the nameplate which will fire OnSizeChanged when it moves
local sizer = CreateFrame('frame', nil, f)
sizer:SetPoint('BOTTOMLEFT', WorldFrame)
sizer:SetPoint('TOPRIGHT', plate, 'CENTER')
sizer:SetScript('OnSizeChanged', function(self, x, y)
f:Hide() -- Important, never move the frame while it's visible
f:SetPoint('CENTER', WorldFrame, 'BOTTOMLEFT', x, y) -- Immediately reposition frame
f:Show()
end)
plate:HookScript('OnHide', function() f:Hide() end)
plate:HookScript('OnShow', function() f:Show() end)
end
end
end
end
end)
This works by creating an extra frame for every nameplate which is attached to the edge of the screen and the center of the nameplate, so that any time the nameplate moves it calls the OnSizeChanged script which is where we reposition our custom nameplate.
Other than that it's the same as it was before, but now it only updates if the frame has actually moved, and it should stay above the unit's head as the camera moves, rather than lag behind.