JRPG Random Encounter Issues

Godot Version

4.7.2

Question

I’m trying to follow the tutorial in this video https://www.youtube.com/watch?v=ekhTIshlInI , and I can’t figure out why my random encounters aren’t triggering. Is there a way to check if any of the code here is actually running, or see where it’s going wrong? I think the problem is with the steps registering, but I don’t really know how to tell what’s wrong, since nothing is happening. It seems like the areas are overlapping when I move the character, and I’m pretty sure everything here is the same as it is in the video. The two area3ds are in the same collision layer, I’ve double-checked that everything is spelled correctly, etc. Any ideas why this might not be working?

This is my full player script, with a comment above the part that’s relevant to the random encounter system.

extends CharacterBody3D


@export var movspd = 5.0

@export var stats: StatsResource

@onready var anim_player = $AnimationPlayer
@onready var step_check_area := $Stepcheckarea

var step_ready := false
var step_timer := 0
var step_interval := 0.2
var is_fully_ready := false



func get_stats():
	return stats

func _ready():
	set_physics_process(false)
	await get_tree().process_frame
	await get_tree().physics_frame
	is_fully_ready = true
	set_physics_process(true)
	
	if Gamestate.return_position != Vector3.ZERO:
		global_transform.origin = Gamestate.return_position
		Gamestate.return_position = Vector3.ZERO

func _physics_process(_delta: float) -> void:
	if not is_fully_ready:
		return
	
	var input_dir := Vector3.ZERO
	
	input_dir.x = Input.get_action_strength("move_left") - Input.get_action_strength("move_right")
	input_dir.z = Input.get_action_strength("move_up") - Input.get_action_strength("move_down")
	
	if input_dir.length() > 0:
		input_dir = input_dir.normalized()
		# roates to face movedir
		look_at(global_transform.origin - input_dir, Vector3.UP)
	#This is the part that should be relevant
	if step_check_area and step_check_area.is_inside_tree():
		for area in step_check_area.get_overlapping_areas():
			if area.has_method("register_step"):
				area.register_step()
	
	velocity.x = input_dir.x * movspd
	velocity.z = input_dir.z * movspd
	
	move_and_slide()

#animation logic
	if input_dir == Vector3.ZERO:
		anim_player.play("Idle")
	elif Input.is_action_pressed("run"):
		anim_player.play("Running_A")
		movspd = 7.50
	else:
		anim_player.play("Walking_A")
		movspd = 5.0

The other relevant file is this

extends Area3D

@export var encounter_rate: float = 0.05
@export var min_steps: int = 10
@export var max_steps: int = 30


var _player_inside := false
var _steps_taken := 0
var _step_threshold := 0
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
	connect("body_entered", Callable(self, "on_body_entered"))
	connect("body_exited", Callable(self, "on_body_exited"))

func _on_body_entered(body):
	if body.name == "player":
		_player_inside = true
		_steps_taken = 0
		_step_threshold = randi_range(min_steps, max_steps)

func _on_body_exited(body):
	if body.name == "player":
		_player_inside = false
		
func register_step():
	if not _player_inside: 
		return
	if Gamestate.in_battle:
		return
	_steps_taken += 1
	
	if _steps_taken >= _step_threshold:
		if randf() <= encounter_rate:
			_steps_taken = 0
			_step_threshold = randi_range(min_steps, max_steps)
			_trigger_battle()

func _trigger_battle():
	Gamestate.save_player_position()
	Gamestate.in_battle = true
	get_tree().change_scene_to_file("res://scenes/world/battlescene.tscn")

You can add print statements to see if register_step is run at all.

Your “Stepcheckarea” seems odd, why would it be a child of the player if it’s checking for the node named “player”. Seems like you can remove this area entirely with an is_on_floor() and velocity check, and/or a timer. Might just be a bad tutorial overly complicating things.

I think the point of the step check area is that the step counter checks if this area3d is overlapping with the random encounters’ area3d? But I’m not completely sure, the guy in the tutorial isn’t spending much time explaining why to do things, only showing how to do them. It’d be nice if there were something as good as the blender donut here, but I’ll take what I can get :sweat_smile:

The thing about print statements helped me narrow down the source of my issue. I had just screwed up the encounter_rate somehow and the value in the scene manager was different from the one in the code. In the future I’ll be sure to use them before I run into bugs like this.