[4.2.1] Why does .looking_at() not like the Target being Vector3(0,0,0)?

Hello there! I’m not quite sure if I should put this here, or make an Issue about it- I’m curious about why this is the case:

So, .looking_at() is supposed to output a Basis consisting of an angle from one point to another, right?

Then why does it complain when the Target is at Vector3(0,0,0) , even if the point it’s coming from isn’t?

It makes sense that it would complain if the Target and the Basis’ origin were at the same point, but not when just the Target is.

Like, you aren’t allowed to use it at all if you have something that happens to be at 0,0,0? Why limit the user in such a way?

1 Like

Because the look_at function will perform rotations based on differences from looking node position to its target position.

If the looking node position is vector(0,0,0) and target position is vector(0,0,0), meaning they have the same position, there is no definable math to produce a rotation, it becomes undefined.

you can look at the source code to see the math.

2 Likes

Aye, that’s what I was meaning in the 4th paragraph- I’m talking about scenarios where the looking node position isn’t 0,0,0, but the target position is 0,0,0- In cases like that, from what I’ve seen, it will complain until the target position is moved away from 0,0,0

1 Like

Which seems like exactly what I just mentioned. All spacial nodes have a global position and a local position. Most local positions are zeros if the node sits at the origin of their parent.

The positions don’t have to be zero, they just cannot be the same otherwise their difference will be zeros.

I suspect you are probably crossing local and global positions with your function calls.

1 Like

The issue stopped throwing errors when I switched from

@onready var parentBody = get_parent()
@export var targetAngle : Quaternion
@export var targetPosition : Vector3

func _ready():
   targetPosition = EntityManager.playerPositionSource

func _process(delta):
   targetAngle = parentBody.basis.looking_at(targetPosition).get_rotation_quaternion()

To

@onready var parentBody = get_parent()
@export var targetAngle : Transform3D
@export var targetPosition : Vector3

func _ready():
   targetPosition = EntityManager.playerPositionSource

func _process(delta):
   targetAngle = parentBody.global_transform.looking_at(targetPosition)

So does that mean that calling an object’s .basis will always return 0,0,0?

If so, that means that the error message is misleading, in which case I’ll create an Issue about changing it

1 Like

The first command you are using the local basis. This will reference the local position to the parent object. By default a new child is placed at the origin (0,0,0) of a parent.

The second command you are accessing the global_basis through the global_transform.

I’m not sure what playerPostionSource is but it should be equivalent to the entity’s global_position.

2 Likes

What may be a little confusing is how Godot allows access to a nodes position and rotation and how it has two variations, local and global.

It gets a little more confusing when we want to use position and rotation, because these values are actually interfacing with the spatial nodes transform.

There is a local and global transform. And a transform is compromised of an origin vector (position) and a basis matrix of vectors (rotation and scale).

Local space is relative to the parent. Where the parents movement also move the children to the same degree. It’s helpful to move a child without caring where the parent is placed and move a parent with all the children with it.

Global space comes from the viewport node. This has an arbitrary origin. And all children and children of children’s global position comes from their location relative to the viewport 3d world space origin. (Or canvas 2d world space origin) this is also why global positions can’t be set or accessed until the node is added to the scene tree.

Btw there many looking_at functions, of you use basis alone it assumes it position is zero, but if you use transform looking at it will use the origin position.

2 Likes

I’m not sure what playerPostionSource is but it should be equivalent to the entity’s global_position.

Ah damn, I missed a few bits of the code with regards to the playerPositionSource- it grabs the Node3D itself, then gets targetPosition from that Node3D’s .position

The first command you are using the local basis. This will reference the local position to the parent object

So .basis gets the Node’s position relative to its parent Node? In this case, the Node in question-- the one accessed with parentBody– is a child of the Scene Root, and I’d moved it to a random point on the screen: 8,0,-6

The .basis shouldn’t be 0,0,0 in that case, right?

1 Like

Btw there many looking_at functions, of you use basis alone it assumes it position is zero, but if you use transform looking at it will use the origin position

Ah, that answers that question, I think

That seems to indicate that the error message is misleading

2 Likes

Sorry i didn’t see that earlier. I could have saved some breath. :sweat_smile:

2 Likes

It was a constructive conversation either way!

1 Like

Fixed for getting_started/first_3d_game - The error appeared after I used rounding of movements through LERP:

	# direcion lerp
	direction_to = direction_to.normalized()
	direction = lerp(direction, direction_to, delta*4)

And when idle, the vector approached 0,y,0 - this caused the error “_physics_process(): The target vector can’t be zero looking_at()”
FIXED

	# direcion lerp
	direction_to = direction_to.normalized()
	var direction_ = lerp(direction, direction_to, delta*4)
	# @FIXED The target vector can't be zero.
	if direction_.length() > 0.001:
		direction = direction_
	# Setting the basis property will affect the rotation of the node.
	$Pivot.basis = Basis.looking_at(direction)
1 Like