Landscape Patches - Difficulties with C++ subclasses

Our project has made use of some custom landscape texture patch classes written in C++ since UE 5.3. However, it seems that the C++ API for landscape patches is becoming more restricted each engine upgrade we take.

  • With UE 5.5, the internal heightmap and weightmap textures became private members and the accessor functions for them are also private (ULandscapeTexturePatch::GetHeightInternalTexture and ULandscapeTexturePatch::GetWeightPatchInternalTexture). We’ve worked around this by making local modifications to make the accessor functions protected.
  • With UE 5.6, we ran into many linker errors due to the ULandscapePatchComponent class being updated with the MinimalAPI UCLASS specifier. Many of the crucial functions such as SetIsEnabled and SetPriority are not virtual and as such are no longer exported. We’ve worked around this locally by adding back in the LANDSCAPEPATCH_API decorator to the class, but also understand that this may not be a feasible solution in general when trying to manage the number of module exports.

As of UE 5.6, it seems like the BP interface is more supported than the native C++ interface, as many of the crucial functions that aren’t exported are still exposed as UFUNCTIONs. Is the goal long-term to only allow landscape texture patches to be derived from render-target-backed BP assets, or will the native C++ API eventually be brought back up to parity in a future engine update? We have editor performance and code maintenance concerns about our custom texture patch types if we are forced to use BP graph implementations.

Hi Jeff, thanks for reaching out and sorry about the pains.

No, there is no goal to constrain the patches to BP usage- this was just a result of the plugin being marked experimental (so we did not have our usual constraints for changes) while continuing to be used in BP’s internally. So, the BP operation stayed stable while the C++ compatibility changed. I think we would have been more conservative with changes on the C++ side (despite the experimental tag) if we had been more aware of licensees subclassing them.

With all that said, we plan to keep landscape patches stable, so we will bring the C++ side up to parity for 5.7. Sorry that it is too late to do this for 5.6.

We’ll probably be pretty conservative about it, but if you’d like to list out the specific functions/fields you’re using (aside from the ones you listed above), it might help to make sure we don’t miss anything. Similarly, it might help to have a sense of what your subclasses are doing, if you think you might be relying on anything odd.

Thanks!

Thanks for the info!

The two major systems we have that interact with landscape patches are:

  • A subsystem that enables and disables patches in response to certain editor events. This subsystem will need access to ULandscapePatchComponent::SetIsEnabled() and ULandscapePatchComponent::RequestLandscapeUpdate()
  • A C++ class that derives from ULandscapeTexturePatch, which adjusts the heightmap and weightmaps based on an associated spline component. It effectively mimics the behavior of landscape splines, but allows us to properly prioritize its operations when other overlapping landscape patches are involved. Our spline patch class is set to InternalTexture mode, so we require direct read and write access to the heightmap and weightmap textures. Ideally for our usage, ULandscapeTexturePatch::GetHeightInternalTexture() and ULandscapeTexturePatch::GetWeightPatchInternalTexture() would be protected instead of private.

Outside of those specific functions, I think anything used by patch components’ virtual functions will also need to be exposed. In stock UE 5.6 just making a trivial class that derives from ULandscapeTexturePatch results in a large number of linker errors.

Ok, thank you for the extra information- we’ll do this for 5.7.

FYI, we have already fixed the fact that landscape patches couldn’t be inherited from in 5.6 in the following commit : https://github.com/EpicGames/UnrealEngine/commit/470639b63a24c60b6161019f0c5d6126d716073d. The fact that we removed dll-exposure at the class level in 5.6 stems from a company-wide policy to reduce symbol bloat and since landscape patches were still experimental, I did this manually and didn’t go the extra mile to check every public function out there.

I don’t see a problem with exposing the SetIsEnabled and RequestLandscapeUpdate. If they’re exposed to BP, they probably should be dll-exported anyway, as BP is usually seen as the highest level API.

As for exposing GetHeight/WeightPatchInternalTexture, it’s a little more problematic because of the internal complexity of the patch texture handling but making them protected rather than private seems acceptable still.

Like Semion said, we’ll try to get this done for 5.7 since we are hoping to make the landscape patch plugin non-experimental by then. Please let us know if you need additional things from the API by then. Here’s the public JIRA for tracking : Unreal Engine Issues and Bug Tracker (UE\-308744)

Cheers,

Jonathan