So I have been having issues with multikey support. I looked at the latest “Perfect Doge” and many other sample projects and replicated each version and still my character cant “Dash” when the directional key is being held.
Note: I am using a variable to determine which action to initiate from certain actions
Now if somebody could tell me why….I cant initiate a dash when walking aka pressing key + dash
ex:
Player_Still ——————→ PlayerWalking —————–> “Player_Still_Shortcut”
“Player_Still_Shortcut” ——————> PlayerDashing //Can dash from standing still
“Player_Walking_Shortcut” ————→ PlayerDashing //Cant dash if I am in Walking?
PlayerActionValues:
0 => Standing Still
PlayerActionValues >0 And PlayerActionValues<5 => “Player Walks”
Player Action Value = 6 //Makes player Dash if Standing Still, but not if in walking even tho in my console value 6 is currently being called.
Sorry if I am info dumping I just don’t get why even with just straight up numbers and no key presses I still can’t walk + Dash at the same time only standing still…..
Baz
2025 年 7 月 31 日午後 7:04
2
Can I see your script that is sending the arguments?
If it is easier you can also zip your project and send it into pgmmv-support@gotchagotcha.jp so we can investigate it more thoroughly.
Sure here is what I am using and this script is working its just an input manager for node that sends a value to visual script to detect action_values
SO for now in my visual script 1<5 = Walking
0 => Not Walking
6 => Dash
Its in Line #76
playerAction.emit(input.action, input.value)
extends Node
#calling -> Player1_Base->GameObject
@onready var player:GameObject = $".."
signal playerAction(action_name: String, action_value: float)
var buffer_time := 0.3 # Seconds input stays buffered
var combo_time_limit := 0.3 # Max seconds between combo inputs
var input_buffer := [] # Buffered inputs [{action, value, time}]
var input_history := [] # Recent inputs for combo detection [{action, time}]
var last_actions := {}
var combo_triggered := false
var can_accept_input := true
var action_values := {
"Key_Up": 1.0,
"Key_Down": 2.0,
"Key_Left": 3.0,
"Key_Right": 4.0,
"Key_Action": 5.0,
"Key_Dash": 6.0,
"Key_Attack": 7.0
}
var combo_sequence := ["Key_Dash", "Key_Attack"]
func _ready() -> void:
var timer = Timer.new()
timer.name = "CooldownTimer"
timer.wait_time = 0.5
timer.one_shot = true
timer.connect("timeout", Callable(self, "_on_cooldown_timeout"))
add_child(timer)
func _process(delta: float) -> void:
read_new_inputs()
process_buffered_inputs()
check_timed_combo()
# Emit No_Input if no keys pressed and buffer empty
var any_input_pressed = false
for action_name in action_values.keys():
if Input.is_action_pressed(action_name):
any_input_pressed = true
break
if not any_input_pressed and input_buffer.size() == 0 and can_accept_input:
playerAction.emit("No_Input", 0)
func read_new_inputs() -> void:
for action_name in action_values.keys():
if Input.is_action_just_pressed(action_name):
var now = Time.get_ticks_msec() / 1000.0
input_buffer.append({
"action": action_name,
"value": action_values[action_name],
"time": now
})
input_history.append({
"action": action_name,
"time": now
})
print("Buffered Input: ", action_name)
func process_buffered_inputs() -> void:
var now = Time.get_ticks_msec() / 1000.0
input_buffer = input_buffer.filter(func(entry):
return now - entry.time <= buffer_time
)
if can_accept_input and input_buffer.size() > 0:
var input = input_buffer.pop_front()
playerAction.emit(input.action, input.value)
print("🟢 Buffered Action Executed: ", input.action, " : ", input.value)
can_accept_input = false
$CooldownTimer.start()
func _on_cooldown_timeout() -> void:
can_accept_input = true
combo_triggered = false
func check_timed_combo() -> void:
if combo_triggered:
return
var now = Time.get_ticks_msec() / 1000.0
input_history = input_history.filter(func(entry):
return now - entry.time <= combo_time_limit
)
var recent_sequence = input_history.map(func(entry): return entry.action)
if recent_sequence.size() >= combo_sequence.size():
var recent_tail = recent_sequence.slice(-combo_sequence.size(), recent_sequence.size())
if recent_tail == combo_sequence:
playerAction.emit("Combo_Spin", 10.0)
print("🔥 Timed Combo Activated: Spin Attack!")
combo_triggered = true
input_history.clear()
Baz
2025 年 7 月 31 日午後 9:15
4
Hard to debug without the full project in my hands but I would start with some debugs here:
func process_buffered_inputs() -> void:
var now = Time.get_ticks_msec() / 1000.0
input_buffer = input_buffer.filter(func(entry):
return now - entry.time <= buffer_time
)
print("Before pop: ",input_buffer)
if can_accept_input and input_buffer.size() > 0:
var input = input_buffer.pop_front()
playerAction.emit(input.action, input.value)
print("🟢 Buffered Action Executed: ", input.action, " : ", input.value)
can_accept_input = false
$CooldownTimer.start()
print("After pop: ",input_buffer)
I’m curious if the movement input is still first out, so all that is popping is the movement input.
Well not to sure where to start in debugging myself anyhow I just sent the project files to that support email you mentioned earlier hope you guys can figure out why I can’t use “multiple keys at once”.
「いいね!」 1
Baz
2025 年 7 月 31 日午後 10:54
6
We were able to solve the issue. For anyone reading and wondering similar thing this is what was happening:
Walk → Idle link was created first priority 0
Walk → Dash link was created second priority 0
Both link conditions were true at same time and since both conditions were priority 0, Walk → Idle took priority (because it was created first)
By changing the Walk → Dash link priority to 1 (higher priority), it let that link get checked first, making it work as intended
「いいね!」 1
Once again the link condition priority issue rears its head. I’ll make a reminder post about it later on the official Twitter account too.
「いいね!」 2