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

Godot Engine场景间数据传递:敌人如何正确获取玩家位置?

跨场景实现敌人跟随玩家的方案

当玩家和敌人分属不同场景时,核心是解决跨场景的位置数据共享问题,以下是几种实用的实现方式:

1. 全局单例状态管理

创建一个全局的玩家状态管理类,让它跨场景保留,玩家实时更新位置到这个单例,敌人直接从单例读取最新坐标。

示例代码(以Unity为例):

// 全局玩家状态单例
public class PlayerState : MonoBehaviour
{
    public static PlayerState Instance;
    public Vector3 CurrentPosition;

    void Awake()
    {
        // 确保单例唯一且跨场景不销毁
        if (Instance == null)
        {
            Instance = this;
            DontDestroyOnLoad(gameObject);
        }
        else
        {
            Destroy(gameObject);
        }
    }
}

// 玩家脚本中更新位置
public class PlayerController : MonoBehaviour
{
    void Update()
    {
        if (PlayerState.Instance != null)
        {
            PlayerState.Instance.CurrentPosition = transform.position;
        }
    }
}

// 敌人脚本中读取位置并跟随
public class EnemyFollower : MonoBehaviour
{
    public float MoveSpeed = 3f;

    void Update()
    {
        if (PlayerState.Instance == null) return;
        
        Vector3 targetPos = PlayerState.Instance.CurrentPosition;
        transform.position = Vector3.MoveTowards(transform.position, targetPos, MoveSpeed * Time.deltaTime);
    }
}

2. 全局事件订阅机制

通过自定义事件系统,玩家位置变化时触发全局事件,敌人场景订阅该事件来同步位置,这种方式耦合度更低。

示例代码:

// 全局事件定义
public static class GameEvents
{
    public static event Action<Vector3> OnPlayerPositionChanged;

    public static void BroadcastPlayerPosition(Vector3 newPos)
    {
        OnPlayerPositionChanged?.Invoke(newPos);
    }
}

// 玩家端触发事件
public class PlayerController : MonoBehaviour
{
    void Update()
    {
        GameEvents.BroadcastPlayerPosition(transform.position);
    }
}

// 敌人端订阅事件
public class EnemyFollower : MonoBehaviour
{
    private Vector3 _targetPos;
    public float MoveSpeed = 3f;

    void OnEnable()
    {
        GameEvents.OnPlayerPositionChanged += UpdateTargetPosition;
    }

    void OnDisable()
    {
        // 必须取消订阅,避免内存泄漏
        GameEvents.OnPlayerPositionChanged -= UpdateTargetPosition;
    }

    void UpdateTargetPosition(Vector3 newPos)
    {
        _targetPos = newPos;
    }

    void Update()
    {
        transform.position = Vector3.MoveTowards(transform.position, _targetPos, MoveSpeed * Time.deltaTime);
    }
}

3. 场景加载时传递初始位置(适合场景切换场景)

如果敌人场景是在玩家场景之后加载,可以在切换场景前把玩家位置临时存储,敌人场景初始化时读取,后续再通过单例/事件持续更新。

示例代码:

// 玩家场景切换到敌人场景前
public class SceneSwitcher : MonoBehaviour
{
    public void LoadEnemyScene()
    {
        // 临时存储玩家位置
        PlayerPrefs.SetFloat("PlayerPosX", GameObject.Find("Player").transform.position.x);
        PlayerPrefs.SetFloat("PlayerPosY", GameObject.Find("Player").transform.position.y);
        PlayerPrefs.SetFloat("PlayerPosZ", GameObject.Find("Player").transform.position.z);
        
        UnityEngine.SceneManagement.SceneManager.LoadScene("EnemyScene");
    }
}

// 敌人场景初始化时读取
public class EnemyInitializer : MonoBehaviour
{
    private Vector3 _initialPlayerPos;

    void Start()
    {
        _initialPlayerPos = new Vector3(
            PlayerPrefs.GetFloat("PlayerPosX"),
            PlayerPrefs.GetFloat("PlayerPosY"),
            PlayerPrefs.GetFloat("PlayerPosZ")
        );
        // 后续切换到单例/事件来持续获取实时位置
    }
}

注意事项

  • 单例模式要确保对象唯一,避免重复创建导致数据混乱
  • 事件订阅必须在对象销毁时取消,防止内存泄漏
  • 如果是多人游戏,需要依赖服务器同步玩家位置,而非本地直接共享

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 20:25:07