My character "breaks" his neck

Godot Version

4.3

Question

There is a problem. When I rotate the mouse very much, my character starts walking strangely. Pressing one of the WASD buttons, for some reason, he walks diagonally.

NORMAL WALK

PROBLEM

Player.gd

extends Unit

@onready var head = $Head

@export var VelocityComponent : _VelocityComponent
@export var ControllerComponent : _ControllerComponent

var bullet = preload("res://scenes/Player/Weapons/bullet.tscn")

const MAX_WALL_SLIDING = 3

enum {
	NOT_TOUCH = 0,
	TOUCH = 1
}

var wall_touch := 0 : 
	set(value):
		wall_touch = value
		print(wall_touch)

func _ready() -> void:
	ControllerComponent.Camera = $Head/Camera3D
	ControllerComponent.Head = head
	VelocityComponent.ControllerComponent = ControllerComponent

func _physics_process(delta: float) -> void:
	VelocityComponent.Move(self)
	
	if is_on_floor():
		wall_touch = NOT_TOUCH

func _on_wall_sliding_wall_touch() -> void:
	wall_touch += TOUCH

func _on_controller_component_shooting() -> void:
	var instance = bullet.instantiate()
	instance.position = $Head/Camera3D/Revolver/RayCast3D.global_position
	instance.transform.basis = $Head/Camera3D/Revolver/RayCast3D.global_transform.basis
	get_parent().add_child(instance)

VelocityComponent.gd

extends Node
class_name _VelocityComponent

@onready var TimerStamina := $RecoverStamina
var ControllerComponent : _ControllerComponent

var Velocity : Vector3
var TransformBasis : Basis
var SPEED : int
var Player : Unit
var direction := Vector3.ZERO

const WALL_FRICTION = 0.5
const FLY_MOVE_MULTIPLIER = 10.0 ### Чем больше, тем больше управление в воздухе. Влияет на рывок в воздухе
@export var DASH_MULTIPLIER := 10

@export var jump_height : float
@export var jump_time_to_peak : float
@export var jump_time_to_descent : float

@onready var jump_velocity : float = (2.0 * jump_height) / jump_time_to_peak
@onready var jump_gravity : float = (-2.0 * jump_height) / (jump_time_to_peak * jump_time_to_peak)
@onready var fall_gravity : float = (-2.0 * jump_height) / (jump_time_to_descent * jump_time_to_descent)

func _physics_process(delta: float) -> void:
	var input_dir := ControllerComponent.input_dir
	direction = (TransformBasis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
	if Player.is_on_floor():
		if direction:
			Velocity.x = direction.x * SPEED
			Velocity.z = direction.z * SPEED
		else:
			Velocity.x = move_toward(Velocity.x, 0, SPEED)
			Velocity.z = move_toward(Velocity.z, 0, SPEED)
	else:
		## Плавное замеддение в воздухе
		Velocity.x = lerp(Velocity.x, direction.x*SPEED,delta * FLY_MOVE_MULTIPLIER) 
		Velocity.z = lerp(Velocity.z, direction.z*SPEED,delta * FLY_MOVE_MULTIPLIER)

	if !Player.is_on_floor():
		Velocity.y += Gravity() * delta
	else:
		### Если не обнулять, накопиться большое значение и падение будет слишком резким
		Velocity.y = 0

	Friction()

func RecoverStamina():
	if Player.stamina < Player.MAX_STAMINA:
		Player.stamina += Player.COUNT_RECOVER_STAMINA
		TimerStamina.start()

func WasteStamina(num : int):
	if Player.stamina > Player.MIN_STAMINA:
		Player.stamina -= num
		TimerStamina.start()

func Jump():
	if Player.stamina > Player.MIN_STAMINA:
		if Player.is_on_floor():
			Velocity.y = jump_velocity

		if !Player.is_on_floor() and Player.is_on_wall():
			Velocity = Player.get_wall_normal() * jump_velocity
			Velocity.y = jump_velocity

func Dash():
	### Рывок с места
	if Player.stamina > Player.MIN_STAMINA and !direction:
		Velocity.x = -TransformBasis.z.x * SPEED * DASH_MULTIPLIER
		Velocity.z = -TransformBasis.z.z * SPEED * DASH_MULTIPLIER
	### Рывок в движении
	elif Player.stamina > Player.MIN_STAMINA and direction:
		Velocity.x = direction.x * SPEED * DASH_MULTIPLIER
		Velocity.z = direction.z * SPEED * DASH_MULTIPLIER

func Gravity() -> float:
	return jump_gravity if Velocity.y > 0.0 else fall_gravity

func Friction():
	if Player.is_on_wall() and !Player.is_on_floor():
		if Player.wall_touch <= Player.MAX_WALL_SLIDING:
			Velocity.y *= WALL_FRICTION

func Move(player : Unit):
	Player = player
	player.velocity = Velocity
	TransformBasis = player.head.transform.basis
	SPEED = player.speed
	player.move_and_slide()

ControllerComponent.gd

extends Node
class_name _ControllerComponent

signal waste_stamina
signal dash
signal jump
signal sliding
signal shooting

@export var SENS := 0.02

var input_dir : Vector2
var Head 
var Camera : Camera3D

enum Actions {
	DASH = 1,
	JUMP = 1,
	SLIDING = 1
}

func _physics_process(delta: float) -> void:
	input_dir = Input.get_vector("Left", "Right", "Forward", "Back")
	Camera.rotation.z = -input_dir.x * deg_to_rad(2)

func _input(event: InputEvent) -> void:
	if event is InputEventMouse:
		if event is InputEventMouseMotion:
			Head.rotate_y(-event.relative.x * SENS)
			Camera.rotate_x(-event.relative.y * SENS)
			Camera.rotation.x = clamp(Camera.rotation.x, deg_to_rad(-40),deg_to_rad(50))
		if event is InputEventMouseButton:
			if event.is_action_pressed("Shoot"):
				shooting.emit()

	if event is InputEventKey:
		### Сначала сигнал действия, потом трата выносливости !!!
		if event.is_action_pressed("Dash"):
			dash.emit()
			waste_stamina.emit(Actions.DASH)
		if event.is_action_pressed("Jump"):
			jump.emit()
			waste_stamina.emit(Actions.JUMP)
		if event.is_action_pressed("Sliding"):
			sliding.emit()
			waste_stamina.emit(Actions.SLIDING)
1 Like

Its a combination of your view bob

And how you rotate your x axis

You can try changing the axis order of godot

To ZXY but you will probably need to refactor your rotation code.

1 Like

I’m sorry, I didn’t understand your comment fully. With this piece of code, I was trying to tilt my character’s head while moving left or right (as in the game ULTRAKILL).
Camera.rotate_x(-event.relative.y * SENS)
After testing, I realized that there was a problem with this specific part of the code.

I think I’ve managed to solve the problem. Instead of turning the camera, I simply turn my head.
image
For the test, I tried turning the camera like I did last time. So far, it seems to be working. :slight_smile:

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.