0 votes

I have been following along the 3D game tutorial pretty closely, but during the section where we implement killing the player, the game suddenly crashes every time I try to run it. I have narrowed it down to the die() function, specifically queuefree() being called to delete the player. After putting in some breakpoints and stepping through, what appears to be happening is that somehow, I think the very first mob spawns right on top of the player, killing the player right away. The next iteration of _onMobTimer_timeout() then gets a Node not found error, due to trying to spawn another mob based off a player reference that no longer exists(I haven't implemented the stopping of the timer yet).

I'll put my code below, but I think I need to somehow prevent the mob from touching my player node right as the game is starting. Any help with this would be appreciated, especially if there is another issue altogether that I am missing. Thank you! PS, sorry for the bad code formatting, it seems that large blocks cause issues for some reason.

Main.gd:

`extends Node

no different than exporting a normal variable, but in this case, it allows up to assign a scene

export (PackedScene) var mob_scene

func _ready():
randomize()

func onMobTimertimeout():
# Create a new instance of the Mob scene.
var mob = mob
scene.instance()

# Choose a random location on the SpawnPath.
# We store the reference to the SpawnLocation node.
var mob_spawn_location = get_node("SpawnPath/SpawnLocation")
# And give it a random offset.
mob_spawn_location.unit_offset = randf()

#finds the center of the Player node's coordinates
var player_position = $Player.transform.origin
mob.initialize(mob_spawn_location.translation, player_position)

add_child(mob)

`

======================================================================

Mob.gd:

extends KinematicBody

signal squashed

Minimum speed of the mob in meters per second.

export var min_speed = 10

Maximum speed of the mob in meters per second.

export var max_speed = 18

var velocity = Vector3.ZERO

func physicsprocess(delta):
move
and_slide(velocity)

We will call this function from the Main scene.

func initialize(startposition, playerposition):
# We position the mob and turn it so that it looks at the player.
lookatfromposition(startposition, playerposition, Vector3.UP)
# And rotate it randomly so it doesn't move exactly toward the player.
rotate
y(rand_range(-PI / 4, PI / 4))

# We calculate a random speed.
var random_speed = rand_range(min_speed, max_speed)
# We calculate a forward velocity that represents the speed.
velocity = Vector3.FORWARD * random_speed
# We then rotate the vector based on the mob's Y rotation to move in the direction it's looking.
velocity = velocity.rotated(Vector3.UP, rotation.y)

func onVisibilityNotifierscreenexited():
queue_free()

func squash():
emitsignal("squashed")
queue
free()

=======================================================================

Player.gd:

extends KinematicBody

signal hit

How fast the player moves in meters per second.

export var speed = 14

The downward acceleration when in the air, in meters per second squared.

export var fall_acceleration = 75

Vertical impulse applied to the character upon jumping in meters per second.

export var jump_impulse = 20

Vertical impulse applied to the character upon bouncing over a mob in meters per second.

export var bounce_impulse = 16

var velocity = Vector3.ZERO

similar to _process(delta), but runs at a fixed rate(60FPS by default), as opposed to as fast as the computer can do

as the name implies, this is best for anything involving physics, like moving bodies and collision

func physicsprocess(delta):
# input direction.
var direction = Vector3.ZERO

#update direction based off input
if Input.is_action_pressed("move_right"):
    direction.x += 1
if Input.is_action_pressed("move_left"):
    direction.x -= 1
if Input.is_action_pressed("move_back"):
    # Notice how we are working with the vector's x and z axes.
    # In 3D, the XZ plane is the ground plane.
    direction.z += 1
if Input.is_action_pressed("move_forward"):
    direction.z -= 1

#the look_at() function points the body in the specified direction, needing a reference to "up"
#translation, is the local location of the body relative to its parent's coordinates, rather than the global coordinates
if direction != Vector3.ZERO:
    direction = direction.normalized()
    $Pivot.look_at(translation + direction, Vector3.UP)

# Ground velocity
velocity.x = direction.x * speed
velocity.z = direction.z * speed

# Jumping.
if is_on_floor() and Input.is_action_just_pressed("jump"):
    velocity.y = jump_impulse

# Vertical velocity
velocity.y -= fall_acceleration * delta

# Moving the character
# this function makes for smoother movement if there were to be a collision.
# it takes a velocity and the up direction, and returns the leftover velocity after accounting for collisions
# in this case, it prevents the body from gaining enough momentum to clip through collisions
velocity = move_and_slide(velocity, Vector3.UP)

for index in range(get_slide_count()):
    # We check every collision that occurred this frame.
    var collision = get_slide_collision(index)
    # If we collide with a monster...
    if collision.collider.is_in_group("mob"):
        var mob = collision.collider
        # ...we check that we are hitting it from above.
        if Vector3.UP.dot(collision.normal) > 0.1:
            # If so, we squash it and bounce.
            mob.squash()
            velocity.y = bounce_impulse

func die():
#pass
emitsignal("hit")
queue
free()

func onMobDetectorbodyentered(body):
die()

Godot version v3.5.1.stable.mono.official
in Engine by (30 points)

UPDATE: After some toying around, I believe the issue is the two different collision areas on the player scene. Initially, they overlapped with one another, causing the onMobDetectorbodyentered() function to be called right away. I separated them, and the game no longer crashes, but now the player doesn't die when colliding with a mob.

1 Answer

0 votes
Best answer

GOT IT! It's always something simple. It would seem that I forgot to properly mask the MobDetector node, so it wasn't detecting the mob layer, and only looking at the player layer instead.

by (30 points)
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to [email protected] with your username.