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
相关产品推荐
相关产品推荐

