UWorldPartition::GetIntersectingCells for UWorldPartitionRuntimeHashSet::ForEachStreamingCellsQuery incorrectly handles bDataLayersOnly

If you try to query against cells with DataLayers, even if you set bDataLayersOnly=false it will fail because of the else if branch that should just be an if.

Inside UWorldPartitionRuntimeHashSet::ForEachStreamingCells the ShouldAddCell lambda:

	auto ShouldAddCell = [this](const UWorldPartitionRuntimeCell* Cell, const FWorldPartitionStreamingQuerySource& QuerySource)
	{
		if (IsCellRelevantFor(Cell->GetClientOnlyVisible()))
		{
			if (Cell->HasDataLayers())
			{
				if (Cell->GetDataLayers().FindByPredicate([&](const FName& DataLayerName) { return QuerySource.DataLayers.Contains(DataLayerName); }))
				{
					return true;
				}
			}
			else if (!QuerySource.bDataLayersOnly) // Issue here
			{
				return true;
			}
		}

		return false;
	}

[Attachment Removed]

Steps to Reproduce
NA

[Attachment Removed]

Hello!

I would like to clarify the intent. What understand is that you would like to include all cells that have datalayers without having to specify a list in the QuerySource. This would require adding a new setting in FWorldPartitionStreamingQuerySource .

	auto ShouldAddCell = [this](const UWorldPartitionRuntimeCell* Cell, const FWorldPartitionStreamingQuerySource& QuerySource)
	{
		if (IsCellRelevantFor(Cell->GetClientOnlyVisible()))
		{
			if (Cell->HasDataLayers())
			{
				//Include any cell that has Datalayers
				if (QuerySource.bIncludeAnyDataLayer)
				{
					return true;
				}
 
				if (Cell->GetDataLayers().FindByPredicate([&](const FName& DataLayerName) { return QuerySource.DataLayers.Contains(DataLayerName); }))
				{
					return true;
				}
			}
			else if (!QuerySource.bDataLayersOnly) // Issue here
			{
				return true;
			}
		}
 
		return false;
	}

Is this the behavior you are looking for?

Martin

[Attachment Removed]

A new setting would work as well, but the comments on the code for the data layer properties read to be that if bDataLayersOnly=false than the DataLayers would be ignored. Happy with either solution, both will work for us :slight_smile:

	/* Optional list of data layers to specialize the query. If empty only non data layer cells will be returned by the query. */
	UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Query")
	TArray<FName> DataLayers;
 
	/* If True, Only cells that are in a data layer found in DataLayers property will be returned by the query. */
	UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Query")
	bool bDataLayersOnly;

[Attachment Removed]

Thanks for confirming. I need to validate with the owner of this code. The comment on DataLayers is what is making me hesitate. It does say that an empty array means that non data layers cells are targeted. I wouldn’t want to introduce bugs for licensees that count on that behavior.

[Attachment Removed]

Hello!

After discussing with the engine team, it was agreed that adding a new option is safer. You can grab CL52760639.

The behavior is:

  • bIncludeAnyDataLayer=true + bDataLayersOnly=true --> returns only cells with data layers (any DL), excludes non-DL cells
  • bIncludeAnyDataLayer=true + bDataLayersOnly=false --> effectively returns ALL cells (DL cells pass via short-circuit, non-DL cells pass via the else branch)
  • bIncludeAnyDataLayer=true + DataLayers populated --> the DataLayers array is silently ignored

Regards,

Martin

[Attachment Removed]

Thank you for the help!

[Attachment Removed]