Godot Version
4.6.1
Question
I’ve been creating a character controller in godot-cpp GDExtension that extends CharacterBody3D. This section of code for creating my collision shape has been giving me trouble. I was under the impression anything that extends resource/refcounted should be instantiated as a Ref like this:
Ref<Class> objectname = memnew(Class);
However, when I try and instantiate my CylinderShape3D for my CollisionShape3D this way, my crouch function later segfaults when I try and access the get_height(); function. However, everything works correctly when I instantiate the CylinderShape3D like this:
CylinderShape3D* objectname = memnew(Class);
Here’s a snip from my _ready() function on my character controller where I am creating my collision shape. I commented out the line that I thought was “correct” but was causing a segfault.
_PlayerCollision = memnew ( CollisionShape3D );
_PlayerCollision -> set_name ( "PlayerCollision" );
add_child ( _PlayerCollision );
_PlayerCollision -> set_owner(get_tree()->get_edited_scene_root());
//working instantiation (Defined as CylinderShape3D* pointer in .h)
_PlayerCylinder = memnew ( CylinderShape3D );
//not working instantiation (defined as Ref<CylinderShape3D> in .h)
//Ref<CylinderShape3D> _PlayerCylinder = memnew ( CylinderShape3D );
_PlayerCylinder -> set_height ( PLAYER_COLLISION_HEIGHT );
_PlayerCylinder -> set_radius ( PLAYER_COLLISION_RADIUS );
_PlayerCollision -> set_shape ( _PlayerCylinder );
And here’s the part of the crouch function causing a segfault when instantiated as a Ref<> but not as a pointer like a node, the crouch function is called once per _physics_process().
_PlayerCylinder->set_height(m_player_cylinder_height);
I think way I am doing it is bypassing the reference count and instantiating it like a node. Am I creating a small memory leak when the CharacterBody3D leaves the scene tree? Should I manually call memfree(); in the destructor if I am doing this?
Why could my Ref<> be producing a nullptr when I call memnew() this way and assign the shape in _ready()? Is it getting garbage collected? I used to call get _PlayerCylinder->get_shape() in _ready() to initialize the Ref when I had the resource as a tscn file, and now I’m trying to instantiate it from code.
EDIT:
After much screwing around, I came to the conclusion that the Ref<> was going out of scope at the end of _Ready(), as it should. Here’s how to initialize in _Ready()
Ref<CylinderShape3D> _PlayerCylinder = memnew ( CylinderShape3D );
_PlayerCylinder -> set_height ( PLAYER_COLLISION_HEIGHT );
_PlayerCylinder -> set_radius ( PLAYER_COLLISION_RADIUS );
_PlayerCollision -> set_shape ( _PlayerCylinder );
and then just make a new Ref in the duck function to reference it
Ref<CylinderShape3D> m_CylinderShape3D = _PlayerCollision -> get_shape ();
m_CylinderShape3D -> set_height ( m_player_cylinder_height );
Feel free to close this thread.