前提
以下の様な親子構造になっているオブジェクトの「子」を選択して動かせるようにする機能を実装しています.
親であるGroupオブジェクト
子オブジェ(A,B同じ)
親(Groupオブジェクト)のDragと,AorB各オブジェクトのDragが出来る様にするために親子構造になっています.
子のDragをする際は親子関係を解消してCanvas直下にA,Bが来るようにしています.
親のDragか子のDragかの判定は,子(実際にはGroupオブジェ)の長押し成立でしています.
長押し成立 →親子関係を解消して指定した子を動かせるようにする.
長押し不成立→親子関係は解消せず親を動かせる(=A,B相対位置を変えずに動かせる).
実現したいこと&発生している問題
一度のタップで子のDragまで行いたいのですが,Dragが出来ません.
該当のソースコード
c#
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; //Groupオブジェクトにつける. public class ClickObject : MonoBehaviour, IPointerDownHandler, IPointerUpHandler { [SerializeField] private RectTransform A; [SerializeField] private RectTransform B; //private PointerEventData tempPed; //長押し処理用. private Coroutine coroutine; private readonly float time = 1.0f; private void Start() { GetComponent<DragObject>().MoveAction += CancelLongTap; } /// <summary> /// 長押し成立でおこなう処理. /// </summary> /// <returns></returns> private IEnumerator TimerCoroutine() { yield return new WaitForSeconds(time); Debug.Log("Timer End!"); //A,Bの親をCanvas直下に変更.Groupを解消. A.SetParent(this.transform.parent); B.SetParent(this.transform.parent); //A,Bをさわれるようにする. A.GetComponent<CanvasGroup>().blocksRaycasts = true; B.GetComponent<CanvasGroup>().blocksRaycasts = true; ShootRay(); } /// <summary> /// Groupオブジェクト(AorBオブジェクトの上)をTapしたときに呼ばれる. /// </summary> /// <param name="eventData"></param> public void OnPointerDown(PointerEventData eventData) { coroutine = StartCoroutine(TimerCoroutine()); //長押し判定開始. //tempPed = eventData; } public void OnPointerUp(PointerEventData eventData) { if (coroutine != null) CancelLongTap(); } /// <summary> /// 長押し判定コルーチン動作中に動いたらキャンセル. /// </summary> public void CancelLongTap() { if (coroutine != null) StopCoroutine(coroutine); coroutine = null; // tempPed = null; } /// <summary> /// /UserがTapした真のTarget(AorB)にray飛ばして取得. /// </summary> private void ShootRay() { //現在のマウスの位置からレイキャストを撃ってヒットしたものを取得します。 GraphicRaycaster gr = transform.root.GetComponent<GraphicRaycaster>(); PointerEventData ped = new PointerEventData(EventSystem.current); // = CopyEventData(tempPed); ped.position = Input.mousePosition; List<RaycastResult> rr = new List<RaycastResult>(); gr.Raycast(ped, rr); GameObject target = rr[0].gameObject; //D&Dの対象となるAorBは一番手前の要素のはず. Debug.Log("Target Name:" + target.name); //AorBオブジェクトならそれをそのままDragしたい if (target.name == "A" || target.name == "B") target.GetComponent<DragObject>().MyContinue(ped, rr[0]); } private PointerEventData CopyEventData(PointerEventData original) { return new PointerEventData(EventSystem.current) { selectedObject = original.selectedObject, hovered = original.hovered, button = original.button, clickCount = original.clickCount, clickTime = original.clickTime, delta = original.delta, dragging = original.dragging, eligibleForClick = original.eligibleForClick, pointerCurrentRaycast = original.pointerCurrentRaycast, pointerDrag = original.pointerDrag, pointerEnter = original.pointerEnter, pointerId = original.pointerId, pointerPress = original.pointerPress, pointerPressRaycast = original.pointerPressRaycast, position = original.position, pressPosition = original.pressPosition, rawPointerPress = original.rawPointerPress, scrollDelta = original.scrollDelta, useDragThreshold = original.useDragThreshold, }; } }
c#
using UnityEngine; using UnityEngine.EventSystems; using System; using System.Collections; public class DragObject : MonoBehaviour, IBeginDragHandler, IDragHandler { public Action MoveAction; private GameObject groupObj; //AorB用 private void Start() { groupObj = transform.parent.gameObject; } public void OnBeginDrag(PointerEventData eventData) { if (MoveAction != null) MoveAction(); //長押し中に動いた } public void OnDrag(PointerEventData eventData) { this.transform.position = eventData.position; } public void MyContinue(PointerEventData eventData,RaycastResult rr) { StartCoroutine(Method(eventData, rr)); } private IEnumerator Method(PointerEventData eventData, RaycastResult rr) { Destroy(groupObj); //Groupオブジェクトを削除. Debug.Log("Destroy"); yield return null; GameObject target = this.gameObject; eventData.pointerDrag = target; eventData.pointerCurrentRaycast = rr; eventData.rawPointerPress = target; eventData.pointerPress = target; eventData.pointerDrag = target; eventData.pointerPressRaycast = rr; eventData.selectedObject = target; Debug.Log(eventData.selectedObject.name); ExecuteEvents.Execute(target, eventData, ExecuteEvents.beginDragHandler); } }
試したこと
コードに記したように,親子関係が解消された後にスクリプト上からRayを打ってExecuteEvents.Execute()することでDrag出来る様にならないか試してみましたがダメでした.
補足情報(FW/ツールのバージョンなど)
Unity2020.3.30f1
Microsoft Visual Studio Community 2019 Version 16.11.9
まだ回答がついていません
会員登録して回答してみよう