Use this space for questions related to what you're learning. For any other type of support (website, learning platform, payments, etc...) please get in touch using the contact form.
Leg rotation: alternative solutionTJHi! I was trying out if I could come up with an alternative solution for the leg rotation. I came up with the following code below. These lines would need to be executed after updating the `_gobot_skin_3d` global rotation with the mouse look-at functionality. The resulting leg directions look correct, although the compact size of Gobot and the fast running animation makes it less easy for me to be fully confident. What do you think of the code?
```gdscript
if _input_vector.length_squared() > 0.0:
var global_forward: Vector3 = -_gobot_skin_3d.global_basis.z
_gobot_skin_3d.hips_rotation = global_forward.signed_angle_to(direction, Vector3.UP)
```
But I fully agree with the lesson that it's good to dive into the reasoning with the negative angle for the positive x-direction, just to be aware of that mathematics. I also don't know how the performance would compare between the lesson's solution and the above compact code.31Jul. 19, 2024
Is PROJECT_RAY_LENGTH actually necessary?SniffiHey! Really love the module and the lessons so far and learning a lot!
I was just curious if we actually need the variable/constant `PROJECT_RAY_LENGTH` since i tried some stuff out and maybe i don't have the bigger picture for later yet:
I was experimenting with the value of `PROJECT_RAY_LENGTH`, set it to high and low values or just didn't use it. The result of `world_mouse_position` was always the same.
In the docs for the`intersects_ray(from: Vector3, dir: Vector3)` function it says:
> Returns the intersection point of a ray consisting of the position `from` and the **direction normal** `dir` with this plane.
So maybe it is not depending on the length of the vector **dir.**
`from` and `dir` (our `mouse_ray`) basically define a unique line in 3D space where the length of `dir` doesn't matter. The function then calculates the intersection between a line and a plane. ( [https://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection](https://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection) )
I dug deeper in the Godot source code on how they calculated that intersection:
[https://github.com/godotengine/godot/blob/f0d15bbfdfde1c1076903afb7a7db373580d5534/core/math/plane.cpp#L97](https://github.com/godotengine/godot/blob/f0d15bbfdfde1c1076903afb7a7db373580d5534/core/math/plane.cpp#L97)
If you math it out, the length of `dir` (`mouse_ray`) cancels out in the calculation:
[https://imgur.com/a/godot-plane-intersects-ray-qLp09UY](https://imgur.com/a/godot-plane-intersects-ray-qLp09UY)
Based on that it shouldn't make a difference if we use `PROJECT_RAY_LENGTH` or not!
I could be wrong and made some mistakes but this was just something i noticed and wanted to point out. If there´s a reason for later parts in the lessons where we need it and it just doesn't matter for now then i didn't say anything 😊.
Thank you and keep up the great work :) !51Jul. 03, 2024
Movement relative to the playerram876Hello! I wanted to be able to rotate the camera and still have the character's movement relative to the player. I played around with the AI and here's the result. On q and e, I can rotate the camera view and the character moves relative to the player. To do this, we take the camera transformation, x and z directions (judging by the documentation, they are already in Vector3 format), then multiply them by the normalized values from the input. But for some reason, the AI set the forward direction to negative, indicating that z looks in the opposite direction, in my case I removed the minus, since my forward and backward were incorrect in this case. I also thought that in forward and right I would get the values x, y, 1 and 1, y, z. Therefore, I cannot understand what exactly these two variables got. Here is my code:
```gdscript
extends CharacterBody3D
## The maximum speed the player can move at in meters per second.
@export_range(3.0, 12.0, 0.1) var max_speed := 6.0
## Controls how quickly the player accelerates and turns on the ground.
@export_range(1.0, 50.0, 0.1) var steering_factor := 20.0
@onready var _gobot_skin_3d: GobotSkin3D = %GobotSkin3D
@onready var rotation_dir: Node2D = %rotation_dir
var _ground_plane := Plane(Vector3.UP)
@onready var _camera_3d: Camera3D = %Camera3D
var is_rotating := false
var _camera_rotation_speed: float = 0.05
var _camera_speed_acceleration_time: float = 2.0
var _camera_current_timer = 0.0
func _physics_process(delta: float) -> void:
var input_vector := Input.get_vector("move_left", "move_right", "move_up", "move_down")
# correct direction
var camera_transform := _camera_3d.global_transform
var forward = camera_transform.basis.z.normalized()
var right = camera_transform.basis.x.normalized()
var direction := (right * input_vector.x + forward * input_vector.y).normalized()
#
var desired_ground_velocity := direction * max_speed
var steering_vector := desired_ground_velocity - velocity
steering_vector.y = 0.0
var steering_amount: float = min(steering_factor * delta, 1.0)
velocity += steering_vector * steering_amount
const GRAVITY := 40.0 * Vector3.DOWN
velocity += GRAVITY * delta
move_and_slide()
if is_on_floor() and not direction.is_zero_approx():
_gobot_skin_3d.run()
elif is_on_floor():
_gobot_skin_3d.idle()
elif not is_on_floor():
_gobot_skin_3d.fall()
_ground_plane.d = global_position.y
var mouse_position_2d := get_viewport().get_mouse_position()
var mouse_ray := _camera_3d.project_ray_normal(mouse_position_2d)
var world_mouse_position: Variant = _ground_plane.intersects_ray(_camera_3d.global_position, mouse_ray)
if world_mouse_position != null:
_gobot_skin_3d.look_at(world_mouse_position)
if input_vector.length() > 0.0:
var skin_forward_vector := -1 * _gobot_skin_3d.global_basis.z
_gobot_skin_3d.hips_rotation = skin_forward_vector.signed_angle_to(direction, Vector3.UP)
#camera_rotation_code
if Input.is_action_pressed("rotate_cam_left"):
if not is_rotating:
_camera_current_timer = 0.0
is_rotating = true
if _camera_speed_acceleration_time > _camera_current_timer:
_camera_current_timer += delta
$CameraAnchor.rotation.y -= lerpf(0.0, _camera_rotation_speed, _camera_current_timer/_camera_speed_acceleration_time)
elif Input.is_action_pressed("rotate_cam_right"):
if not is_rotating:
_camera_current_timer = 0.0
is_rotating = true
if _camera_speed_acceleration_time > _camera_current_timer:
_camera_current_timer += delta
$CameraAnchor.rotation.y += lerpf(0.0, _camera_rotation_speed, _camera_current_timer/_camera_speed_acceleration_time)
else:
is_rotating = false
_camera_current_timer = 0.0
```10Nov. 17, 2024
Transformsheartfelt-wormLove your work!
Just some feedback, the Godot docs have an article about using Transforms over thinking in angles or setting rotations and the Godot TOS demo project has good examples of that. Like instead of using angle to we could slerp between the current basis and a new basis looking_at. Would it be worth making that a running thing from the get go? Cause it took me a while to wrap my head around it but I find it very useful now.10Nov. 13, 2024
Smoother leg rotationValrogI played with the steering factor a bit and noticed that the leg movement is quite snappy so instead of using direction I used the velocity to calculate the hips_rotation like this :
```gdscript
_gobot_skin_3d.hips_rotation = skin_forward_vector.signed_angle_to(velocity, Vector3.UP)
```
But I wonder if this can cause any bug using directly the velocity ? It works well and the legs now turn smoothly but it feels like it can mess with the velocity and then with the movement.
10Nov. 06, 2024
eyesnot showing correctlyexalted-dragonflyI relblicated the code in the examples but have found a issue with the charactermodel, where it seems to not show the black pupils when running. so far i've only observed it when the game is running not while looking at the character using wigglebone. I'm not sure if it's expecected?10Nov. 04, 2024
why doesnt the skin look down then?high-tarsierwe the cast a ray on a plane that is below the robot , how come the skin of the robot doesnt look down or up? , we get 3d vector .. i assume there is a Y value as well ?30Oct. 01, 2024
I have a problem! white-butterflyThe character starts spinning 360 degrees around its axis with just a small movement of the mouse to the side.40Sep. 15, 2024
My L5.P3 solution after strugglingtedious-crowI struggled to figure out how to change the global position of the box. Mainly because I did not know (or possibly didn't remember) how to turn the preloaded box scene into a node that global_position could be used on instead of staying as a packed scene.
after creating a variable for the scene to be preloaded into at the very top of the script i then took time to figure out how to properly instantiate it and then add it as a child. I first wrote these two lines directly underneath the world_mouse_position line, box.instantiate() first then add_child(box).but that gave me errors so i did some research and saw i had to change it to one line as add_child(box.instantiate()), but even after that typing box.global_position would still give me an error that said box is still recognized as a packed scene.
So after being stumped for a few minuets i decided to open up my workbook for Module 6 in the 2D game dev tutorials because i remembered that the chest added the loot as children so maybe I can see how that worked to get this working.
It was successful and below is the resulting code.
```gdscript
extends Node3D
var mouse_position_2d := Vector2.ZERO
var mouse_ray := Vector3.ZERO
var world_mouse_position: Variant = null
var box := preload("res://practices/L5.P3/box.tscn")
var _world_plane := Plane(Vector3.UP)
@onready var _camera_3d: Camera3D = %Camera3D
func _physics_process(delta: float) -> void:
_world_plane.d = global_position.y
if Input.is_action_just_pressed("left_click"):
# This code is the same as in previous practices. We calculate the projected mouse position.
mouse_position_2d = get_viewport().get_mouse_position()
mouse_ray = _camera_3d.project_ray_normal(mouse_position_2d)
world_mouse_position = _world_plane.intersects_ray(_camera_3d.global_position, mouse_ray)
# Preload the box scene file, instantiate it, add it as a child of this
# node, and set its global position to the projected mouse position.
var box_child: Node3D = box.instantiate()
add_child(box_child)
box_child.global_position = world_mouse_position
```
I don't know if having a second variable that is specified to be a Node3D is the most efficient (especially since i had to look at the box scene to see what the root node was, and other scenes that use this method can easily have different roots) but that is how i managed to solve this challenge. And I wanted to post this so anyone else that was struggling can receive help.
10Sep. 13, 2024
Practices plugin isn't listed in the plugins tabdeserted-walrusThe only plugins I see listed are:
GDQuest 3D Math Visualizer
GDQuest ColorPicker Presets
WiggleBone
I do see a folder called "gdpractice" in the addons folder for the project though (along with 2 others, gdquest_sparkly_bag and gdquest_theme_utils)30Sep. 06, 2024
L5.P3 Practice issue - need add "left_click" action (solved)MelabelaWas quite sure I coded the practice correctly, but could not get it to pass.
Then I checked Debugger -> Errors tab, and saw many lines of
`E 0:00:00:0490 instantiate_on_click.gd:16 @ _physics_process(): The InputMap action "left_click" doesn't exist. Did you mean "ui_text_caret_left"?`
---
**Solution:** It took a while for me to realize, that need to add "left_click" action, under Project Settings -> Input Map.
- *Perhaps this should be mentioned as a practice hint and/or practice code comment?*
Note - was a bit surprised by this, since we had previously assigned <left_click> input to "shoot" action, in previous page (M3.)L4 - section "Adding input actions"
> Finally for "shoot", I mapped the Ctrl, **the left mouse button**, and the joypad axis 5 (→Trigger button on the XBox controller).80Aug. 19, 2024
Problem with look_at() function (Solved)PurpleHuesSo, I'm actually redoing this part fresh for practice and I ran into a problem where when I put in the code for look_at() and run scene the player is angled in an odd way. It's face runs into the ground.
I've tried finding mistakes and rereading the code several times. I even copy pasted your code to see if I'd get a different result, but it's the same. so, I'm stumped. I'm not sure if it's due to the lesson's 2.1 update or, if I'm missing something.20Aug. 08, 2024
Leg rotation: code indentationTJHi! I have a question/suggestion about the code indentation for the legs rotation. In my browser (Chrome) currently the code listing in the lesson is displayed as if the last line is indented under the if-test on the direction vector:
```gdscript
if direction.x != 0.0:
target_angle *= -sign(direction.x)
_gobot_skin_3d.hips_rotation = target_angle - _gobot_skin_3d.rotation.y
```
However, when I copy the code then I see that the line should not be indented under the if-test. So is there perhaps a formatting issue because of the plus-sign at the beginning of that last line? I was quite confused why the last line should be indented, and it indeed turns out that it should not be indented!10Jul. 19, 2024
Small Diagram Feedbackwell-to-do-owlMight be just me, but I feel the vector diagrams would help if there was a little legend or labelled arrows. For me, it was a bit cumbersome having to look at the diagram and then search again the text above to see what each coloured arrow represents, I feel they should make sense on their own! Small nit-pick, great lesson overall thank you!!30Jul. 10, 2024
I attempted to Implement turning around using the right joystickKenseiKCHere is the Code I used, the skin does react to the inputs but doesn't turn toward the right?
```gdscript
var looking_vector := Input.get_vector("look_left","look_right","look_up","look_down")
var looking_direction := Vector3(looking_vector.x,0.0, looking_vector.y)
var looking_angle := Vector3.FORWARD.angle_to(looking_direction)
if looking_vector.length() > 0.0:
_gobot_skin_3d.rotation.y = looking_angle
```90Jul. 10, 2024
L5.P2 Practice... issueminiature-rhinocerosThe test fails the condition for updating the boxes position on left click 😭
This is my bad for reading the gist of the practice and not the whole thing, but the behaviour is slightly different, yes?
Input.is_mouse_button_pressed seems to always pass the condition, so the box is essentially following my cursor, and it sounds like the intended effect was using input.is_action_just_pressed("left_click") which would only teleport the block on the frame where a left click happens.
> I understand this course is still under construction, so just checking that following the mouse was intentional20Jul. 04, 2024
Visualising the Planeunhealthy-frogI believe I understand the general idea behind the plane we are creating in order to capture our ray intersects, but I am having trouble visualising it and what it actually looks like in the scene, and the distance property confuses me.
Is there a way to visualise what the created plane looks like in 3D space?30Jul. 04, 2024
Lesson Q&A
Use this space for questions related to what you're learning. For any other type of support (website, learning platform, payments, etc...) please get in touch using the contact form.