Is physics really difficult in UE4, or is it just me?

I’m having so many problems trying to get physics working on objects the way I want it to, it’s getting to the point that implementing it myself is starting to look like a faster option. Am I alone? Am I just completely off track?

Things in particular I’m having trouble with (as of 4.7.6):

  • Mass - this seems inconsistent. If I use BlockAll or OverlapAll for collision the mass has a different value. There are also multiple functions to calculate it - CalculateMass and GetMass - what’s the difference?
  • Center of Mass - This changes when I attach objects, even if they have a mass of 0 - why? Even worse, I can’t change the position of the Center of Mass. COMNudge seems to be ignored?
  • AddForce sometimes produces a torque - if I attach some objects to a mesh, then depending on the collision flags I sometimes get a torque. Shouldn’t AddForce apply the force to the center of mass - so no torque?
  • Attaching objects - if I set bWeldSimulatedBodies to false, then the object just doesn’t attach - it sits there while the parent mesh moves off. Why?

Does anyone have any tips?

Failing that feel free to vent. Is Physics really usable in UE4?

I is venting!

Yes physics is usable in unreal but its tricky pony, and stubborn one.
I am doing physics based game and its trail and error, many things just do not add up and are illogical.

for eg. i had asteroids perfectly set up for planar movement (physics constraint) they barely rotated (spinned) no matter what i did.
Then i tried to free them from constraints and add force (push them back to gameplay plane instead of constraining), but it did not work (ebil pendulum effect). All i changed was locked axis in constraint from locked Z to no locked.
So after that small experiment i locked Z axis again and removed correcting force logic. But then they started spin like mad, also sometimes disobeyed constraint.
I think they either rotated with constraint sometimes or plain broke it. Luckily i did backup right before messing with physics.

Also it is quite dangerous to add impulse or force from bp or code. it if just happens that you poke physical object right before it collides you can get quite funny glitches.

So with physics if it works do not try to make it better (without doing backup first).

The thing to remember is that UE4 is using Physx. So go and get the Physx SDK documentation (might be in the libs directory already) and read it for info on how Physx handles things. Read the UE4 calls and see which functions they map to in Physx. The Physx documentation is pretty complete after all.

It should only float if you apply an equal force. But for what timestep are you applying the forces? At least compare the timesteps as these things aren’t always equal. If the force is constant and gravity is constant, then yes it should float, but what if gravity is constant and your force is an impulse applied for a given time?

Again, I point you to the Physx documentation, its not like the Epic guys have any more information than you have. Doesn’t do what you want? you’re welcome to fix it.

I know GetMass() can return 0 at times - I think if the physics aren’t active on the actor. GetMass() is the Physx interface. CalculateMass() is UE4’s attempt to ‘guess’ what GetMass() will be.

I don’t know why you’d expect the components to move together if bWeldSimulatedBodies is false? The component that isn’t welding itself to its parent will then run its physics simulation independent of that parent. If you want it to follow, but not be “welded” then you need some kind of joint?

I don’t know why AddForce is producing torque, nor why 0 mass objects are affecting the center of mass.

Welded simulated bodies don’t work properly either. You end up losing physics properties of all but the the parent object and collision between the pawn and the welded bodies becomes weird. :confused:

I just figured that AttachTo would do just that, attach one object to another so that they move together. I thought the welding was some form of optimisation, given that it’s off by default. Seems like having a function like DoSomethingEssential(bool bYesReallyDoIt). I have turned off physics simulations on the objects being attached, and they just float away.

My aim with this thread wasn’t to trash UE4 btw, I just needed to know that I’m not alone! It’s cheaper than therapy, which I think I’m going to need by the time I figure all this out.

1 Like

I was starting to believe I was alone on this! Thanks for posting this. I sort of felt the same way. My major issue has also has been with things like add force and add force at location, etc

