Hello im trying to make a custom cursor for my game how should i aproach this

Godot Version

4.4

Question

im making a 3d game and wanted to make a cursor that changes depending on what im “looking” at for example if the cursor is at an enemy make it look like a fist and when its at an object make it look like an open hand or a pointing hand.

extends Area2D

@onready var MouseSprited: Sprite2D = $".."


func _on_Area2D_mouse_enter():
    Input.set_mouse_mode(Input.MOUSE_MODE_HIDDEN)
    get_node("MouseSprite").show()

func _on_Area2D_mouse_exit():
    Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
    get_node("MouseSprite").hide()

#  Move the custom cursor in the same function where the mouse is moved (example)
func _process(delta):
    if !get_node("MouseSprite").is_visible():
        return
    get_node("MouseSprite").position = Input.get_mouse_position()

Have you had a read of this: https://docs.godotengine.org/en/stable/tutorials/inputs/custom_mouse_cursor.html?

You can change the image with Input.set_custom_mouse_cursor

1 Like

You can change the curser from the project setting as well.

yeah but how do i make it change depending on where the cursor is?

i saw but i want to do it with the code since i want it to change depending on stuff

  1. Get the node the player is looking at with a raycast. (you can theoretically also use RayCast3D but that gets annoying because you would have to rotate it every frame and it would be another node that you would have to reference)
  2. Put all objects into groups describing what cursor they should be looked at with and retreive the group that the node is in
  3. Change the cursor to a texture corresponding to the group name
3 Likes

This could be helpful

1 Like

can i use the 2d area if the game is 3d with this method?

will check it up

is okey but i need the cursor to change depending on what im pointing at

No, because the physics systems for 2D and 3D work independently. You would have to use something inheriting CollisionObject3D (for example Area3D)

1 Like

do they need an area 3d even if they are in a global group?

Raycasts only detect physics objects so yes, the objects they hit would have to be.

I suppose you could code your own raycast that works with any object but that gets complicated quickly and it would probably be slower than the built-in methods

1 Like

i did that for something earlier.
rn im fighting with the code on this maybe if i do the code change the texure of the cursor by loading it directly i can do it. still havent figured it out

yeah i have no idea what im doing

extends Area2D

@onready var normal: Sprite2D = $"../normal/Normal"
@onready var combat: Sprite2D = $Combat


func _on_mouse_entered():
	if CollisionShape3D().is_in_group("Enemy"):
		display_server.get_mouse_cursor() = "combat"

func _on_mouse_exited():

To set the mouse cursor, you would have to use Input.set_custom_mouse_cursor. Functions starting with “get_” usually just return a copy of the object you want to have so setting it wouldn’t work (and the function “get_mouse_cursor” doesn’t seem to exist?)

About the raycasts: Have you read the documentation on ray-casting?

It’s a somewhat big topic to get into and I can’t explain everything in one post (the docs do a really good job, in my opinion), but it isn’t terribly difficult once you’ve read the basics.

Just to clarify, these raycasts are shot from a 3D point to another 3D point and return the first CollisionObject3D that is in the way. (To get an “infinite” distance, you can just do something like 1000, they’re not to slow performance-wise) To cast a ray, you will need the origin and direction which you can get from the camera (project_ray_origin and project_ray_normal)

This video seems useful to get a hang of raycasts

1 Like

i have that i need to make the cursor change.
rn im trying to make the cursor change depending on what im standing over with it like in an point and click game if you know them

Doesn’t this work for you?

1 Like

i did all of that but i dont know how to do the last one

extends Area2D

@onready var normal = preload("res://Ui/interface/cursor_mano2.png")
@onready var combat = preload("res://Ui/interface/cursor_combate2.png")
@onready var interact = preload("res://Ui/interface/cursor_interactuar2.png")

var all_groups = get_tree().get_groups()

func _ready():
	Input.set_mouse_mode(Input.MOUSE_MODE_HIDDEN)

func _process(_delta):
	self.position = self.get_global_mouse_position()

func _on_mouse_entered():
	if CollisionShape3D().is_in_group("Enemy"):
		display_server.get_mouse_cursor() = combat