Tengo problemas para intentar resolver este problema que tengo al migrar mi antiguo juego Unity5 a Unity 2020. Tengo todo funcionando nuevamente, excepto por este problema con mis botones que no funcionan debido a que una actualización de "HitTest" está obsoleta. ¿Qué puedo hacer para que esto funcione sin comenzar completamente desde cero?
foreach (Touch touch in Input.touches) { if (touch.phase == TouchPhase.Stationary && hitButton.HitTest(touch.position)) { GetComponent<Rigidbody2D>().MoveRotation(80); }Haría un Canvas como hijo del gameobject con los componentes rigidbody2d/collider2d, luego colocaría el botón en ese lienzo, y luego en su código anterior, mantendría una referencia al lienzo y al botón que vive allí.
Luego, puedes usar GraphicRaycaster.Raycast . Versión modificada del código fuente en Unity Docs :
// Attach this script to your Canvas GameObject. // Also attach a GraphicsRaycaster component to your canvas by clicking the // Add Component button in the Inspector window. // Also make sure you have an EventSystem in your scene using UnityEngine; using UnityEngine.UI; using UnityEngine.EventSystems; using System.Collections.Generic; public class RaycasterTester : MonoBehaviour { GraphicRaycaster m_Raycaster; void Start() { //Fetch the Raycaster from the GameObject (the Canvas) m_Raycaster = GetComponent<GraphicRaycaster>(); } public bool TestTouch(Touch touch, GameObject target) { //Set up the new Pointer Event PointerEventData pointerEventData = new PointerEventData(EventSystem.current); //Set the Pointer Event Position to that of the touch position pointerEventData.position = touch.position; //Create a list of Raycast Results List<RaycastResult> results = new List<RaycastResult>(); //Raycast using the Graphics Raycaster and touch position m_Raycaster.Raycast(pointerEventData, results); foreach (RaycastResult result in results) { if (result.gameObject == target) return true; } return false; } }Básicamente, la jerarquía se parece a esto en tiempo de ejecución:
Flipper object [ Rigidbody2D, Collider2D, questionScript (references RaycasterTester and Button) ] L Canvas object [ Canvas (world space), GraphicRaycaster, RaycasterTester ] L Button object [ Button, Image, hitButtonScript (?) ] (somewhere in scene) [ EventSystem ] Luego, en el script de preguntas, obtenga una referencia a la instancia del script anterior y luego llame al método TestTouch :
foreach (Touch touch in Input.touches) { if (touch.phase == TouchPhase.Stationary && raycasterTester.TestTouch(touch, hitButton.gameObject)) { GetComponent<Rigidbody2D>().MoveRotation(80); // break to avoid being turned by multiple touches? // break; } } Por cierto, si el código de la pregunta está ocurriendo en Update , podría ser mejor llamar a GetComponent<Rigidbody2D> en Start (o, si alguna vez se quita y/o reemplaza Rigidbody2D, también en esos momentos) y almacenar en caché los resultados, ya que puede ser una operación costosa.
En realidad, mejor que verificar esto manualmente sería un UI.Button + además implementar una extensión personalizada usando las IPointerDownHandler e IPointerUpHandler , etc. (nota: la API vinculada es 2018, pero esto también se aplica a 2020, simplemente movieron la API a un paquete y ahí no está tan bien explicado) como
public class HoldButton : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IPointerEnterHandler, IPointerExitHandler { // Called once when the button goes down (comparable to GetKeyDown) public UnityEvent OnButtonDown; // Called every frame while the button is pressed (comparable to GetKey) public UnityEvent WhilePressed; // Called once when the button goes up (comparable to GetKeyUp) public UnityEvent OnButtonUp; // Called if you hover with the mouse or drag an existing touch into the button public void OnPointerEnter(PointerEventData pointerEventData) { // Not sure if needed for OnPointerExit to work, doing nothing else } // Called when mouse or touch leaves the button public void OnPointerExit(PointerEventData pointerEventData) { OnButtonUp.Invoke(); StopAllCoroutines(); } // Called if you press the mouse or begin a touch over this button public void OnPointerDown(PointerEventData pointerEventData) { OnButtonDown.Invoke(); StartCoroutine (WhilePressedRoutine()); } // Called if you release mouse or touch over this button public void OnPointerUp(PointerEventData pointerEventData) { OnButtonUp.Invoke(); StopAllCoroutines(); } private IEnumerator WhilePressedRoutine() { while(true) { WhilePressed.Invoke(); yield return null; } } } En estos UnityEvent s, puede hacer referencia a sus métodos de controlador como en UI.Button.onClick a través del Inspector o en tiempo de ejecución a través de un script.
Entonces, puede adjuntar esto en un elemento de la interfaz de usuario (como un Button ) y dejar que el EventSystem de la escena llame a los controladores de puntero.
¡O incluso puede adjuntar esto a objetos 3D normales! En tal caso, esto requiere adicionalmente
PhysicsRaycaster en su CameraO para un objeto 2D en consecuencia
Physics2DRaycaster en tu CameraEstas interfaces funcionan tanto para el mouse como para la entrada táctil (excepto para la entrada del puntero, probablemente porque un toque no puede simplemente pasar el mouse, al menos no en todos los teléfonos;))