How about this one? Here is a sample project for you all and all I do is drop some grenades and depending on the velocity they fall through the terrain. Just open and run the project with Simulate (the download is only 3.8 MB for the complete project): https://www.dropbox.com/s/79lifwyy3px5q5a/CPP_PenetrateTerrain4.8.7z?dl=0

Any ideas on what is causing this? The only thing that seems to work is to jack up the Physics Sub-stepping in the project settings. I put the value at 0.005 and then they seem to work but it kills the CPU. So any clues on this PhysX issue?

*Please keep in mind that the grenade meshes and textures are Copyrighted materials.

Well you could have tried that too, but actually we’ve been messing around with it. It seems that Use CCD needs to be checked on the Physics asset itself. Doing it in code or BP doesn’t work. Any ideas why?

Ok, I think I’ve had enough of the physics. All I want to do is have a player ship and allow it to attach another mesh component, but the degree of difficulty is insane!

I managed to figure out how to dynamically spawn and attach the objects. It was a bit tricky (ie why is weld off by default??), but I got there, and it didn’t cost me too much time.
Then I noticed that I couldn’t set the mass, or at least it wasn’t responding. Tracked that down to a bug in the PIE Collision code, that took a day or so.
Then I noticed that even though my attached object had a mass of 0.0kg - the center of mass was moving. You can’t set that in UE4, and COMNudge didn’t work. So I disregarded most of the UE4 code and ended up working with PhysX instead.
Then I was getting this odd behaviour if I applied a right handed torque my object would translate. left handed torque was ok. Tracked that down to a slight overlap in collision between the player ship and the attached component. Some sort of warning would have saved me a lot of time.
Now I have the equipment attaching, and I can set the center of mass and moment of inertia. Works fine on the main ship. Problem is even though my attached equipment has a mass of 0.0kg vs the mass of 3000kg of my ship, the player ship can’t budge a 30,000kg asteroid on collision, while my 0kg attachment sends it flying off the screen.

I’m not sure I can take this anymore. We’re early in our project and I’m strongly considering switching to a different engine. This is a CORE component, it really shouldn’t be so hard.

My current plan is to try and write my own physics code. It will be quicker and sufficient for what I need. All I want now from UE4 is just basic collisions. Surely that works… right?

Well this bit of code will fix it regardless of how it is set:



void AThrowable::PreInitializeComponents()
{
	Super::PreInitializeComponents();
	//TRACE("UseCCD Before: MeshBodySetup:%d MeshBodies:%d", (Mesh->BodySetup && Mesh->BodySetup->DefaultInstance.bUseCCD) ? 1 : 0, (Mesh->Bodies.Num() > 0 && Mesh->Bodies[0]->bUseCCD) ? 1 : 0);
	UPhysicsAsset* PhysicsAsset = Mesh->GetPhysicsAsset();
	if (PhysicsAsset)
	{
		bool bUseCCDWasOff = true;
		int32 Count = 0;
		for (UBodySetup* BodySetup : PhysicsAsset->BodySetup)
		{
			if (BodySetup && !BodySetup->DefaultInstance.bUseCCD)
			{
				if (BodySetup->DefaultInstance.GetCollisionEnabled() == ECollisionEnabled::QueryAndPhysics)
				{
					UE_LOG(Throwable, Warning, TEXT("Throwable: BodyIndex%d] Name=%s Use CCD is false on Physics Asset but collision is enabled, Use CCD must be true otherwise this actor will fall through terrain and walls when thrown (we are setting this to true for you but you must set it to true and save it for this asset in the editor)."), Count, *GetHumanReadableName());
					BodySetup->DefaultInstance.bUseCCD = true;
					bUseCCDWasOff = true;
				}
			}
			++Count;
		}
		//If any of the physics bodies had CCD off, we must force reinit the physics asset
		if (bUseCCDWasOff)
		{
			Mesh->SetPhysicsAsset(PhysicsAsset, true);
		}
	}
	//TRACE("UseCCD After: MeshBodySetup:%d MeshBodies:%d", (Mesh->BodySetup && Mesh->BodySetup->DefaultInstance.bUseCCD) ? 1 : 0, (Mesh->Bodies.Num() > 0 && Mesh->Bodies[0]->bUseCCD) ? 1 : 0);
}


