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

Unity 2D平台游戏:将E键箱子抓取功能改为UI按钮实现

修改方案:将按键触发改为UI按钮触发

核心修改点

  • 新增状态变量跟踪是否正持有箱子
  • 提取抓取/释放逻辑为公共方法,供UI按钮直接调用
  • 修复原脚本中潜在的空引用错误
  • 调整射线检测时机,仅在点击抓取按钮时执行

修改后的完整脚本

using UnityEngine;

public class trigger : MonoBehaviour
{
    private PlayerMovement1 move;
    [SerializeField] public LayerMask jumpableGround;

    private PlayerPush grab;
    public float distance = 1f;
    public LayerMask boxmask;

    [SerializeField] private Animator anim;
    [SerializeField] private Rigidbody2D rb1, rb2;
    private GameObject currentHeldBlock;
    private bool isHoldingBlock = false;

    void Start()
    {
        anim = GetComponent<Animator>();
        rb1 = GetComponent<Rigidbody2D>();
        move = GetComponent<PlayerMovement1>();
        grab = GetComponent<PlayerPush>();
    }

    // 供UI抓取按钮调用的方法
    public void OnGrabButtonPressed()
    {
        if (isHoldingBlock) return; // 避免重复抓取

        Physics2D.queriesStartInColliders = false;
        RaycastHit2D hit = Physics2D.Raycast(transform.position, Vector2.right * transform.localScale.x, distance, boxmask);

        if (hit.collider != null && hit.collider.gameObject.CompareTag("block"))
        {
            currentHeldBlock = hit.collider.gameObject;
            
            // 确保箱子有FixedJoint2D组件,没有则自动添加
            FixedJoint2D joint = currentHeldBlock.GetComponent<FixedJoint2D>();
            if (joint == null)
            {
                joint = currentHeldBlock.AddComponent<FixedJoint2D>();
            }

            // 切换玩家状态
            move.enabled = false;
            grab.enabled = true;
            anim.SetBool("Push_idle", true);
            anim.SetBool("player_idle", false);
            
            joint.enabled = true;
            joint.connectedBody = rb1;
            rb2.constraints = RigidbodyConstraints2D.None;
            
            isHoldingBlock = true;
        }
    }

    // 供UI释放按钮调用的方法
    public void OnReleaseButtonPressed()
    {
        if (!isHoldingBlock || currentHeldBlock == null) return;

        FixedJoint2D joint = currentHeldBlock.GetComponent<FixedJoint2D>();
        if (joint != null)
        {
            joint.enabled = false;
        }

        // 恢复玩家原状态
        anim.SetBool("player_push", false);
        anim.SetBool("Push_idle", false);
        anim.SetBool("player_idle", true);
        move.enabled = true;
        grab.enabled = false;
        rb2.constraints = RigidbodyConstraints2D.FreezePositionX | RigidbodyConstraints2D.FreezeRotation;
        
        isHoldingBlock = false;
        currentHeldBlock = null;
    }

    void OnDrawGizmos()
    {
        Gizmos.color = Color.yellow;
        Gizmos.DrawLine(transform.position, (Vector2)transform.position + Vector2.right * transform.localScale.x * distance);
    }
}

Unity编辑器中设置UI按钮

  1. 在Canvas下创建两个Button(例如命名为"GrabButton"和"ReleaseButton")
  2. 选中抓取按钮,在Inspector的On Click()列表中:
    • 点击+号,拖拽玩家对象到对象槽
    • 在下拉菜单中选择trigger -> OnGrabButtonPressed()
  3. 对释放按钮重复上述操作,选择trigger -> OnReleaseButtonPressed()

关键细节说明

  • 新增isHoldingBlock和currentHeldBlock变量,防止重复抓取和空引用崩溃
  • 修复原脚本中先调用组件再赋值对象的顺序错误
  • 添加自动创建FixedJoint2D的逻辑,避免箱子缺少组件时出错
  • 射线检测仅在点击按钮时执行,减少不必要的性能消耗

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 17:43:07