Can't get dictionary value if key is a Vector3?

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

So for my project, I want to use A* for pathfinding, so I made a code to make a dictionary of points with their corresponding ids (position is the key rather than the value for ease of use) and add them to the AStar, they get added successfully and the dictionary works, but I can’t retrieve any of the id’s from the dictionary: tempLocalMap is a list of all points, position, as a Vector3 is the key and id, as an int is the value, but whenever I try tempLocalMap[Vector3(0,0,0)], it returns an error, I have tried printing the entire dict, and (0,0,0) is the first key with a value of 1, could somebody help?
I realize this is very basic and I bet I’m doing something mega-dumb rn.

Which error is it giving you exactly?
Can you show your code?

Zylann | 2019-07-27 15:10

I’m not getting an error, it’s just saying it can’t get index of tempLocalMap[whateverVector3] and anyway I found a fix, I went internet surfing, and found the answer in an AStar tutorial, https://youtu.be/A1xjUuRZmWQ?t=294, apparently Vector3’s can’t be used directly as keys in a dictionary, you have to convert them to strings, or something like that first, so I just converted it to strings using the same method as the video.

I doubt it matters much now, but here’s the fixed code

func _ready():
	bakeAstarMap()
	
	print(get_point_ID(Vector3(6,0,5)))
	print(tempLocalMap.get(Vector3(0,0,0)))
	pass


func v3_to_index(v3):
    return str(int(round(v3.x))) + "," + str(int(round(v3.y))) + "," + str(int(round(v3.z)))


func bakeAstarMap():
	
	var currentPoint = Vector3(0,0,0)
	var i = 0
	for y in dimensions.y:
		currentPoint.z = y
		
		for x in dimensions.x:
			currentPoint.x = x
			var hit = raycast(currentPoint)
			if hit:
				i += 1
				As.add_point(i,hit["position"], 1)
				tempLocalMap[v3_to_index(hit["position"])] = i



func get_point_ID(position: Vector3):
	return tempLocalMap[v3_to_index(position)]


func raycast(currentPoint):
	var space_state = get_world().direct_space_state
	return space_state.intersect_ray(Vector3(currentPoint.x,maxHeight,currentPoint.z), Vector3(currentPoint.x,minHeight,currentPoint.z))

Agentfox | 2019-07-27 17:56

apparently Vector3’s can’t be used directly as keys in a dictionary

This is false, you definitely can. The only thing to be aware of, is that Vector3 are float, and as such they are subject to precision error if you do computations with them. So if you use integer positions, make sure to floor() them first (or round).

Also, I see inconsistency in your code:

print(tempLocalMap.get(Vector3(0,0,0)))

You are getting with a vector key here, but later you do this:

return tempLocalMap[v3_to_index(position)]

Which is getting with a string key.

Zylann | 2019-07-27 17:59

Ah, thanks, that was leftover from debugging, so basically, I need to round the individual points in a Vector3 for it to be used in a dictionary? (for future reference)

Agentfox | 2019-07-27 18:51

You don’t need to, but it’s recommended because sometimes after some calculations (such as addition, multiplication, divisions of vectors), the result might not exactly be rounded (like (42.000, -19.0001, 27.99999)).

Zylann | 2019-07-27 18:54