Sorry kid bothered me and I couldn’t explain the rest

So here is what I discovered. If it was not checked then it fell through objects. When I set the DefaultInstance above it would be invalid on the first Simulation but not on subsequent ones. When I looked at the Physics asset it would have the Use CCD checked but no star (*) showing it needed to be resaved. Anyhow, the code above will set the default instance one to have CCD on and then all others after this one will be correct because I set the Physics Asset in the code and force a reinitialization (2nd parameter == true).

It just seems like if you set Mesh->BodyInstance.bUseCCD = true; in the constructor that it would work. Well the Physics asset is where it really needs to be set. I’ve noticed that the physics assets and materials really drive a lot of PhysX in UE4. Perhaps that is also the OPs issue, just a lack of understanding in UE4’s way of doing PhysX.

“many people do not have the capability” - erm yes they do. They get the source code. What you are implying is that they don’t have the skill? That’s another matter, but I would note that it’s really not that hard.

I specifically mentioned the documentation for Physx because it might give you some insight into how Unreal Engine’s physics actually works (its using the Physx library to do it, so the documentation regarding how it fundamentally works might be informative). But outside of that, this is YOUR game to make. Isn’t that basically the point of Epic releasing the source in the first place? So you can ultimately take the source and make it do whatever you want.

What you’re really saying here is “I want Epic to make this work for me!” which might be fair for some functionality (stuff they say that should work and doesn’t) but might well not be (stuff that works the way Epic intended but doesn’t match your own games requirements).

Let me just say this. Physx isn’t hard to understand. I’ve read the docs and used it for my own engine a few years back and the docs are 1) Very well written and informative 2) Pretty easy to understand and discuss the edge-cases where things don’t work as intended. Sure, it will take some time and effort, but it is definitely possible for most C++ programmers to understand it.

Well, after spending 2-3 days on trying to get physics to work, I figured out the main cause of my grief was in the welding. Instead I put in a PhysicsConstraint and now it works perfectly.

zoombapup - your advice to look into the physX side of things was very useful to me - I can now set the center of mass and rotational inertia properties which you can’t do otherwise. So thanks for that. While it’s do-able, physics is a core component of any game engine, so it’s really very disappointing to have to have to wrestle and ultimately bypass things that should really just work out the box.

Please share, many will come here based on the keywords… :slight_smile:

Cool. It really is a good set of documentation actually, certainly one of the better middleware’s I’ve used in that sense. Glad you took the plunge, I hope it serves as a guide to others who are struggling to understand the physics engine. To be honest if I were to have an issue with Epic, its less about the physics code so much and more about the lack of decent documentation for it.

Ok, Here’s how I set the Center of Mass based on a socket on my StaticMesh, as well as set the Mass itself correctly:



        FBodyInstance* BodyInst = StaticMeshComponent->GetBodyInstance();
	if (!BodyInst) { return; }
	BodyInst->bOverrideMass = true;
	BodyInst->MassInKg = Mass;
	BodyInst->UpdateMassProperties();
	
	PxRigidBody* PRigidBody = BodyInst->GetPxRigidBody();
	if (!PRigidBody) { return; }

	FVector CenterOfMass = StaticMeshComponent->GetSocketLocation(FName("CenterOfMass"));
	PxVec3 PWorldCOM;
	PWorldCOM.x = CenterOfMass.X;
	PWorldCOM.y = CenterOfMass.Y;
	PWorldCOM.z = CenterOfMass.Z;

	SCOPED_SCENE_READ_LOCK(PRigidBody->getScene());
	PxVec3 PLocalCOM = PRigidBody->getGlobalPose().transformInv(PWorldCOM);

	PRigidBody->setMass(Mass);

	PxTransform trans;
	trans.p = PLocalCOM;
	PRigidBody->setCMassLocalPose(trans);


