You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Godot中D20战斗系统代码求助:回合交替与循环失效

Godot D20战斗系统问题排查与规范解答

一、攻击者连续攻击两次的问题

核心问题是回合切换时的参数传递错误,以及部分逻辑的顺序问题:

  1. 初始_start_combat中,turn(enemy, player)的参数是对的(turn(target, attacker),即玩家攻击敌人),但在turn函数的miss分支、damage函数的回合切换分支,你错误地调用了_start_combat(attacker,target)——_start_combat的参数要求是player, enemy,传递交换后的角色会导致回合逻辑混乱,出现连续攻击。
  2. 另外建议把player和enemy存为AutoLoad的全局变量,避免每次重复传递,减少参数错误概率。

修正思路:切换回合后调用_start_combat时,传入全局存储的玩家和敌人,而非临时的attacker和target。

二、for循环无法输出2个数值的问题

你的循环代码里第一次迭代就执行了return,直接跳出了循环,导致永远只执行一次骰子投掷:

for n in attacker.row:
    dmg_roll += roll(attacker.dice)
    print(dmg_roll)
    return damage(target, attacker, dmg_roll)  # 这里直接return,循环只走一次

修正方法:将return移出循环,等所有骰子投掷完成后再调用damage函数:

var dmg_roll : int = 0
for n in attacker.row:
    var single_roll = roll(attacker.dice)
    dmg_roll += single_roll
    print("单次骰子结果:", single_roll, " | 当前总伤害:", dmg_roll)
# 循环结束后统一处理伤害
damage(target, attacker, dmg_roll)

三、函数接收参数与传入变量同名是否规范?

这在GDScript(以及绝大多数编程语言)里是完全规范且推荐的做法。比如你示例中的:

func turn(target, attacker):
    ...
        damage(target, attacker, dmg_roll)
        
func damage(target, attacker, dmg_roll):
    ...

函数参数是局部变量,仅在函数内部生效,不会与外部同名变量冲突。这种命名方式能让代码逻辑更清晰,避免冗余命名(比如target_param这种不必要的后缀)。

修正后的完整代码示例

extends Node2D

var enemy_turn : bool = false
var critical_Hit : bool = false
# 全局存储对战双方,避免重复传递参数
var current_player = null
var current_enemy = null

func _start_combat(player, enemy):
    current_player = player
    current_enemy = enemy
    if enemy_turn == false:
        # 玩家回合:玩家攻击敌人
        turn(current_enemy, current_player)
    else:
        # 敌人回合:敌人攻击玩家
        turn(current_player, current_enemy)

func roll(dice) -> int:
    var random_number = RandomNumberGenerator.new()
    random_number.randomize()
    return random_number.randi_range(1, dice)

func turn(target, attacker):
    print(attacker.char_name, " 攻击 ", target.char_name)
    var iniciative_roll = roll(20)
    print(" Initiative d20: ", iniciative_roll)
    
    critical_Hit = false
    if iniciative_roll == 20:
        print("暴击!")
        critical_Hit = true
    elif iniciative_roll >= abs(target.ac - attacker.thac0):
        pass  # 普通命中,critical_Hit保持false
    else:
        print(attacker.char_name, " 攻击落空。")
        enemy_turn = !enemy_turn
        _start_combat(current_player, current_enemy)
        return
    
    var dmg_roll : int = 0
    for n in attacker.row:
        var single_roll = roll(attacker.dice)
        dmg_roll += single_roll
        print(" 骰子投掷:", single_roll, " | 当前累计伤害:", dmg_roll)
    # 循环结束后处理伤害结算
    damage(target, attacker, dmg_roll)
        
func damage(target, attacker, aux):
    var final_damage = aux
    if critical_Hit == true:
        final_damage = aux * 2
        target.hp -= final_damage
        print(attacker.char_name, " 打出暴击!对 ", target.char_name, " 造成 ", final_damage, " 点伤害")
    else:
        target.hp -= final_damage
        print(attacker.char_name, " 对 ", target.char_name, " 造成 ", final_damage, " 点伤害")
    
    if target.hp <= 0:
        target._death()
    else:
        enemy_turn = !enemy_turn
        _start_combat(current_player, current_enemy)

内容的提问来源于stack exchange,提问作者Marcelo João

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 05:00:52