diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp
index 01c2b9bffe1..e56a9e71ef6 100644
--- a/scene/gui/spin_box.cpp
+++ b/scene/gui/spin_box.cpp
@@ -41,7 +41,11 @@ Size2 SpinBox::get_minimum_size() const {
 }
 
 void SpinBox::_update_text(bool p_keep_line_edit) {
-	String value = String::num(get_value(), Math::range_step_decimals(get_step()));
+	double step = get_step();
+	if (use_custom_arrow_step && custom_arrow_step != 0.0) {
+		step = custom_arrow_step;
+	}
+	String value = String::num(get_value(), Math::range_step_decimals(step));
 	if (is_localizing_numeral_system()) {
 		value = TS->format_number(value);
 	}
@@ -75,6 +79,9 @@ void SpinBox::_text_submitted(const String &p_string) {
 	text = text.trim_prefix(prefix + " ").trim_suffix(" " + suffix);
 
 	Error err = expr->parse(text);
+
+	use_custom_arrow_step = false;
+
 	if (err != OK) {
 		// If the expression failed try without converting commas to dots - they might have been for parameter separation.
 		text = p_string;
@@ -114,8 +121,13 @@ void SpinBox::_line_edit_input(const Ref<InputEvent> &p_event) {
 void SpinBox::_range_click_timeout() {
 	if (!drag.enabled && Input::get_singleton()->is_mouse_button_pressed(MouseButton::LEFT)) {
 		bool up = get_local_mouse_position().y < (get_size().height / 2);
-		double step = get_custom_arrow_step() != 0.0 ? get_custom_arrow_step() : get_step();
-		set_value(get_value() + (up ? step : -step));
+		double step = get_step();
+		// Arrow button is being pressed, so we also need to set the step to the same value as custom_arrow_step if its not 0.
+		double temp_step = get_custom_arrow_step() != 0.0 ? get_custom_arrow_step() : get_step();
+		_set_step_no_signal(temp_step);
+		set_value(get_value() + (up ? temp_step : -temp_step));
+		_set_step_no_signal(step);
+		use_custom_arrow_step = true;
 
 		if (range_click_timer->is_one_shot()) {
 			range_click_timer->set_wait_time(0.075);
@@ -156,8 +168,7 @@ void SpinBox::gui_input(const Ref<InputEvent> &p_event) {
 	Ref<InputEventMouseButton> mb = p_event;
 	Ref<InputEventMouseMotion> mm = p_event;
 
-	double step = get_custom_arrow_step() != 0.0 ? get_custom_arrow_step() : get_step();
-
+	double step = get_step();
 	Vector2 mpos;
 	bool mouse_on_up_button = false;
 	bool mouse_on_down_button = false;
@@ -177,7 +188,12 @@ void SpinBox::gui_input(const Ref<InputEvent> &p_event) {
 				line_edit->grab_focus();
 
 				if (mouse_on_up_button || mouse_on_down_button) {
-					set_value(get_value() + (mouse_on_up_button ? step : -step));
+					// Arrow button is being pressed, so step is being changed temporarily.
+					double temp_step = get_custom_arrow_step() != 0.0 ? get_custom_arrow_step() : get_step();
+					_set_step_no_signal(temp_step);
+					set_value(get_value() + (mouse_on_up_button ? temp_step : -temp_step));
+					_set_step_no_signal(step);
+					use_custom_arrow_step = true;
 				}
 				state_cache.up_button_pressed = mouse_on_up_button;
 				state_cache.down_button_pressed = mouse_on_down_button;
@@ -193,17 +209,20 @@ void SpinBox::gui_input(const Ref<InputEvent> &p_event) {
 			case MouseButton::RIGHT: {
 				line_edit->grab_focus();
 				if (mouse_on_up_button || mouse_on_down_button) {
+					use_custom_arrow_step = false;
 					set_value(mouse_on_up_button ? get_max() : get_min());
 				}
 			} break;
 			case MouseButton::WHEEL_UP: {
 				if (line_edit->is_editing()) {
+					use_custom_arrow_step = false;
 					set_value(get_value() + step * mb->get_factor());
 					accept_event();
 				}
 			} break;
 			case MouseButton::WHEEL_DOWN: {
 				if (line_edit->is_editing()) {
+					use_custom_arrow_step = false;
 					set_value(get_value() - step * mb->get_factor());
 					accept_event();
 				}
@@ -243,6 +262,7 @@ void SpinBox::gui_input(const Ref<InputEvent> &p_event) {
 		if (drag.enabled) {
 			drag.diff_y += mm->get_relative().y;
 			double diff_y = -0.01 * Math::pow(ABS(drag.diff_y), 1.8) * SIGN(drag.diff_y);
+			use_custom_arrow_step = false;
 			set_value(CLAMP(drag.base_val + step * diff_y, get_min(), get_max()));
 		} else if (drag.allowed && drag.capture_pos.distance_to(mm->get_position()) > 2) {
 			Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED);
@@ -519,6 +539,12 @@ void SpinBox::_update_buttons_state_for_current_value() {
 	}
 }
 
+void SpinBox::_set_step_no_signal(double p_step) {
+	set_block_signals(true);
+	set_step(p_step);
+	set_block_signals(false);
+}
+
 void SpinBox::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("set_horizontal_alignment", "alignment"), &SpinBox::set_horizontal_alignment);
 	ClassDB::bind_method(D_METHOD("get_horizontal_alignment"), &SpinBox::get_horizontal_alignment);
diff --git a/scene/gui/spin_box.h b/scene/gui/spin_box.h
index 294dc3e5d5c..06a0f622b9c 100644
--- a/scene/gui/spin_box.h
+++ b/scene/gui/spin_box.h
@@ -66,6 +66,7 @@ class SpinBox : public Range {
 	String suffix;
 	String last_updated_text;
 	double custom_arrow_step = 0.0;
+	bool use_custom_arrow_step = false;
 
 	void _line_edit_input(const Ref<InputEvent> &p_event);
 
@@ -133,6 +134,7 @@ class SpinBox : public Range {
 
 	void _mouse_exited();
 	void _update_buttons_state_for_current_value();
+	void _set_step_no_signal(double p_step);
 
 protected:
 	virtual void gui_input(const Ref<InputEvent> &p_event) override;