How do I get my ContactModifyCallback to work?

I have a class MyContactModifyCallback, which inherits PxContactModifyCallback, I don’t know how to make it work in the ue4 project.

class MyContactModifyCallback : public PxContactModifyCallback
{
public:
	virtual void onContactModify(PxContactModifyPair* const pairs, PxU32 count)
	{
		UE_LOG(LogTemp, Error, TEXT("bbbbbbbbbbb"))
		for (PxU32 i = 0; i < count; i++)
		{
			auto p = pairs[i];
			for (PxU32 j = 0; j < p.contacts.size(); j++)
				p.contacts.ignore(j);
		}
	}
};

I tried to set it like this in GameMode.InitGame, but it didn’t work.

void AtestGameMode::InitGame(const FString& MapName, const FString& Options, FString& ErrorMessage)
{
	AGameModeBase::InitGame(MapName, Options, ErrorMessage);

	auto s = this->GetWorld()->GetPhysicsScene(); 
	printf("%p", s);
	s->GetPxScene()->setContactModifyCallback(new MyContactModifyCallback());
}

Anybody help?

Im not too familiar with PhysX, but docs say:

You can enable the use of this contact modification callback by raising the flag [PxPairFlag::eMODIFY_CONTACTS] in the filter shader/callback (see
PxSimulationFilterShader] for a pair of rigid body objects.

PhysX doc

Thanks, But I still don’t know how do I get it to work in UE4

Finally, I find a way to make it worked.

// Fill out your copyright notice in the Description page of Project Settings.

#pragma optimize("", off)

#include "MyWorldSettings.h"
#include <PhysXPublicCore.h>
#include "Physics/PhysicsFiltering.h"

PxFilterFlags PxSimulationFilterShaderProc(PxFilterObjectAttributes attributes0, PxFilterData filterData0,
	PxFilterObjectAttributes attributes1, PxFilterData filterData1,
	PxPairFlags& pairFlags, const void* constantBlock, PxU32 constantBlockSize)
{
	pairFlags = physx::PxPairFlag::eCONTACT_DEFAULT;
	pairFlags |= physx::PxPairFlag::eDETECT_CCD_CONTACT;
	pairFlags |= physx::PxPairFlag::eNOTIFY_CONTACT_POINTS;
	pairFlags |= physx::PxPairFlag::eMODIFY_CONTACTS;  //necessary

    PxFilterFlags ret = PxFilterFlag::eDEFAULT;
    return ret;
}

class MyContactModifyCallback : public FContactModifyCallback
{
public:
	void onContactModify(PxContactModifyPair* const pairs, PxU32 count)
	{
		for (PxU32 i = 0; i < count; i++)
		{
			PxContactModifyPair& pair = pairs[i];
			for (PxU32 j = 0; j < pair.contacts.size(); j++)
			{
				// code your filter codes
				//pair.contacts.ignore(j);
			}
		}
	}
};

class MyContactModifyCallbackFactory : public IContactModifyCallbackFactory
{
public:
	FContactModifyCallback* Create(FPhysScene_PhysX* PhysScene)
	{
		return new MyContactModifyCallback();
	}

	void Destroy(FContactModifyCallback* Callback)
	{
		delete Callback;
	}
};


AMyWorldSettings::AMyWorldSettings(const FObjectInitializer& ObjectInitializer)
	: AWorldSettings(ObjectInitializer)
{
	GSimulationFilterShader = PxSimulationFilterShaderProc;
	FPhysScene_PhysX::ContactModifyCallbackFactory = TSharedPtr<IContactModifyCallbackFactory>(new MyContactModifyCallbackFactory());
	
}

This example is taking effect only if the following conditions are reached.

  1. ’ Edit → Project Settings → General Settings → Default Classes → World Settings Class ’ be set of ‘AMyWorldSettings’ .
  2. ‘Simulate Physics’ be set of true.
  3. Physics Collision enabled.
  4. Add module ‘PhysicsCore’ in xxx.Build.cs.
1 Like

Thank you, this is great stuff!

I wanted to add that the function outlined here, PxSimulationFilterShaderProc(), which sets up the pair flags etc. should probably be an exact copy of PhysXSimFilterShader() in the engine (not just setting the 4 pair flags as outlined here) so collisions behave “normally”. Then, the “modify contacts” flag needs to be added of course.