diff --git a/CHANGES.md b/CHANGES.md index 4c2eda899..9ceca5979 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,7 @@ # Change Log {#changes} +- adding a function to change the collision response of a Cesium3DTileset by collision channel. + ### v2.20.0 - 2025-10-01 ##### Additions :tada: diff --git a/Source/CesiumRuntime/Private/Cesium3DTileset.cpp b/Source/CesiumRuntime/Private/Cesium3DTileset.cpp index 07554d883..24bbca0ed 100644 --- a/Source/CesiumRuntime/Private/Cesium3DTileset.cpp +++ b/Source/CesiumRuntime/Private/Cesium3DTileset.cpp @@ -146,10 +146,11 @@ void ACesium3DTileset::SampleHeightMostDetailed( positions.reserve(LongitudeLatitudeHeightArray.Num()); for (const FVector& position : LongitudeLatitudeHeightArray) { - positions.emplace_back(CesiumGeospatial::Cartographic::fromDegrees( - position.X, - position.Y, - position.Z)); + positions.emplace_back( + CesiumGeospatial::Cartographic::fromDegrees( + position.X, + position.Y, + position.Z)); } auto sampleHeights = [this, &positions]() mutable { @@ -1083,9 +1084,10 @@ void ACesium3DTileset::LoadTileset() { options.requestHeaders.reserve(this->RequestHeaders.Num()); for (const auto& [Key, Value] : this->RequestHeaders) { - options.requestHeaders.emplace_back(CesiumAsync::IAssetAccessor::THeader{ - TCHAR_TO_UTF8(*Key), - TCHAR_TO_UTF8(*Value)}); + options.requestHeaders.emplace_back( + CesiumAsync::IAssetAccessor::THeader{ + TCHAR_TO_UTF8(*Key), + TCHAR_TO_UTF8(*Value)}); } switch (this->TilesetSource) { @@ -1559,9 +1561,10 @@ ACesium3DTileset::CreateViewStateFromViewParameters( glm::dvec3 tilesetCameraLocation = glm::dvec3( unrealWorldToTileset * glm::dvec4(camera.Location.X, camera.Location.Y, camera.Location.Z, 1.0)); - glm::dvec3 tilesetCameraFront = glm::normalize(glm::dvec3( - unrealWorldToTileset * - glm::dvec4(direction.X, direction.Y, direction.Z, 0.0))); + glm::dvec3 tilesetCameraFront = glm::normalize( + glm::dvec3( + unrealWorldToTileset * + glm::dvec4(direction.X, direction.Y, direction.Z, 0.0))); glm::dvec3 tilesetCameraUp = glm::normalize( glm::dvec3(unrealWorldToTileset * glm::dvec4(up.X, up.Y, up.Z, 0.0))); @@ -2315,3 +2318,49 @@ void ACesium3DTileset::RuntimeSettingsChanged( } } #endif + +void ACesium3DTileset::SetCollisionResponseToChannel( + ECollisionChannel Channel, + ECollisionResponse NewResponse) { + // Update the tileset's BodyInstance for future tiles + BodyInstance.SetResponseToChannel(Channel, NewResponse); + + // Get all loaded glTF components + TArray GltfComponents; + GetComponents(GltfComponents); + + // Apply settings to existing tiles + for (UCesiumGltfComponent* Gltf : GltfComponents) { + if (Gltf && IsValid(Gltf)) { + applyActorCollisionSettings(BodyInstance, Gltf); + } + } + + // Force refresh on each primitive component + for (UCesiumGltfComponent* Gltf : GltfComponents) { + if (Gltf && IsValid(Gltf)) { + const TArray& Children = Gltf->GetAttachChildren(); + for (USceneComponent* Child : Children) { + UCesiumGltfPrimitiveComponent* Prim = + Cast(Child); + if (Prim && IsValid(Prim)) { + // Set to Custom profile if not already, to allow per-channel changes + Prim->SetCollisionProfileName("Custom"); + + // Set the specific channel response + Prim->SetCollisionResponseToChannel(Channel, NewResponse); + + // Update collision profile to apply changes + Prim->UpdateCollisionProfile(); + + // Toggle collision enabled to force refresh + Prim->SetCollisionEnabled(ECollisionEnabled::NoCollision); + Prim->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics); + + // Recreate physics state for final application + Prim->RecreatePhysicsState(); + } + } + } + } +} \ No newline at end of file diff --git a/Source/CesiumRuntime/Public/Cesium3DTileset.h b/Source/CesiumRuntime/Public/Cesium3DTileset.h index 2aa951bb1..f0e893dc1 100644 --- a/Source/CesiumRuntime/Public/Cesium3DTileset.h +++ b/Source/CesiumRuntime/Public/Cesium3DTileset.h @@ -138,6 +138,30 @@ class CESIUMRUNTIME_API ACesium3DTileset : public AActor { const TArray& LongitudeLatitudeHeightArray, FCesiumSampleHeightMostDetailedCallback OnHeightsSampled); + /** + * @brief Sets the collision response of this tileset to a specific collision + * channel at runtime. This updates the actor's BodyInstance for future-loaded + * tiles and propagates the change to all currently loaded tiles by refreshing + * their primitive components, ensuring consistent collision behavior for both + * queries and physics interactions. + * + * The change takes effect immediately after propagation, including recreation + * of physics states on existing primitives. This function is + * blueprint-callable and suitable for dynamic adjustments, such as toggling + * interactions with pawns or projectiles during gameplay. Note that tiles + * must have physics meshes enabled (via CreatePhysicsMeshes) for physical + * collisions to apply. + * + * @param Channel The collision channel to modify (e.g., ECC_Pawn, + * ECC_Visibility). + * @param NewResponse The new response for the channel (e.g., ECR_Block, + * ECR_Ignore). + */ + UFUNCTION(BlueprintCallable, Category = "Cesium|Collision") + void SetCollisionResponseToChannel( + ECollisionChannel Channel, + ECollisionResponse NewResponse); + private: /** * The designated georeference actor controlling how the actor's