And here’s how I keep the center of mass and the moment of inertia constant after welding (not that I weld anymore, boo!!):



        // What follows is a hack to prevent the attached component altering the existing physics
	FBodyInstance* BodyInst = StaticMeshComponent->GetBodyInstance();
	if (!BodyInst) { return; }
	PxRigidBody* PRigidBody = BodyInst->GetPxRigidBody();
	if (!PRigidBody) { return; }
	PxTransform CenterOfMass = PRigidBody->getCMassLocalPose();
	PxVec3 InertiaTensor = PRigidBody->getMassSpaceInertiaTensor();
	// -- end hack

        // Attach things here

        // Now restore the previous settings
        PRigidBody->setCMassLocalPose(CenterOfMass);
	PRigidBody->setMassSpaceInertiaTensor(InertiaTensor);


You will need to include these:



#include "PhysXIncludes.h"
#include "PhysicsPublic.h"
#include "Runtime/Engine/Private/PhysicsEngine/PhysXSupport.h"


And you need to add some dependencies in your build file - PhysX and Apex which is just a single line in the file. There is a tutorial (as always) on the topic on the wiki.

As I said though, I found trying to weld bodies together a complete dead end, even with these hacks. Instead I just use a physics constraint component now instead and everything works as advertised.

UPDATE: I was running into some odd bugs with that code. Here’s what I now use to set the Center of mass:



        FVector CenterOfMass = StaticMeshComponent->GetSocketLocation(FName("CenterOfMass"));
	PxVec3 PWorldCOM(CenterOfMass.X, CenterOfMass.Y, CenterOfMass.Z);
	PxScene* Scene = PRigidBody->getScene();
	
	SCENE_LOCK_READ(Scene);
	PxVec3 PLocalCOM = PRigidBody->getGlobalPose().transformInv(PWorldCOM);
	SCENE_UNLOCK_READ(Scene);

	SCENE_LOCK_WRITE(Scene);
	PRigidBody->setMass(Mass);
	PxTransform trans(PLocalCOM);
	PRigidBody->setCMassLocalPose(trans);
	SCENE_UNLOCK_WRITE(Scene);



Bad news, do not use this code in the PreInitializationComponents:



		if (bUseCCDWasOff)
		{
			Mesh->SetPhysicsAsset(PhysicsAsset, true);
		}


Basically something is broken after setting this with the Physics and the velocity was not being set when this code was in there.

Thank you, that will be very informative for others that have the same issues or need to do the same thing. Also, just a clarification, it is APEX not Apex for those who may read this in the future.


PublicDependencyModuleNames.AddRange(new string] { "Core", "CoreUObject", "Engine", "InputCore", "Json", "OnlineSubsystem", "OnlineSubsystemUtils", "PhysX", "RHI", "APEX", "Voice" });

The OverlapAll preset changes the CollisionEnabled property to Query only. This means we do not set a simulation flag on the body (for performance). Typically this is what you want because OverlapAll bodies are used for queries not simulation. So what ends up happening is there is no mass calculated by PhysX. To fix this you need to change CollisionEnabled to “Collision Enabled” which will put the body into the simulation. This is indeed confusing and I’ve added warnings to any physics operation (like GetMass or AddForce) when the body is set to QueryOnly.

I haven’t seen this, but it sounds like a bug. Do you mind creating an answerhub post with this?

The welding code is still in early days. This sounds like a bug, but from your description my guess is that you are calling AddForce on an attached object (i.e. the child object). I’m surprised by this behavior though as when calling AddForce on a welded child we actually use the single welded body under the hood. Do you mind making an answerhub post about this too?

Is the child a simulated body? If you try to attach two simulated bodies without welding it will have no effect. The reason is that without welding the attachment says you want to inherit transforms only. However, this is kind of a vague concept when both objects are simulated since the child now has two locaton inputs (PhysX and its parent)