Destroying GC with multiple AddPhysicsField doesn't seems to work as intended

Hi,

I observed a difference of behavior between the fieldsystemcomponent/global-AddTransientField and the gc/targeted-AddPhysicsField:

If a GC is partially destroyed by a global field, then a second global field is applied, both are applied as expected

If a GC is partially destroyed by a targeted field, then a second targeted field is applied, the second has no effects (unless the field overlap the gc entirely ?)

In the provided example project, there are the 4 combinations of flat/clustered GC with global/targeted field, with 2 custom MasterField on each. I modified the FS_MasterField as “FS_MasterField_Targeted” to apply only “Dynamic State” and “External Strain” (and skip all others), with a boolean parameter “Global Fields” to switch between FieldSystemComponent->AddTransientField and GeometryCollectionComponent->AddPhysicsField (with the “Target Actor” provided as parameter) to illustrate the behavior.

I used “GC_ChaosPrim_Cuboid_Convex_NoiseGrout” provided with content example, clustered and flattened (in case that had an influence)

To ensure it wasn’t an issue with the second field setup, I tried unchecking “Field Active” on the first one, and in that case the second behave as expected, destroying part of the GC

We are currently using 5.5.1, but I reproduced with 5.6 too, which was used to create the provided project (both “5.6-release” tag and the current last commit on “5.6”, f07fb656e30ea59ce28127ca209d46c80156e1f2)

While we could switch back to global field for now, we hoped having control on which GC the fields are applied to could lead to better performance and better control, considering the list of affected actor is already something we fetch to provide feedback to players ahead of destruction.

Is that a problem on chaos side, or something we are doing wrong ?

Cheers

Maxime

Hello [mention removed]​

Thank you for reaching out.

Thank you for taking the time to create and share this repro project as well.

I was able to replicate the behavior described.

I’m still investigating, but I’ve noticed that DamagePropagation is disabled, so clustered GCs did not propagate the damage up the hierarchy.

If you set Damage Propagation Data > Enabled = true, the behavior on the clustered is similar to the flat GCs.

Let me know if this information is useful.

I’ll keep you informed as I find out more.

All the best,

[mention removed]​

Hello Rafael, and thanks for your reply

I’ve been able to reproduce your suggestion on my side, and indeed turning Propagation on does result in the GC being partially destroyed by both masterfield, but it might be hiding the root cause of the problem:

I took the “Cluster + Targeted” setup of my provided project (and removed the 3 others to reduce the amount of data) with propagation enabled and a 1.0 Break Damage Propagation Factor, and as soon as the first field occurs, in chaos debugger all GC clusters have their “Particle Cluster > External Strains” value jumping above threshold, which I guess is the expected behaviour of propagation. That also mean the GC is effectively “destroyed” internally, and parts that were not affected by the fields are held in place only by their kinematic setting. The second applied field then manage to turn those particles dynamic, and they fall.

[Image Removed]

I might not be using the chaos debugger to its fullest, I have yet to figure how to display parent/child relationship and fields, if supported.

We are trying to keep GC state “under control” considering “making holes” is a key part of the core gameplay. I understand that chaos is still an experimental feature, but it would be great to know if this test case is revealing an unintended behaviour that could be solved engine side, while keeping your suggestion (and/or global fields) as an alternative way to get the expected result.

Cheers

Maxime

Hello Rafael

First of all, thanks for all the time you spent on this. I’ve been able to reproduce what you describe, but I’m really not sure what I’m supposed to from here :smiley:

I’d be grateful if you could escalate the issue, it would be great to know if the behaviour with global and targeted fields are meant to be different

Cheers

Maxime

Hello !

I still did not manage to understand the underlying issue or find a better way to make it work so far, do you know if someone had time to take a look yet ?

Cheers

Max

Hey there,

I received an email stating this case “will be close due to no response”, just adding this message to ensure it does not happen.

Cheers

Maxime

Hi [mention removed]​

I investigated the issue and found the problem

