GDNative, C++; "Your first 3D Game" crashes when mob->initialize is called?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By *_C

Hello all, Godot beginner here. I ran into an issue yesterday or so that I am utterly confused on how to solve. Here it is:

I’m using Godot 3.5.1 (stable), linux edition. I am trying to complete the “Your first 3D game” tutorial on the Godot docs using C++ (GDNative) only. Upon completing the “Spawning monsters” section however, my game would crash whenever the _on_MobTimer_timeout() method was called. After various tests, I learned that, for some reason, it was because none of my member variables (_random, _velocity, min_speed, and max_speed) could be accessed within my _initialize method, and if I were to remove them (define a local _random inside the method, make _velocity a property and use get(“_velocity”) and set("_velocity, …), and replace min_speed and max_speed with constants [10 and 18]), then the program would not only not crash, but would run like clockwork. Today I did further testing and generated this when I ran Godot from the terminal:

Running: /app/bin/godot-bin --path /home/x/Projects/Godot%20Projects/squash_the_creeps/project --remote-debug 127.0.0.1:6007 --allow_focus_steal_pid 37 --position 600,270
Godot Engine v3.5.1.stable.flathub.6fed1ffa3 - https://godotengine.org
libGL error: failed to create dri screen
libGL error: failed to load driver: nouveau
OpenGL ES 2.0 Renderer: Mesa Intel(R) UHD Graphics (CML GT2)

ERROR: NativeScriptInstance detected crash on method: _on_MobTimer_timeout
at: notification (modules/gdnative/nativescript/nativescript.cpp:758)

================================================================
handle_crash: Program crashed with signal 11
Engine version: Godot Engine v3.5.1.stable.flathub (6fed1ffa313c6760fa88b368ae580378daaef0f0)
Dumping the backtrace. Please include this when reporting the bug on: Issues · godotengine/godot · GitHub
[1] /usr/lib/x86_64-linux-gnu/libc.so.6(+0x39510) [0x7f15459e8510] ()
[2] godot::RandomNumberGenerator::randf_range(float, float) ()
[3] Mob::initialize(godot::Vector3, godot::Vector3) ()
[4] Main::_on_MobTimer_timeout() ()
[5] godot_variant godot::__wrapped_method<Main, void>(void*, void*, void*, int, godot_variant**) ()
[6] /app/bin/godot-bin() [0xef3e2a] ()
[7] /app/bin/godot-bin() [0x2e60e5e] ()
[8] /app/bin/godot-bin() [0x2e6bad1] ()
[9] /app/bin/godot-bin() [0x2e6c8a3] ()
[10] /app/bin/godot-bin() [0x1faff72] ()
[11] /app/bin/godot-bin() [0x1f562c6] ()
[12] /app/bin/godot-bin() [0x1f6bdfe] ()
[13] /app/bin/godot-bin() [0xaa227a] ()
[14] /app/bin/godot-bin() [0xa10c05] ()
[15] /usr/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0) [0x7f15459d2b80] ()
[16] /app/bin/godot-bin() [0xa23d6e] ()
– END OF BACKTRACE –
================================================================

With all that said, I’ve tried all I could fathom and I’m still stumped, so maybe some Godot experts can solve my conundrum? My basic questions are as follows:

  1. Why did this happen?
  2. How do I prevent this from happening in the future?
  3. Is this a bug that I should report?

Thanks in advance for any answers all :slight_smile:


Files:

Mob.hpp:

#ifndef MOB_H
#define MOB_H

 #include <Godot.hpp>
 #include <KinematicBody.hpp>
 #include <RandomNumberGenerator.hpp>


 class Mob : public godot::KinematicBody
 {
    GODOT_CLASS(Mob, godot::KinematicBody)

    godot::Vector3 _velocity;
    godot::Ref<godot::RandomNumberGenerator> _random;

  public:
    int min_speed;
    int max_speed;

    Mob();
    ~Mob() {}

     void _init() {}
     void initialize(godot::Vector3, godot::Vector3);
     void _on_VisibilityNotifier_screen_exited();
     void _physics_process(float);
     static void _register_methods();
};

#endif

Mob.cpp:

#include "mob.hpp"


Mob::Mob()
{
	_random = (godot::Ref<godot::RandomNumberGenerator>)godot::RandomNumberGenerator::_new();
	_random->randomize();
	
	min_speed = 10;
	max_speed = 18;
	_velocity = godot::Vector3::ZERO;
}

void Mob::_physics_process(float delta)
{
	move_and_slide(_velocity);
	return;
}

void Mob::initialize(godot::Vector3 start_position, godot::Vector3 player_position)
{		
	look_at_from_position(start_position, player_position, godot::Vector3::UP);
	rotate_y(_random->randf_range(-3.14f / 4, 3.14f / 4));
	
	float random_speed = (float)_random->randf_range(min_speed, max_speed);
	_velocity = godot::Vector3::FORWARD * random_speed;
	_velocity = _velocity.rotated(godot::Vector3::UP, get_rotation().y);
		
	return;
}

void Mob::_on_VisibilityNotifier_screen_exited()
{
	queue_free();
	return;
}

void Mob::_register_methods()
{
	godot::register_method("_physics_process", &Mob::_physics_process);
	godot::register_method("_on_VisibilityNotifier_screen_exited", &Mob::_on_VisibilityNotifier_screen_exited);
	
	godot::register_property("min_speed", &Mob::min_speed, 10);
	godot::register_property("max_speed", &Mob::max_speed, 18);
	
	return;
}

Main.hpp:

#ifndef MAIN_H
#define MAIN_H

#include <Godot.hpp>
#include <Node.hpp>
#include <PackedScene.hpp>
#include <RandomNumberGenerator.hpp>
#include <PathFollow.hpp>
#include "player.hpp"
#include "mob.hpp"


class Main : public godot::Node
{
	GODOT_CLASS(Main, godot::Node)
			
	godot::Ref<godot::RandomNumberGenerator> _random;
	Player * _player;
			
public:
	godot::Ref<godot::PackedScene> mob_scene;
	
	void _init() {}
	void _ready();
	void _on_MobTimer_timeout();
	static void _register_methods();
};

#endif

Main.cpp:

#include "main.hpp"


void Main::_ready()
{
	_random = (godot::Ref<godot::RandomNumberGenerator>)godot::RandomNumberGenerator::_new();
	_random->randomize();
	_player = get_node<Player>("Player");
	return;
}

void Main::_on_MobTimer_timeout()
{	
	// Create new instance of the mob
	Mob * mob = static_cast<Mob*>(mob_scene->instance());
	
	// Choose random location on spawn path
	godot::PathFollow * mob_spawn_location = get_node<godot::PathFollow>("SpawnPath/SpawnLocation");
	
	// Give spawn location a random offset
	mob_spawn_location->set_unit_offset(_random->randf());
	
	godot::Vector3 player_position = _player->get_transform().origin;

	mob->initialize(mob_spawn_location->get_translation(), player_position);
	
	add_child(mob);
	return;
}

void Main::_register_methods()
{
	godot::register_method("_ready", &Main::_ready);
	godot::register_method("_on_MobTimer_timeout", &Main::_on_MobTimer_timeout);
	
	godot::register_property("mob_scene", &Main::mob_scene, (godot::Ref<godot::PackedScene>)nullptr);
	return;
}