Game crashes when trying to get mouse position

Godot Version

v4.6.stable.official

Question

Git repo: GitHub - DaMushKen/PROJECT-WOUND · GitHub
In my WeaponsManager (res://scripts/weapons/WeaponsManager.gd) whenever I try to shoot I get an error saying: Trying to assign a value of type ‘Nil’ to a variable of type ‘Vector3’ (func shoot(), line 138).
Please help me I have been trying to fix this for so long. If there isn’t a fix to the way I am currently doing it please atleast tell me another way to do it. Thanks

I’d really rather not parse your entire repo for a problem in one script, you should put the script (or where you think the problem is in the script) in your post instead of just a repo link.

1 Like

Here is the script. The function I am talking about are shoot() and _get_3d_mouse_position()

class_name WeaponManager
extends Node3D



signal WeaponChanged
signal UpdateAmmo
signal UpdateWeaponStack



var current_weapon_debug : String
var current_weapon_stack_debug : String
var current_weapon_ammo_debug : String



@export var ANIM_PLAYER : AnimationPlayer
@onready var BULLET_POINT : Marker3D = get_node("WeaponRigs/BulletPoint")
const BULLET : PackedScene = preload("res://scenes/bullet/bullet.tscn")



var CURRENT_WEAPON
var WEAPON_STACK = [] # An array of weapons currently held by the player
var WEAPON_INDICATOR = 0
var NEXT_WEAPON : String
var WEAPON_LIST = {}

@export var WEAPON_RESOURCES: Array[WeaponResource]
@export var START_WEAPONS: Array[String]





func _ready() -> void:
	Global.weapon_manager = self
	Initialize(START_WEAPONS) # Enter the state machine





func _physics_process(delta: float) -> void:
	Global.debug.add_property("Current Weapon", current_weapon_debug, 6)
	Global.debug.add_property("Ammo", current_weapon_ammo_debug, 7)
	Global.debug.add_property("Weapon Stack", current_weapon_stack_debug, 8)







func _input(event: InputEvent) -> void:
	if event.is_action_released("SCROLL_UP"):
		WEAPON_INDICATOR = min(WEAPON_INDICATOR +1, WEAPON_STACK.size() -1)
		exit(WEAPON_STACK[WEAPON_INDICATOR])
	
	if event.is_action_released("SCROLL_DOWN"):
		WEAPON_INDICATOR = max(WEAPON_INDICATOR -1, 0)
		exit(WEAPON_STACK[WEAPON_INDICATOR])
	
	if event.is_action_pressed("SHOOT"):
		shoot()
	if event.is_action_pressed("RELOAD"):
		reload()





func Initialize(start_weapons: Array):
	
	# Create a dictionary
	for weapon in WEAPON_RESOURCES:
		WEAPON_LIST[weapon.WEAPON_NAME] = weapon
	
	for i in start_weapons:
		WEAPON_STACK.push_back(i) #Add start weapons
	
	CURRENT_WEAPON = WEAPON_LIST[WEAPON_STACK[0]]
	emit_signal("UpdateWeaponStack", WEAPON_STACK)
	enter()





func enter():
	ANIM_PLAYER.queue(CURRENT_WEAPON.ACTIVATE_ANIM)
	emit_signal("WeaponChanged", CURRENT_WEAPON.WEAPON_NAME)
	emit_signal("UpdateAmmo", [CURRENT_WEAPON.CURRENT_AMMO, CURRENT_WEAPON.RELOAD_AMMO])





func exit(next_weapon : String):
	if next_weapon != CURRENT_WEAPON.WEAPON_NAME:
		if ANIM_PLAYER.get_current_animation() != CURRENT_WEAPON.DEACTIVATE_ANIM:
			ANIM_PLAYER.play(CURRENT_WEAPON.DEACTIVATE_ANIM)
			NEXT_WEAPON = next_weapon





func Change_Weapon(weapon_name : String):
	CURRENT_WEAPON = WEAPON_LIST[weapon_name]
	NEXT_WEAPON = ""
	enter()





func _on_weapon_anims_animation_finished(anim_name: StringName) -> void:
	if anim_name == CURRENT_WEAPON.DEACTIVATE_ANIM:
		Change_Weapon(NEXT_WEAPON)
	
	if anim_name == CURRENT_WEAPON.SHOOT_ANIM and CURRENT_WEAPON.isAutoFire == true:
		if Input.is_action_pressed("SHOOT"):
			shoot()





func shoot():
	if CURRENT_WEAPON.CURRENT_AMMO != 0 and !ANIM_PLAYER.is_playing():
		ANIM_PLAYER.play(CURRENT_WEAPON.SHOOT_ANIM)
		CURRENT_WEAPON.CURRENT_AMMO -= 1
		emit_signal("UpdateAmmo", [CURRENT_WEAPON.CURRENT_AMMO, CURRENT_WEAPON.RELOAD_AMMO])
		
		var bulletNode : Node = BULLET.instantiate()
		var mouse3D : Vector3 = _get_3d_mouse_position()
	
		if not mouse3D: return
		#bulletNode.direction = -get_viewport().get_camera_3d().global_transform.basis.z.normalized()
		bulletNode.direction = global_position.direction_to(mouse3D)

		get_tree().root.add_child(bulletNode)
		bulletNode.global_position = BULLET_POINT.global_position
	else:
		reload()





func _get_3d_mouse_position():
	var mouse2DPosition : Vector2 = get_viewport().get_mouse_position()
	var currentCamera : Camera3D = get_viewport().get_camera_3d()
	var params : PhysicsRayQueryParameters3D = PhysicsRayQueryParameters3D.new()
	
	params.from = currentCamera.project_ray_origin(mouse2DPosition)
	params.to = currentCamera.project_position(mouse2DPosition, 100)
	
	var worldspace : PhysicsDirectSpaceState3D = get_world_3d().direct_space_state
	var intersect : Dictionary = worldspace.intersect_ray(params)
	
	if not intersect: return
	var intersectPosition = intersect.position
	intersectPosition.y = global_position.y
	return intersectPosition





func reload():
	if CURRENT_WEAPON.CURRENT_AMMO == CURRENT_WEAPON.MAGAZINE:
		return
	elif !ANIM_PLAYER.is_playing() and CURRENT_WEAPON.RELOAD_AMMO != 0:
		ANIM_PLAYER.play(CURRENT_WEAPON.RELOAD_ANIM)
		var RELOAD_AMOUNT = min(CURRENT_WEAPON.MAGAZINE - CURRENT_WEAPON.CURRENT_AMMO, CURRENT_WEAPON.MAGAZINE, CURRENT_WEAPON.RELOAD_AMMO)
		
		CURRENT_WEAPON.CURRENT_AMMO += RELOAD_AMOUNT
		CURRENT_WEAPON.RELOAD_AMMO -= RELOAD_AMOUNT
		
		emit_signal("UpdateAmmo", [CURRENT_WEAPON.CURRENT_AMMO, CURRENT_WEAPON.RELOAD_AMMO])





func _on_update_ammo(ammo) -> void:
	current_weapon_ammo_debug = str(ammo[0], " / ", str(ammo[1]))





func _on_update_weapon_stack(weapon_stack) -> void:
	current_weapon_stack_debug = ""
	for i in weapon_stack:
		current_weapon_stack_debug += "\n" + i





func _on_weapon_changed(weapon_name) -> void:
	current_weapon_debug = weapon_name

I see this line potentially causing an error. Your shoot function expects the function to return a Vector3, but you are returning nil. You should make your _get_3d_mouse_position() return a Vector3 by type, which will help you find the issue.
(This looks like func _get_3d_mouse_position() -> Vector3:)

When I make the function return Vector3 the line you said gives an error so it’s probably that one. I dont know how to do that line tho. If I remove it my game crashes

Just make it return Vector3.ZERO then check in the shoot() function if the Vector3 is blank, then handle that case

1 Like