When the field resolution in set to Minimum ( only affect active clusters ) and use “local” fields, the code does not look for internal clusters ( Partial clusters that have been created as a result of a previous fractures )

This does not happen in global fields because they just go through all the solver active particles and the partial clusters will be in the list. But the local fields only scan the particles in the list of pre-created particles in the geometry collection proxy , failing to find the internal clusters

I have a fix that I’m going to submit for the 5.7 release

In the meantime, and if you have access to changing code, you can modify the following method :

FGeometryCollectionPhysicsProxy::GetRelevantParticleHandles

The change is contained to the scope of the Minimal case :

Here’ the changed code :

	else if (ResolutionType == EFieldResolutionType::Field_Resolution_Minimal)
	{
		const auto& Clustering = RigidSolver->GetEvolution()->GetRigidClustering();
		const auto& ClusterMap = Clustering.GetChildrenMap();
 
		for (FClusterHandle* ClusterHandle : SolverParticleHandles)
		{
			if (ClusterHandle)
			{
				FClusterHandle* HandleToAdd = nullptr;
				if (ClusterHandle->Disabled())
				{
					if (FClusterHandle* ParentHandle = ClusterHandle->Parent())
					{
						bool bHasPartialClusterParent = ParentHandle->InternalCluster() && !ParentHandle->Disabled() && (ParentHandle->PhysicsProxy() == ClusterHandle->PhysicsProxy());
						if (bHasPartialClusterParent)
						{
							HandleToAdd = ParentHandle;
						}
					}
				}
				else
				{
					HandleToAdd = ClusterHandle;
				}
				if (HandleToAdd)
				{
					Handles.Add(HandleToAdd);
					if (HandleToAdd->ClusterIds().NumChildren)
					{
						if (ClusterMap.Find(HandleToAdd))
						{
							for (Chaos::FPBDRigidParticleHandle* ChildHandle : ClusterMap[HandleToAdd])
							{
								if (ChildHandle->Disabled())
								{
									Handles.Add(ChildHandle);
								}
							}
						}
					}
				}
			}
		}
	}

I hope this helps

Hello [mention removed]​

I integrated and tested it this morning, it works great !

Thanks a lot for your help

Maxime

Hi both,

@Cedric - much appreciated!

@Maxime - apologies again this was bounced around and took a while to respond to - are you all unblocked now on this issue?

Best

Geoff

Hello [mention removed]​

I confirm that Cedric’s patch fully fixes the issue, this ticket can be closed

Thanks again

Maxime

Hello [mention removed]​

I’ve been trying to debug with ChaosVisualDebugger (CVD).

I’ve also tried to make fields show on CVD, but couldn’t.

Maybe they aren’t supported at this time.

You can enable extra DataChannels, but enabling AccelerationStructures crashed the engine for me.

[Image Removed]With that being said, I’ve noticed that an UnnamedParticle was created once the field broke the GC, and that one had zero ExternalStrain:

[Image Removed]Let’s agree that CVD is not doing a good job of tracking the smaller fragments.

I waited after the first Field was applied, and immediately after, another particle was created, and it looked like it was holding the unaffected clusters:

[Image Removed]That one still had External Strain at zero as well as Internal Cluster true.

A few frames later, I could observe the same as you, each cluster had a very high value in External Strain, and the MObjectState was Kinematic.

Once the second field hits, there are still some clusters that are “Internal” and have zero ExternalStrains:

[Image Removed]It looks like once a part is broken, an UnnamedParticle is created to hold what should remain together.

Let me know if this is useful to you or if you want me to escalate the case to Epic.

I’m sure they would be able to give you more information on the intricacies of this system.

All the best,

[mention removed]​

Hello [mention removed]​

As you requested, I’ve escalated the issue to Epic.

When I do so, it stops showing on my EPS interface, so I don’t have visibility on who took your case.

Hopefully someone will reach out soon, but I’ll ask and let you know if I learn anything new.

Thank you for your patience.

All the best,

[mention removed]​