local EntityUIPositionModule = {} local private = {} local cameraPos = { x = 0, y = 0, z = 0 } local cameraForward = { x = 0, y = 0, z = 0 } local curEntityPos = { x = 0, y = 0, z = 0 } local hasRenderEntity = false -- 需要elementDic key是renderEntity, valye 是table {isActive、isShown、isEnemy、element} function EntityUIPositionModule.OnLateUpdate(elementModule, elementDic, uiElementParams) -- 获取相机参数 local mainTrans = AuxUtil.MainCameraTrans cameraPos.x, cameraPos.y, cameraPos.z = mainTrans:GetPosition() local forward = mainTrans.forward cameraForward.x, cameraForward.y, cameraForward.z = forward.x, forward.y, forward.z -- 获取玩家参数 local curEntity = LogicUpdateManager._curEntity if curEntity then local expEntity = curEntity.ExpEntity if expEntity then local renderEntity = expEntity.RenderEntity if renderEntity then hasRenderEntity = true curEntityPos.x, curEntityPos.y, curEntityPos.z = renderEntity.Transform:GetPosition() else hasRenderEntity = false end else hasRenderEntity = false end else hasRenderEntity = false end -- 以上参数在循环前获取,一次循环只会获取一次,不要单独获取 for renderEntity, elementData in pairs(elementDic) do if elementData.isActive then local active = not elementModule:GetElementHide(elementData) private.SetElementShow(elementData, active) end if elementData.isShown then private.UpdatePosition(renderEntity, elementData, uiElementParams) end end end function private.UpdatePosition(renderEntity, elementData, uiElementParams) local elementObj = elementData.element.gameObject local nodePosX, nodePosY, nodePosZ = renderEntity:GetUINodePosition(nil, nil, nil) if elementData.isStatue then if elementData.modelHeight == nil or elementData.modelHeight == 0 then elementData.modelHeight = renderEntity:GetModelHeight() end nodePosY = nodePosY - elementData.modelHeight - 0.5 end if elementData.uiOffsetY then nodePosY = nodePosY + elementData.uiOffsetY end local monsterDirX = nodePosX - cameraPos.x local monsterDirY = nodePosY - cameraPos.y local monsterDirZ = nodePosZ - cameraPos.z local show = private.GetVector3Dot(monsterDirX, monsterDirY, monsterDirZ) > 0 if hasRenderEntity then local monsterToRoleX = nodePosX - curEntityPos.x local monsterToRoleZ = nodePosZ - curEntityPos.z show = show and private.GetMonsterToRoleSqrMagnitude(monsterToRoleX, 0, monsterToRoleZ) < private.GetMaxDistSqrModelUI(elementData, uiElementParams) end local scale = 1 if show then local screenPointX, screenPointY, screenPointZ = UIUtils.WorldToScreenPoint(nodePosX, nodePosY, nodePosZ, 0, 0, 0) local uiPointX, uiPointY, uiPointZ = UIUtils.GetScreenToWorldPoint(screenPointX, screenPointY, screenPointZ, nil, nil, nil) if uiPointZ > 0 then uiPointZ = 0 elementData.elementTf:SetPosition(uiPointX, uiPointY, uiPointZ) if private.IsUseZoom(elementData, uiElementParams) then local length = uiElementParams.ModelUIMaxDistance - uiElementParams.ModelUIMinDistance local percent = private.GetPercentByMagnitude(monsterDirX, monsterDirZ, uiElementParams.ModelUIMinDistance, length) -- 计算差值 Mathf.Lerp if percent > 1 then scale = uiElementParams.ModelUIMinScale elseif percent < 0 then scale = uiElementParams.ModelUIMaxScale else scale = uiElementParams.ModelUIMaxScale + (uiElementParams.ModelUIMinScale - uiElementParams.ModelUIMaxScale) * percent end end else scale = 0 end else scale = 0 end if elementData.lastScale ~= scale then elementData.elementTf:SetLocalScale(scale, scale, scale) elementData.lastScale = scale end end function private.IsUseZoom(elementData, uiElementParams) if elementData.extendData and elementData.extendData.UseZoom ~= nil then return elementData.extendData.UseZoom end return uiElementParams.UseZoom end function private.GetMaxDistSqrModelUI(elementData, uiElementParams) if elementData.extendData and elementData.extendData.MaxDistSqrModelUI ~= nil then return elementData.extendData.MaxDistSqrModelUI end return uiElementParams.MaxDistSqrModelUI end function private.SetElementShow(elementData, active) if active ~= elementData.isShown then UIUtils.SetActiveByScale(elementData.elementTf, active) elementData.isShown = active elementData.lastScale = active and 1 or 0 end end -- 返回 Vector3.Dot(cameraTrans.forward, nodePos - private.cameraV3) function private.GetVector3Dot(dirX, dirY, dirZ) return cameraForward.x * dirX + cameraForward.y * dirY + cameraForward.z * dirZ end -- 返回 sqrMagnitude function private.GetMonsterToRoleSqrMagnitude(dirX, dirY, dirZ) return dirX * dirX + dirY * dirY + dirZ * dirZ end -- 返回 percent = (v2.magnitude - uiElementParams.ModelUIMinDistance) / length function private.GetPercentByMagnitude(dirX, dirY, minDistance, length) local magnitude = math.sqrt(dirX * dirX + dirY * dirY) return (magnitude - minDistance) / length end return EntityUIPositionModule