ATH*_*boy 1 drag-and-drop eventtrigger scrollrect scrollview unity-game-engine
我想在滚动视图的内容上实现拖放。
问题是,当您尝试在滚动视图中拖动项目时,无法滚动视图。
首先,我尝试通过IDragHandler,IBeginDragHandler,IEndDragHandle和IDropHandler接口实现拖放。乍一看,它工作得很好,但问题是您无法滚动ScrollRect。
我认为问题是由于重载造成的,当我使用事件触发器与拖动一样像rect rect时,父触发器无法正常工作。
因此,在那之后,我自己思考了一下,并通过IPointerDown,IPointerUp接口和在ScrollRect中保留可拖动UI的特定时间来实现它,如果您没有在特定时间保持它,则滚动工作会很好。
但是问题是通过启用在保持时间结束时在OnDrag,OnBeginDrag和OnEndDrag函数之前编写的DragHandler脚本不起作用。
首先我想知道有什么方法可以调用这些函数吗?
其次,有什么方法可以在不使用拖动界面的情况下实现拖放UI?
DragHandler:
using System;
using UnityEngine;
using UnityEngine.EventSystems;
public class DragHandler : MonoBehaviour, IDragHandler, IBeginDragHandler, IEndDragHandler
{
public static GameObject itemBeingDragged;
private Vector3 startPos;
private Transform startParent;
DragHandler dragHandler;
public void Awake()
{
dragHandler = GetComponent<DragHandler>();
}
public void OnBeginDrag(PointerEventData eventData)
{
Debug.Log("Begin");
itemBeingDragged = gameObject;
startPos = transform.position;
startParent = transform.parent;
}
public void OnDrag(PointerEventData eventData)
{
Debug.Log("Drag");
transform.position = Input.mousePosition;
}
public void OnEndDrag(PointerEventData eventData)
{
Debug.Log("End");
itemBeingDragged = null;
if (transform.parent == startParent)
{
dragHandler.enabled = false;
transform.SetParent(startParent);
transform.position = startPos;
}
}
}
Run Code Online (Sandbox Code Playgroud)
ScrollRectController:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class ScrollRectController : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
{
public float holdTime;
public float maxVelocity;
private Transform scrollRectParent;
private DragHandler dragHandler;
private ScrollRect scrollRect;
private float timer;
private bool isHolding;
void Awake()
{
scrollRectParent = GameObject.FindGameObjectWithTag("rec_dlg").transform;
dragHandler = GetComponent<DragHandler>();
dragHandler.enabled = false;
}
// Use this for initialization
void Start()
{
timer = holdTime;
}
// Update is called once per frame
void Update()
{
}
public void OnPointerDown(PointerEventData eventData)
{
Debug.Log("Down");
scrollRect = scrollRectParent.GetComponent<ScrollRect>();
isHolding = true;
StartCoroutine(Holding());
}
public void OnPointerUp(PointerEventData eventData)
{
Debug.Log("Up");
isHolding = false;
}
IEnumerator Holding()
{
while (timer > 0)
{
//if (scrollRect.velocity.x >= maxVelocity)
//{
// isHolding = false;
//}
if (!isHolding)
{
timer = holdTime;
yield break;
}
timer -= Time.deltaTime;
Debug.Log(timer);
yield return null;
}
dragHandler.enabled = true;
//dragHandler.OnBeginDrag();
}
}
Run Code Online (Sandbox Code Playgroud)
广告位:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class Slot : MonoBehaviour, IDropHandler
{
public void OnDrop(PointerEventData eventData)
{
DragHandler.itemBeingDragged.transform.SetParent(transform);
}
}
Run Code Online (Sandbox Code Playgroud)
小智 8
此问题最简单的解决方案实际上是,如果用户没有使用ExecuteEvents.Execute按下足够长的时间,则手动调用ScrollRect 的事件。该解决方案的附加代码量最少。
using System.Collections;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class DragAndDropHandler : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IPointerExitHandler, IDragHandler, IBeginDragHandler, IEndDragHandler
{
// Don't forget to set this to TRUE or expose it to the Inspector else it will always be false and the script will not work
public bool Draggable { get; set; }
private bool draggingSlot;
[SerializeField] private ScrollRect scrollRect;
public void OnPointerDown(PointerEventData eventData)
{
if (!Draggable)
{
return;
}
StartCoroutine(StartTimer());
}
public void OnPointerExit(PointerEventData eventData)
{
StopAllCoroutines();
}
public void OnPointerUp(PointerEventData eventData)
{
StopAllCoroutines();
}
private IEnumerator StartTimer()
{
yield return new WaitForSeconds(0.5f);
draggingSlot = true;
}
public void OnBeginDrag(PointerEventData eventData)
{
ExecuteEvents.Execute(scrollRect.gameObject, eventData, ExecuteEvents.beginDragHandler);
}
public void OnDrag(PointerEventData eventData)
{
if (draggingSlot)
{
//DO YOUR DRAGGING HERE
} else
{
//OR DO THE SCROLLRECT'S
ExecuteEvents.Execute(scrollRect.gameObject, eventData, ExecuteEvents.dragHandler);
}
}
public void OnEndDrag(PointerEventData eventData)
{
ExecuteEvents.Execute(scrollRect.gameObject, eventData, ExecuteEvents.endDragHandler);
if (draggingSlot)
{
//END YOUR DRAGGING HERE
draggingSlot = false;
}
}
}
Run Code Online (Sandbox Code Playgroud)
回答:
我编写了一些无需使用DragHandler接口即可处理scrollRect(scrollView)中的拖放的代码。
DragHandler:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class DragHandler : MonoBehaviour, IPointerExitHandler
{
public static GameObject itemBeingDragged;
public static bool isCustomerDragged;
public Transform customerScrollRect;
public Transform dragParent;
public float holdTime;
public float maxScrollVelocityInDrag;
private Transform startParent;
private ScrollRect scrollRect;
private float timer;
private bool isHolding;
private bool canDrag;
private bool isPointerOverGameObject;
private CanvasGroup canvasGroup;
private Vector3 startPos;
public Transform StartParent
{
get { return startParent; }
}
public Vector3 StartPos
{
get { return startPos; }
}
void Awake()
{
canvasGroup = GetComponent<CanvasGroup>();
}
// Use this for initialization
void Start()
{
timer = holdTime;
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0))
{
if (EventSystem.current.currentSelectedGameObject == gameObject)
{
//Debug.Log("Mouse Button Down");
scrollRect = customerScrollRect.GetComponent<ScrollRect>();
isPointerOverGameObject = true;
isHolding = true;
StartCoroutine(Holding());
}
}
if (Input.GetMouseButtonUp(0))
{
if (EventSystem.current.currentSelectedGameObject == gameObject)
{
//Debug.Log("Mouse Button Up");
isHolding = false;
if (canDrag)
{
itemBeingDragged = null;
isCustomerDragged = false;
if (transform.parent == dragParent)
{
canvasGroup.blocksRaycasts = true;
transform.SetParent(startParent);
transform.localPosition = startPos;
}
canDrag = false;
timer = holdTime;
}
}
}
if (Input.GetMouseButton(0))
{
if (EventSystem.current.currentSelectedGameObject == gameObject)
{
if (canDrag)
{
//Debug.Log("Mouse Button");
transform.position = Input.mousePosition;
}
else
{
if (!isPointerOverGameObject)
{
isHolding = false;
}
}
}
}
}
public void OnPointerExit(PointerEventData eventData)
{
isPointerOverGameObject = false;
}
IEnumerator Holding()
{
while (timer > 0)
{
if (scrollRect.velocity.x >= maxScrollVelocityInDrag)
{
isHolding = false;
}
if (!isHolding)
{
timer = holdTime;
yield break;
}
timer -= Time.deltaTime;
//Debug.Log("Time : " + timer);
yield return null;
}
isCustomerDragged = true;
itemBeingDragged = gameObject;
startPos = transform.localPosition;
startParent = transform.parent;
canDrag = true;
canvasGroup.blocksRaycasts = false;
transform.SetParent(dragParent);
}
public void Reset()
{
isHolding = false;
canDrag = false;
isPointerOverGameObject = false;
}
}
Run Code Online (Sandbox Code Playgroud)
这段代码的一些解释:
广告位:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class Slot : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
bool isEntered;
public void OnPointerEnter(PointerEventData eventData)
{
isEntered = true;
}
public void OnPointerExit(PointerEventData eventData)
{
isEntered = false;
}
void Update()
{
if (Input.GetMouseButtonUp(0))
{
if (isEntered)
{
if (DragHandler.itemBeingDragged)
{
GameObject draggedItem = DragHandler.itemBeingDragged;
DragHandler dragHandler = draggedItem.GetComponent<DragHandler>();
Vector3 childPos = draggedItem.transform.position;
//Debug.Log("On Pointer Enter");
draggedItem.transform.SetParent(dragHandler.StartParent);
draggedItem.transform.localPosition = dragHandler.StartPos;
draggedItem.transform.parent.SetParent(transform);
draggedItem.transform.parent.position = childPos;
isEntered = false;
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
此脚本的一些解释:
1.将脚本附加到放置的项目。
| 归档时间: |
|
| 查看次数: |
5015 次 |
| 最近记录: |