diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayerDebug.h b/Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayerDebug.h new file mode 100644 index 0000000000..384db66317 --- /dev/null +++ b/Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayerDebug.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +namespace Multiplayer +{ + //! @class IMultiplayerDebug + //! @brief IMultiplayerDebug provides access to multiplayer debug overlays + class IMultiplayerDebug + { + public: + AZ_RTTI(IMultiplayerDebug, "{C5EB7F3A-E19F-4921-A604-C9BDC910123C}"); + + virtual ~IMultiplayerDebug() = default; + + //! + virtual void ShowEntityBandwidthDebugOverlay() = 0; + + //! + virtual void HideEntityBandwidthDebugOverlay() = 0; + }; +} diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.cpp index a29350e43a..38a1a27dcd 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.cpp +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugByteReporter.cpp @@ -8,12 +8,10 @@ #include "MultiplayerDebugByteReporter.h" -#include +#include // for std::setfill #include #include -#pragma optimize("", off) - namespace Multiplayer { void MultiplayerDebugByteReporter::ReportBytes(size_t byteSize) diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.cpp index da32bbb666..b0bfe097e1 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.cpp +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.cpp @@ -17,11 +17,6 @@ #include #endif -#pragma optimize("", off) - -AZ_CVAR(bool, net_DebugNetworkEntity_Bandwidth, true, nullptr, AZ::ConsoleFunctorFlags::Null, - "If true, prints debug text over entities that use a considerable amount of network traffic"); - AZ_CVAR(float, net_DebugNetworkEntity_ShowAboveKbps, 1.f, nullptr, AZ::ConsoleFunctorFlags::Null, "Prints bandwidth on network entities with higher kpbs than this value"); @@ -304,8 +299,8 @@ namespace Multiplayer void MultiplayerDebugPerEntityReporter::RecordRpcReceived( AZ::EntityId entityId, const char* entityName, - Multiplayer::NetComponentId netComponentId, - Multiplayer::RpcIndex rpcId, + NetComponentId netComponentId, + RpcIndex rpcId, uint32_t totalBytes) { if (const Multiplayer::MultiplayerComponentRegistry* componentRegistry = Multiplayer::GetMultiplayerComponentRegistry()) @@ -323,69 +318,66 @@ namespace Multiplayer void MultiplayerDebugPerEntityReporter::UpdateDebugOverlay() { - if (net_DebugNetworkEntity_Bandwidth) + m_networkEntitiesTraffic.clear(); + + for (AZStd::pair& entityPair : m_receivingEntityReports) { - m_networkEntitiesTraffic.clear(); - - for (AZStd::pair& entityPair : m_receivingEntityReports) - { - m_networkEntitiesTraffic[entityPair.first].m_name = entityPair.second.GetEntityName(); - m_networkEntitiesTraffic[entityPair.first].m_down = entityPair.second.GetKbitsPerSecond(); - } - - for (AZStd::pair& entityPair : m_sendingEntityReports) - { - m_networkEntitiesTraffic[entityPair.first].m_name = entityPair.second.GetEntityName(); - m_networkEntitiesTraffic[entityPair.first].m_up = entityPair.second.GetKbitsPerSecond(); - } - - //get debug display interface for the viewport - if (m_debugDisplay == nullptr) - { - AzFramework::DebugDisplayRequestBus::BusPtr debugDisplayBus; - AzFramework::DebugDisplayRequestBus::Bind(debugDisplayBus, AzFramework::g_defaultSceneEntityDebugDisplayId); - m_debugDisplay = AzFramework::DebugDisplayRequestBus::FindFirstHandler(debugDisplayBus); - } - - const AZ::u32 stateBefore = m_debugDisplay->GetState(); - - for (AZStd::pair& networkEntity : m_networkEntitiesTraffic) - { - if (networkEntity.second.m_down < net_DebugNetworkEntity_ShowAboveKbps && networkEntity.second.m_up < net_DebugNetworkEntity_ShowAboveKbps) - { - continue; - } - - if (networkEntity.second.m_down > net_DebugNetworkEntity_WarnAboveKbps || networkEntity.second.m_up > net_DebugNetworkEntity_WarnAboveKbps) - { - m_debugDisplay->SetColor(net_DebugNetworkEntity_WarningColor); - } - else - { - m_debugDisplay->SetColor(net_DebugNetworkEntity_BelowWarningColor); - } - - if (networkEntity.second.m_down > net_DebugNetworkEntity_ShowAboveKbps && networkEntity.second.m_up > net_DebugNetworkEntity_ShowAboveKbps) - { - azsprintf(m_statusBuffer, "[%s] %.0f down / %0.f up (kbps)", networkEntity.second.m_name, - networkEntity.second.m_down, networkEntity.second.m_up); - } - else if (networkEntity.second.m_down > net_DebugNetworkEntity_ShowAboveKbps) - { - azsprintf(m_statusBuffer, "[%s] %.0f down (kbps)", networkEntity.second.m_name, networkEntity.second.m_down); - } - else - { - azsprintf(m_statusBuffer, "[%s] %.0f up (kbps)", networkEntity.second.m_name, networkEntity.second.m_up); - } - - AZ::Vector3 entityPosition = AZ::Vector3::CreateZero(); - constexpr bool centerText = true; - AZ::TransformBus::EventResult(entityPosition, networkEntity.first, &AZ::TransformBus::Events::GetWorldTranslation); - m_debugDisplay->DrawTextLabel(entityPosition, 1.0f, m_statusBuffer, centerText, 0, 0); - } - - m_debugDisplay->SetState(stateBefore); + m_networkEntitiesTraffic[entityPair.first].m_name = entityPair.second.GetEntityName(); + m_networkEntitiesTraffic[entityPair.first].m_down = entityPair.second.GetKbitsPerSecond(); } + + for (AZStd::pair& entityPair : m_sendingEntityReports) + { + m_networkEntitiesTraffic[entityPair.first].m_name = entityPair.second.GetEntityName(); + m_networkEntitiesTraffic[entityPair.first].m_up = entityPair.second.GetKbitsPerSecond(); + } + + //get debug display interface for the viewport + if (m_debugDisplay == nullptr) + { + AzFramework::DebugDisplayRequestBus::BusPtr debugDisplayBus; + AzFramework::DebugDisplayRequestBus::Bind(debugDisplayBus, AzFramework::g_defaultSceneEntityDebugDisplayId); + m_debugDisplay = AzFramework::DebugDisplayRequestBus::FindFirstHandler(debugDisplayBus); + } + + const AZ::u32 stateBefore = m_debugDisplay->GetState(); + + for (AZStd::pair& networkEntity : m_networkEntitiesTraffic) + { + if (networkEntity.second.m_down < net_DebugNetworkEntity_ShowAboveKbps && networkEntity.second.m_up < net_DebugNetworkEntity_ShowAboveKbps) + { + continue; + } + + if (networkEntity.second.m_down > net_DebugNetworkEntity_WarnAboveKbps || networkEntity.second.m_up > net_DebugNetworkEntity_WarnAboveKbps) + { + m_debugDisplay->SetColor(net_DebugNetworkEntity_WarningColor); + } + else + { + m_debugDisplay->SetColor(net_DebugNetworkEntity_BelowWarningColor); + } + + if (networkEntity.second.m_down > net_DebugNetworkEntity_ShowAboveKbps && networkEntity.second.m_up > net_DebugNetworkEntity_ShowAboveKbps) + { + azsprintf(m_statusBuffer, "[%s] %.0f down / %0.f up (kbps)", networkEntity.second.m_name, + networkEntity.second.m_down, networkEntity.second.m_up); + } + else if (networkEntity.second.m_down > net_DebugNetworkEntity_ShowAboveKbps) + { + azsprintf(m_statusBuffer, "[%s] %.0f down (kbps)", networkEntity.second.m_name, networkEntity.second.m_down); + } + else + { + azsprintf(m_statusBuffer, "[%s] %.0f up (kbps)", networkEntity.second.m_name, networkEntity.second.m_up); + } + + AZ::Vector3 entityPosition = AZ::Vector3::CreateZero(); + constexpr bool centerText = true; + AZ::TransformBus::EventResult(entityPosition, networkEntity.first, &AZ::TransformBus::Events::GetWorldTranslation); + m_debugDisplay->DrawTextLabel(entityPosition, 1.0f, m_statusBuffer, centerText, 0, 0); + } + + m_debugDisplay->SetState(stateBefore); } } diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.h b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.h index d6ceaaf04c..8a33bc78ee 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.h +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugPerEntityReporter.h @@ -11,7 +11,6 @@ #include #include -#include #include #include #include @@ -66,7 +65,7 @@ namespace Multiplayer float m_down = 0.f; }; - AZStd::fixed_unordered_map m_networkEntitiesTraffic; + AZStd::unordered_map m_networkEntitiesTraffic; AzFramework::DebugDisplayRequests* m_debugDisplay = nullptr; }; diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp index 03d79025f7..f892ee9724 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp @@ -13,6 +13,11 @@ #include #include +void OnDebugNetworkEntity_ShowBandwidth_Changed(const bool& showBandwidth); + +AZ_CVAR(bool, net_DebugNetworkEntity_ShowBandwidth, false, &OnDebugNetworkEntity_ShowBandwidth_Changed, AZ::ConsoleFunctorFlags::Null, + "If true, prints bandwidth values over entities that use a considerable amount of network traffic"); + namespace Multiplayer { void MultiplayerDebugSystemComponent::Reflect(AZ::ReflectContext* context) @@ -53,11 +58,20 @@ namespace Multiplayer #endif } - void MultiplayerDebugSystemComponent::OnImGuiInitialize() + void MultiplayerDebugSystemComponent::ShowEntityBandwidthDebugOverlay() { m_reporter = AZStd::make_unique(); } + void MultiplayerDebugSystemComponent::HideEntityBandwidthDebugOverlay() + { + m_reporter.reset(); + } + + void MultiplayerDebugSystemComponent::OnImGuiInitialize() + { + } + #ifdef IMGUI_ENABLED void MultiplayerDebugSystemComponent::OnImGuiMainMenuUpdate() { @@ -327,15 +341,32 @@ namespace Multiplayer if (m_displayPerEntityStats) { - //ImGui::SetNextWindowSize({500, 400}); + // This overrides @net_DebugNetworkEntity_ShowBandwidth value if (ImGui::Begin("Multiplayer Per Entity Stats", &m_displayPerEntityStats, ImGuiWindowFlags_AlwaysAutoResize)) { if (m_reporter) { m_reporter->OnImGuiUpdate(); } + else + { + ShowEntityBandwidthDebugOverlay(); + } } } } #endif } + +void OnDebugNetworkEntity_ShowBandwidth_Changed(const bool& showBandwidth) +{ + if (showBandwidth) + { + AZ::Interface::Get()->ShowEntityBandwidthDebugOverlay(); + } + else + { + AZ::Interface::Get()->HideEntityBandwidthDebugOverlay(); + } +} + diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.h b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.h index a7f76e075a..87b238c79b 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.h +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.h @@ -9,7 +9,9 @@ #pragma once #include +#include #include +#include #ifdef IMGUI_ENABLED # include @@ -20,6 +22,7 @@ namespace Multiplayer { class MultiplayerDebugSystemComponent final : public AZ::Component + , public AZ::Interface::Registrar #ifdef IMGUI_ENABLED , public ImGui::ImGuiUpdateListenerBus::Handler #endif @@ -30,7 +33,7 @@ namespace Multiplayer static void Reflect(AZ::ReflectContext* context); static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided); static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required); - static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatbile); + static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible); ~MultiplayerDebugSystemComponent() override = default; @@ -40,6 +43,12 @@ namespace Multiplayer void Deactivate() override; //! @} + //! IMultiplayerDebugSystem overrides + //! @{ + void ShowEntityBandwidthDebugOverlay() override; + void HideEntityBandwidthDebugOverlay() override; + //! @} + #ifdef IMGUI_ENABLED //! ImGui::ImGuiUpdateListenerBus overrides //! @{ diff --git a/Gems/Multiplayer/Code/multiplayer_files.cmake b/Gems/Multiplayer/Code/multiplayer_files.cmake index 7392ea6856..0b2adb1530 100644 --- a/Gems/Multiplayer/Code/multiplayer_files.cmake +++ b/Gems/Multiplayer/Code/multiplayer_files.cmake @@ -8,6 +8,7 @@ set(FILES Include/Multiplayer/IMultiplayer.h + Include/Multiplayer/IMultiplayerDebug.h Include/Multiplayer/IMultiplayerTools.h Include/Multiplayer/MultiplayerConstants.h Include/Multiplayer/MultiplayerStats.h