Forráskód Böngészése

Merge pull request #481 from o3de/gadams3/occlusionbus_volumetovolume_extensions

Alternate example of multiplier sample entity filtering component using occlusion culling bus
Guthrie Adams 1 éve
szülő
commit
ef7dcdb7a6

+ 80 - 0
Gem/Code/Source/Components/OcclusionFilteredEntityComponent.cpp

@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include <AzCore/Serialization/EditContext.h>
+#include <AzFramework/Visibility/OcclusionBus.h>
+#include <Components/OcclusionFilteredEntityComponent.h>
+#include <Multiplayer/IMultiplayer.h>
+#include <Multiplayer/Components/NetBindComponent.h>
+
+namespace MultiplayerSample
+{
+    void OcclusionFilteredEntityComponent::Reflect(AZ::ReflectContext* context)
+    {
+        AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
+        if (serializeContext)
+        {
+            serializeContext->Class<OcclusionFilteredEntityComponent, AZ::Component>()
+                ->Version(1);
+
+            if (AZ::EditContext* editContext = serializeContext->GetEditContext())
+            {
+                editContext->Class<OcclusionFilteredEntityComponent>("OcclusionFilteredEntityComponent", "Filters occluded player entities out of network replication")
+                    ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
+                    ->Attribute(AZ::Edit::Attributes::Category, "MultiplayerSample")
+                    ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("Level"))
+                ;
+            }
+        }
+    }
+
+    void OcclusionFilteredEntityComponent::Activate()
+    {
+        AZ::Interface<IFilterEntityManager>::Register(this);
+
+        // Create an occlusion view just for performing clear to player visibility tests.
+        AzFramework::OcclusionRequestBus::Broadcast(&AzFramework::OcclusionRequestBus::Events::CreateOcclusionView, m_occlusionViewName);
+    }
+
+    void OcclusionFilteredEntityComponent::Deactivate()
+    {
+        AZ::Interface<IFilterEntityManager>::Unregister(this);
+        AzFramework::OcclusionRequestBus::Broadcast(&AzFramework::OcclusionRequestBus::Events::DestroyOcclusionView, m_occlusionViewName);
+    }
+
+    bool OcclusionFilteredEntityComponent::IsEntityFiltered(
+        AZ::Entity* entity,
+        Multiplayer::ConstNetworkEntityHandle controllerEntity,
+        [[maybe_unused]] AzNetworking::ConnectionId connectionId)
+    {
+        bool result = false;
+
+        // If one is available, use the occlusion culling system to filter out players that cannot be seen by the controlled player.
+        const auto entityNetBindComponent = entity->FindComponent<Multiplayer::NetBindComponent>();
+        const auto entityConnectionId = entityNetBindComponent ? entityNetBindComponent->GetOwningConnectionId() : AzNetworking::InvalidConnectionId;
+        if (entityConnectionId != AzNetworking::InvalidConnectionId)
+        {
+            AzFramework::OcclusionRequestBus::Broadcast([&](AzFramework::OcclusionRequestBus::Events* occlusionHandler) {
+                // Check for a preexisting occlusion view or create one if necessary.
+                if (!occlusionHandler->IsOcclusionViewValid(m_occlusionViewName))
+                {
+                    occlusionHandler->CreateOcclusionView(m_occlusionViewName);
+                }
+                if (occlusionHandler->IsOcclusionViewValid(m_occlusionViewName))
+                {
+                    // Perform an occlusion query to determine if the controlled entity can see the filtered entity.
+                    const AZStd::vector<bool> visibility = occlusionHandler->GetOcclusionViewEntityToEntityVisibility(
+                        m_occlusionViewName, controllerEntity.GetEntity()->GetId(), AZStd::vector<AZ::EntityId>{ entity->GetId() }
+                    );
+                    // If the query succeeded and the entity cannot be seen then filter it out from network replication.
+                    result = !visibility.empty() && !visibility[0];
+                }
+                });
+        }
+        return result;
+    }
+}

+ 40 - 0
Gem/Code/Source/Components/OcclusionFilteredEntityComponent.h

@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include <AzCore/Component/Component.h>
+#include <Multiplayer/NetworkEntity/IFilterEntityManager.h>
+
+namespace MultiplayerSample
+{
+    //! @class OcclusionFilteredEntityComponent
+    //! @brief An example of using IFilterEntityManager that filters occluded player entities out of network replication.
+    class OcclusionFilteredEntityComponent final
+        : public AZ::Component
+        , public Multiplayer::IFilterEntityManager
+    {
+    public:
+        AZ_COMPONENT(MultiplayerSample::OcclusionFilteredEntityComponent, "{D1C628E6-F165-47F4-9C12-7BA96A80DF50}");
+
+        static void Reflect(AZ::ReflectContext* context);
+
+        //! AZ::Component overrides.
+        //! @{
+        void Activate() override;
+        void Deactivate() override;
+        //! }@
+
+        //! IFilterEntityManager overrides.
+        //! @{
+        bool IsEntityFiltered(AZ::Entity* entity, Multiplayer::ConstNetworkEntityHandle controllerEntity, AzNetworking::ConnectionId connectionId) override;
+        //! }@
+
+    private:
+        const AZ::Name m_occlusionViewName{ "ExampleFilteredEntityView" };
+    };
+}

+ 2 - 0
Gem/Code/Source/MultiplayerSampleModule.cpp

@@ -9,6 +9,7 @@
 #include <AzCore/Module/Module.h>
 #include <Components/AttachPlayerWeaponComponent.h>
 #include <Components/ExampleFilteredEntityComponent.h>
+#include <Components/OcclusionFilteredEntityComponent.h>
 #include <Components/PerfTest/NetworkPrefabSpawnerComponent.h>
 #include <Components/UI/UiCoinCountComponent.h>
 #include <Components/UI/UiGameOverComponent.h>
@@ -44,6 +45,7 @@ namespace MultiplayerSample
                 MultiplayerSampleSystemComponent::CreateDescriptor(),
                 AttachPlayerWeaponComponent::CreateDescriptor(),
                 ExampleFilteredEntityComponent::CreateDescriptor(),
+                OcclusionFilteredEntityComponent::CreateDescriptor(),
                 NetworkPrefabSpawnerComponent::CreateDescriptor(),
                 UiCoinCountComponent::CreateDescriptor(),
                 BackgroundMusicComponent::CreateDescriptor(),

+ 2 - 0
Gem/Code/multiplayersample_files.cmake

@@ -39,6 +39,8 @@ set(FILES
     Source/Components/NetworkWeaponsComponent.h
     Source/Components/NetworkSimplePlayerCameraComponent.cpp
     Source/Components/NetworkSimplePlayerCameraComponent.h
+    Source/Components/OcclusionFilteredEntityComponent.h
+    Source/Components/OcclusionFilteredEntityComponent.cpp
     Source/Components/PerfTest/NetworkPrefabSpawnerComponent.cpp
     Source/Components/PerfTest/NetworkPrefabSpawnerComponent.h
     Source/Components/PerfTest/NetworkRandomImpulseComponent.cpp