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

Godot 4.2.2+C#:玩家全局位置与TileMap位置不更新问题

问题排查与解决思路

核心问题分析

你遇到的情况本质是获取位置的逻辑没有实时同步玩家的实际移动,虽然PRESS_COUNT正常更新说明Enter事件触发没问题,但位置始终取初始值,大概率是以下几个原因:


1. 错误使用了初始位置变量

如果你的代码里是在_Ready()中存了一个初始位置变量,之后按Enter时直接输出这个变量,而不是实时从节点获取位置,就会一直显示出生点:

// 错误示例
private Vector2 _initialPos;

public override void _Ready()
{
    _initialPos = GlobalPosition; // 只存了出生时的位置
}

private void _on_enter_pressed()
{
    GD.Print(_initialPos); // 永远输出出生点
}

修正方式:每次按Enter时直接读取节点的实时位置:

private void _on_enter_pressed()
{
    GD.Print(GlobalPosition); // 实时获取当前全局位置
}

2. 玩家移动逻辑未真正修改节点位置

如果你的移动代码只是修改了自定义变量(比如_currentPos)或者播放了动画,但没有同步更新节点的Position/GlobalPosition,那么节点实际位置根本没动,自然取到的是初始值。

以CharacterBody2D为例,正确的移动逻辑应该是:

public override void _Process(double delta)
{
    Vector2 inputDir = Input.GetVector("left", "right", "up", "down");
    if (inputDir != Vector2.Zero)
    {
        Velocity = inputDir.Normalized() * Speed;
        MoveAndSlide(); // 这个方法会自动更新CharacterBody2D的Position
    }
}

如果是普通Node2D,要确保移动时直接修改Position:

Position += inputDir.Normalized() * Speed * (float)delta;

3. TileMap坐标转换未实时计算

如果获取Tile坐标时用的是初始存的值,而不是每次按Enter时重新计算,也会得到出生点的Tile位置:

// 错误示例
private Vector2 _initialTilePos;
private TileMap _tileMap;

public override void _Ready()
{
    _tileMap = GetNode<TileMap>("../TileMap");
    _initialTilePos = _tileMap.WorldToMap(GlobalPosition); // 只存初始Tile坐标
}

private void _on_enter_pressed()
{
    GD.Print(_initialTilePos); // 永远是出生点Tile
}

修正方式:每次按Enter时重新计算Tile坐标:

private void _on_enter_pressed()
{
    Vector2 currentTilePos = _tileMap.WorldToMap(GlobalPosition);
    GD.Print(currentTilePos); // 实时获取当前Tile位置
}

4. 额外排查点

  • 检查玩家节点是否被父节点的Transform锁定,或者有没有其他脚本在偷偷重置玩家位置到出生点;
  • 在移动逻辑的最后打印GlobalPosition,确认移动时位置确实在更新;
  • 确认Enter键的输入映射正确(Project Settings → Input Map,确保ui_accept绑定了Enter键)。

修正后的完整示例代码

using Godot;

public partial class Player : CharacterBody2D
{
    [Export] public float Speed = 300f;
    private TileMap _tileMap;
    private int _pressCount = 0;

    public override void _Ready()
    {
        // 根据你的节点层级调整TileMap的获取路径
        _tileMap = GetNode<TileMap>("../TileMap");
    }

    public override void _Process(double delta)
    {
        Vector2 inputDir = Input.GetVector("left", "right", "up", "down");
        Velocity = inputDir.Normalized() * Speed;
        MoveAndSlide();
    }

    // 确保这个方法和Enter事件正确连接(或用_Input方法监听)
    private void _on_enter_pressed()
    {
        _pressCount++;
        GD.Print($"Press Count: {_pressCount}");
        
        // 实时获取当前全局位置
        GD.Print($"Current Global Position: {GlobalPosition}");
        
        // 实时计算当前Tile位置
        Vector2 currentTilePos = _tileMap.WorldToMap(GlobalPosition);
        GD.Print($"Current Tile Position: {currentTilePos}");

        // 测试修改当前Tile
        _tileMap.SetCell(currentTilePos, 1);
    }
}

内容的提问来源于stack exchange,提问作者jimsherman77

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 09:02:14