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

Unity场景切换后触摸对象锁定状态无法重置问题求助

Unity场景切换后拖拽对象锁定状态无法重置问题解决

问题描述

以下代码实现了触摸拖拽对象到目标位置后锁定的功能,但切换场景再返回原场景时,对象始终处于锁定状态,无法触发TouchPhase.Began的交互逻辑:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class no1 : MonoBehaviour
{
  [SerializeField]
    private Transform no1bg;
    private Vector2 initialPosition;
    private float deltaX,deltaY;
    public static bool locked;

    
    // Start is called before the first frame update
    void Start()
    {
      initialPosition = transform.position;  
      Application.targetFrameRate = 60;
    }

    // Update is called once per frame
    private void Update()
    {
      if (Input.touchCount > 0 && !locked)
      {
          Touch touch = Input.GetTouch(0);
          Vector2 touchpos = Camera.main.ScreenToWorldPoint(touch.position);

          switch (touch.phase)
          {
            case TouchPhase.Began: 
                if (GetComponent<Collider2D>() == Physics2D.OverlapPoint(touchpos))
                {
                  deltaX = touchpos.x - transform.position.x;
                  deltaY = touchpos.y - transform.position.y;  
                }
                break;

            case TouchPhase.Moved:
                if (GetComponent<Collider2D>() == Physics2D.OverlapPoint(touchpos))
                transform.position = new Vector2(touchpos.x - deltaX, touchpos.y - deltaY); 
                break; 

             case TouchPhase.Ended:
             if (Mathf.Abs(transform.position.x - no1bg.position.x) <= 0.5f &&
                Mathf.Abs(transform.position.y - no1bg.position.y) <= 0.5f)
             {
              transform.position = new Vector2(no1bg.position.x, no1bg.position.y);
              locked=true;   
             }
             else{
                 transform.position = new Vector2(initialPosition.x, initialPosition.y);
             }
             break; 
          }
      }  
    }
}

问题根源

locked被定义为静态变量,静态变量属于类本身而非实例对象,其生命周期覆盖整个应用程序运行期间。场景切换时,Unity不会自动重置静态变量的值,因此返回原场景时locked仍保持之前的true状态,导致触摸逻辑的!locked条件不成立,无法触发交互。

解决方案

方案1:重置静态变量(适合跨场景共享状态的场景)

通过监听场景加载事件,在目标场景加载完成后重置locked状态和对象位置:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement; // 引入场景管理命名空间

public class no1 : MonoBehaviour
{
    [SerializeField]
    private Transform no1bg;
    private Vector2 initialPosition;
    private float deltaX, deltaY;
    public static bool locked;

    void Awake()
    {
        // 注册场景加载完成事件监听
        SceneManager.sceneLoaded += OnSceneLoaded;
    }

    void OnDestroy()
    {
        // 移除监听,避免内存泄漏
        SceneManager.sceneLoaded -= OnSceneLoaded;
    }

    void Start()
    {
        initialPosition = transform.position;
        Application.targetFrameRate = 60;
    }

    private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
    {
        // 替换为你的目标场景名称,确保仅在返回该场景时重置状态
        if (scene.name == "TargetSceneName")
        {
            locked = false;
            transform.position = initialPosition;
        }
    }

    // 原有Update逻辑保持不变
    private void Update()
    {
        if (Input.touchCount > 0 && !locked)
        {
            Touch touch = Input.GetTouch(0);
            Vector2 touchpos = Camera.main.ScreenToWorldPoint(touch.position);

            switch (touch.phase)
            {
                case TouchPhase.Began:
                    if (GetComponent<Collider2D>() == Physics2D.OverlapPoint(touchpos))
                    {
                        deltaX = touchpos.x - transform.position.x;
                        deltaY = touchpos.y - transform.position.y;
                    }
                    break;

                case TouchPhase.Moved:
                    if (GetComponent<Collider2D>() == Physics2D.OverlapPoint(touchpos))
                        transform.position = new Vector2(touchpos.x - deltaX, touchpos.y - deltaY);
                    break;

                case TouchPhase.Ended:
                    if (Mathf.Abs(transform.position.x - no1bg.position.x) <= 0.5f &&
                        Mathf.Abs(transform.position.y - no1bg.position.y) <= 0.5f)
                    {
                        transform.position = new Vector2(no1bg.position.x, no1bg.position.y);
                        locked = true;
                    }
                    else
                    {
                        transform.position = new Vector2(initialPosition.x, initialPosition.y);
                    }
                    break;
            }
        }
    }
}

方案2:将locked改为非静态变量(适合单个对象独立状态的场景)

如果不需要跨场景共享锁定状态,直接移除static修饰符,让每个脚本实例在场景加载时自动初始化locked为false:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class no1 : MonoBehaviour
{
    [SerializeField]
    private Transform no1bg;
    private Vector2 initialPosition;
    private float deltaX, deltaY;
    private bool locked; // 移除static修饰符

    void Start()
    {
        initialPosition = transform.position;
        Application.targetFrameRate = 60;
        // 显式重置状态,确保场景加载时的初始状态正确
        locked = false;
        transform.position = initialPosition;
    }

    // 原有Update逻辑保持不变
    private void Update()
    {
        if (Input.touchCount > 0 && !locked)
        {
            Touch touch = Input.GetTouch(0);
            Vector2 touchpos = Camera.main.ScreenToWorldPoint(touch.position);

            switch (touch.phase)
            {
                case TouchPhase.Began:
                    if (GetComponent<Collider2D>() == Physics2D.OverlapPoint(touchpos))
                    {
                        deltaX = touchpos.x - transform.position.x;
                        deltaY = touchpos.y - transform.position.y;
                    }
                    break;

                case TouchPhase.Moved:
                    if (GetComponent<Collider2D>() == Physics2D.OverlapPoint(touchpos))
                        transform.position = new Vector2(touchpos.x - deltaX, touchpos.y - deltaY);
                    break;

                case TouchPhase.Ended:
                    if (Mathf.Abs(transform.position.x - no1bg.position.x) <= 0.5f &&
                        Mathf.Abs(transform.position.y - no1bg.position.y) <= 0.5f)
                    {
                        transform.position = new Vector2(no1bg.position.x, no1bg.position.y);
                        locked = true;
                    }
                    else
                    {
                        transform.position = new Vector2(initialPosition.x, initialPosition.y);
                    }
                    break;
            }
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 16:53:15