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

Unity Actions/事件/委托使用困惑:UI按钮驱动玩家移动求助

Unity UI按钮绑定静态Actions实现玩家移动方案

一、UI按钮绑定触发方法

  1. 在场景中创建前后左右四个UI按钮,选中按钮后在Inspector面板找到On Click()事件区域。
  2. 创建空物体命名为UIManager,挂载如下脚本:
using UnityEngine;

public class UIManager : MonoBehaviour
{
    // 向前按钮触发方法
    public void onMoveForwardClicked()
    {
        Actions.OnPlayerMoved?.Invoke(Directions.Forward);
    }

    // 向后按钮触发方法
    public void onMoveBackwardClicked()
    {
        Actions.OnPlayerMoved?.Invoke(Directions.Backward);
    }

    // 向左按钮触发方法
    public void onMoveLeftClicked()
    {
        Actions.OnPlayerMoved?.Invoke(Directions.Left);
    }

    // 向右按钮触发方法
    public void onMoveRightClicked()
    {
        Actions.OnPlayerMoved?.Invoke(Directions.Right);
    }
}
  1. 将UIManager物体拖拽到每个按钮的On Click()事件对象槽中,分别选择对应方向的触发方法。

二、注册Actions监听逻辑

在Player脚本中注册对Actions.OnPlayerMoved的监听,确保触发时执行移动逻辑,同时在销毁时移除监听避免内存泄漏:

using UnityEngine;

public class Player : MonoBehaviour
{
    private Vector2Int currentPos;

    private void Awake()
    {
        // 从Map类获取初始位置
        currentPos = Map.Instance.playerStartPos;
        // 注册监听:移动事件触发时执行MovePlayer
        Actions.OnPlayerMoved += MovePlayer;
    }

    private void OnDestroy()
    {
        // 移除监听,防止内存泄漏
        Actions.OnPlayerMoved -= MovePlayer;
    }

    public void MovePlayer(Directions direction)
    {
        Vector2Int newPos = currentPos;

        // 根据方向计算新位置
        switch (direction)
        {
            case Directions.Forward:
                newPos += Vector2Int.up;
                break;
            case Directions.Backward:
                newPos += Vector2Int.down;
                break;
            case Directions.Left:
                newPos += Vector2Int.left;
                break;
            case Directions.Right:
                newPos += Vector2Int.right;
                break;
        }

        // 调用Map类方法更新地图中的玩家位置
        Map.Instance.setNewPlayerPositions(currentPos, newPos);
        // 更新玩家当前位置
        currentPos = newPos;
    }
}

三、完善Map类核心逻辑

通过单例模式提供全局访问,正确处理位置更新和边界检查:

using UnityEngine;

public class Map : MonoBehaviour
{
    public static Map Instance;
    public int[,] grid;
    public Vector2Int playerStartPos;

    private void Awake()
    {
        Instance = this;
        // 初始化10x10地图
        grid = new int[10, 10];
        // 设置玩家初始中心位置
        playerStartPos = new Vector2Int(5, 5);
        // 标记初始位置为玩家所在
        grid[playerStartPos.x, playerStartPos.y] = 1;
    }

    public void setNewPlayerPositions(Vector2Int oldPos, Vector2Int newPos)
    {
        // 边界检查:防止玩家移出10x10地图范围
        if (newPos.x < 0 || newPos.x >= 10 || newPos.y < 0 || newPos.y >= 10)
            return;

        // 重置旧位置标记
        grid[oldPos.x, oldPos.y] = 0;
        // 设置新位置标记
        grid[newPos.x, newPos.y] = 1;
    }
}

四、关键细节说明

  • 空引用防护:使用?.Invoke()触发Action,避免在无监听者时抛出空引用异常。
  • 多监听机制:静态Action支持多个脚本同时监听,比如后续添加移动音效、动画触发逻辑,只需在对应脚本中注册Actions.OnPlayerMoved += 目标方法,无需修改现有代码。
  • 参数传递:Action<Directions>的泛型定义实现了方向参数的传递,触发时传入的方向会被所有监听方法接收。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 21:31:09