[GDNative] Problem with FPS Constroller in C++ but works in GDScript

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

Hi everyone! I’m learning to use Godot with the brand new GDNative (C++17) API and I hit a wall. Been hitting hit for like 4 hours…

I’m following the FPS Tutorial from here but converting GDScript code to C++, which looks mostly the same. But, when I move in any direction, it goes in a weird, unexpected direction. In a hope to know if it’s my code or the engine that’s bugged, I copied the code from the tutorial and replaced my class with it, and it works as expected… Why? What am I doing wrong?

I uploaded the whole project to my Dropbox, with compiled binaries for Windows 64-bit (~2mb) if it is needed.

C++ functions that process movement :

void Player::process_input()
{
	auto xform = _cam->get_global_transform();
	_dir = {};

	auto input_vector = Vector2();

	if (Input::is_action_pressed("move_forward"))
		input_vector.y += 1;
	if (Input::is_action_pressed("move_back"))
		input_vector.y -= 1;
	if (Input::is_action_pressed("move_left"))
		input_vector.x -= 1;
	if (Input::is_action_pressed("move_right"))
		input_vector.x += 1;

	input_vector.normalize();

	_dir += -xform.basis.z.normalized() * input_vector.y;
	_dir += xform.basis.x.normalized() * input_vector.x;

	if (Input::is_action_just_pressed("ui_cancel"))
		Input::set_mouse_mode(Input::get_mouse_mode() == Input::MOUSE_MODE_VISIBLE
			? Input::MOUSE_MODE_CAPTURED
			: Input::MOUSE_MODE_VISIBLE);
}

void Player::process_movement(double delta)
{
	_dir.y = 0;
	_dir.normalize();

	_vel.y += delta * GRAVITY;

	auto hvel = _vel;
	hvel.y = 0;

	auto target = _dir;
	target *= MAX_SPEED;

	real_t accel = 0;
	if (_dir.dot(hvel) > 0)
		accel = ACCEL;
	else
		accel = DEACCEL;

	hvel = hvel.linear_interpolate(target, accel * (real_t) delta);
	_vel.x = hvel.x;
	_vel.z = hvel.z;
	_vel = owner->move_and_slide(_vel, Vector3(0, 1, 0), 0.05, 4, deg2rad(MAX_SLOPE_ANGLE));
}

The same functions in GDScript :

func process_input(delta):

    # ----------------------------------
    # Walking
	dir = Vector3()
	var cam_xform = camera.get_global_transform()

	var input_movement_vector = Vector2()

	if Input.is_action_pressed("move_forward"):
		input_movement_vector.y += 1
	if Input.is_action_pressed("move_back"):
		input_movement_vector.y -= 1
	if Input.is_action_pressed("move_left"):
		input_movement_vector.x -= 1
	if Input.is_action_pressed("move_right"):
		input_movement_vector.x += 1

	input_movement_vector = input_movement_vector.normalized()

	dir += -cam_xform.basis.z.normalized() * input_movement_vector.y
	dir += cam_xform.basis.x.normalized() * input_movement_vector.x
    # ----------------------------------

    # ----------------------------------
    # Capturing/Freeing the cursor
	if Input.is_action_just_pressed("ui_cancel"):
		if Input.get_mouse_mode() == Input.MOUSE_MODE_VISIBLE:
			Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
		else:
			Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
    # ----------------------------------

func process_movement(delta):
	dir.y = 0
	dir = dir.normalized()

	vel.y += delta * GRAVITY

	var hvel = vel
	hvel.y = 0

	var target = dir
	target *= MAX_SPEED

	var accel
	if dir.dot(hvel) > 0:
		accel = ACCEL
	else:
		accel = DEACCEL

	hvel = hvel.linear_interpolate(target, accel*delta)
	vel.x = hvel.x
	vel.z = hvel.z
	vel = move_and_slide(vel, Vector3(0, 1, 0), 0.05, 4, deg2rad(MAX_SLOPE_ANGLE))
:bust_in_silhouette: Reply From: Daniel Grondin

Asked the question on the Discord and found the problem : Basis’ axis are transposed in GDNative, I needed to use basis.get_axis(0) instead of basis.x and the same for the other axis. This isn’t documented anywhere though…

Thanks to the Discord guys for helping!