How to get a custom C++ entity moving with physics?

I’m hoping I can get some help in figuring out why my custom entity is not being affected by gravity (or physics at all, really).

I’ve declared it as such in MyEntity.h


struct CMyEntity : CGameObjectExtensionHelper < CMyEntity, IGameObjectExtension >
{
public:
DECLARE_COMPONENT_TYPE("MyEntity", 0x74AE137B221D4EA2, 0xBF2013D11318D660)
MyEntity();
~MyEntity();

To save on space, I’ve already gone ahead and pulled in the rest of the virtual parent functions from IGameObjectExtension that needed to be overridden.

In my “TestGame.cpp”, in TestGame.Init(IGameFramework* framework) I am registering the game object extension:

REGISTER_GAME_OBJECT_EXTENSION(m_gameFramework, "MyEntity", MyEntity, "Entities/Scripts/MyEntity.lua");

I am able to drag and drop the entity from the editor, and it is created, and I have verified that my Entity’s Init, PostInit, and Update’s are all working. My custom code under the hood is executing fine and the entity is drawing with the correct model/rotation/position, etc.

However it just won’t physicalize. I’ve tried it the C++ way in PostInit:

	void CMyEntity::PostInit(IGameObject* pGameObject)
{
pGameObject->EnableUpdateSlot(this, 0);
pGameObject->EnablePostUpdates(this);
SEntityPhysicalizeParams PhysParams;
PhysParams.mass = 50;
PhysParams.type = PE_RIGID;
GetEntity()->Physicalize(PhysParams);
pe_simulation_params simParams;
simParams.gravity = gEnv->pPhysicalWorld->GetPhysVars()->gravity;
GetEntity()->GetPhysics()->SetParams(&simParams);
CGameObjectExtensionHelper::PostInit(pGameObject);
}

And according to what tiny few CryENGINE tutorials I can find, this should be it. From here, it’s supposed to “just work”. The LUA’s OnInit looks like this, for record:

  function MyEntity:OnInit()
self:SetName( "MyEntity" );
self:LoadObject( 0, self.Properties.fileModelName);
self:DrawSlot(0, 1);
end

I’ve tried calling EntityCommon.PhysicalizeRigid in there but that also does not seem to work. Once the game is started in editor (CTRL+G), the object just floats. I’ve tried using both my custom model (which is just a FBX imported to CGF), and I’ve also tried using the default primitive_sphere.cgf. If I drag and drop in a RigidBodyEx from the editor window, and give it primitive_sphere.cgf, it falls with gravity as expected… just not when I’m using my custom entity.

What am I missing here?

EDIT: Seems the forum Code block is absolutely useless so my code looks a bit wonky

EDIT 2: I’ve also attempted to just apply an impulse action in my CMyEntity::Update(). Breakpoints and judicious use of CryLog confirm that the code is being executed, it just does nothing:

	pe_action_impulse impulse;
impulse.impulse.z = 20;
impulse.angImpulse = Vec3(0.0, 0.0, 10.0);
GetEntity()->GetPhysics()->Action(&impulse);

Adding the manual awake after physicalizing did not fix it, but I found that if I removed the MyEntity:OnInit() from the lua script and instead put

GetEntity()->LoadGeometry(0, "Objects/default/primitive_sphere.cgf");

into my PostInit() but before Physicalize(), the sphere mesh now shows up and falls with gravity!Just as a test, I put LoadGeometry() after Physicalize() and it failed to fall with gravity (in the awake action, m_nColliders as 0 and m_pColliders was nullptr!). It seems my problem was that, taking a shot in the dark here, the Lua implementation to LoadObject was executing after the C++ PostInit’s Physicalize was called and it had no colliders generated? I’m not sure what order the lua/C++ code is executed in, but it seems that moving the loading entirely into C++ side has started working.

As a side note, setting p_draw_helpers 1 on throws an assert:

Condition: fabs_tpl(det)>(F)0.00000001
File: d:\lumberyard\dev\code\cryengine\crycommon\Cry_Matrix34.h
Line: 739

Presumably because I’m running in full debug (not profile). If I ignore all I still get the physics proxy drawing though. I am seeing it for the primitive_sphere now, though not my custom mesh. That at least tells me that I need to get back to my artist and have them export this properly :smiley:

Hello @kveilleux,

I’m passing this question along to other Lumberyard devs hoping to get an answer or some direction for you. When I hear anything back, I’ll be in touch again.

Thanks!

We may need more context to track down the issue in your case, but aAs an experiment, can you try to manually wake up the object after physicalizing?

pe_action_awake wake; wake.bAwake = 1;
GetEntity()->GetPhysics()->Action(&wake);

If that doesn’t solve your issue, we can definitely do further investigation. You can also try entering “p_draw_helpers 1” in the console (bring up the console by hitting the tilda key ‘~’), in case the object is physical but somehow the visual elements aren’t being updated.

Great to hear you solved your issue! It’s definitely the case that GetEntity()->Physicalize(…) won’t have much to do if you haven’t yet assigned geometry that contains physical data.

In CComponentPhysics::AddSlotGeometry:

	IStatObj *pStatObj = m_pEntity->GetStatObj(nSlot | ENTITY_SLOT_ACTUAL & -bNoSubslots);
if (!pStatObj)
return -1;

If you called Physicalize() prior to calling LoadGeometry(), it was likely hitting this case. LoadGeometry() won’t implicitly physicalize if the object was already physicalized, simply because it doesn’t infer the settings you’d like; you may have swapped between articulated and rigid physics, for example.

If there’s anything you feel would’ve made it easier to track down the issue, please let us know so we can make it easier in the future. We definitely have plans to make physics in general much easier to leverage, so it should only get easier from here :slight_smile: