- Home /
How to swap gameObject during EventSystem drag?
I am not referring to the usual selected gameObjects used on UIs. I make use of the interfaces IBegin- /IEnd- /DragHandler in conjunction with the EventSystem for dragging gameobjects through the scene.
What I want to know is, when I deactivate the gameobject I am currently dragging, how can I hot-swap it with another so I don't have to click on it again. Right now it just looses focus.
Have you tired setting Selection.activeObject
to the object you want selected? https://docs.unity3d.com/ScriptReference/Selection-activeObject.html There are a a bunch of various Selection members, and I always get 'em confused, so a different one might work better...
Selection is an Editor class. and the problem is not a question about better or worse but how.
Need more details. What do you currently use for the focus? Are you talking about objects with the Selectable Interface? (https://docs.unity3d.com/ScriptReference/UI.Selectable.html)
if so, perhaps https://docs.unity3d.com/ScriptReference/UI.Selectable.Select.html will suit your needs?
No UnityEditor library classes: ok, any other restrictions we should know about?
cannot reply I your last post @Glurth. I did what you did already. notice though that with the first object dragged the EventSystem is already null, but still received input. I know the repo but didn't want to dig until nobody knows an answer
"notice though that with the first object dragged the EventSystem is already null, but still received input."
An object does not need to be the "selected object" to receive input/events. Nor does receiving input/events automatically select it. Unless, of course, specified otherwise (which is what you need to do.)
Sometimes people want the object to become selected OnPointerOver, sometimes it's OnPointerUp, or whatever; so you need to specify. Sounds like adding the SetSelectedGameObject call inside OnDragStart is what you are looking for.
The Selectable class for example only does this in Select(), and the InputField class, as another example, does this in OnPointerDown https://github.com/$$anonymous$$attRix/UnityDecompiled/blob/753fde37d331b2100f93cc5f9eb343f1dcff5eee/UnityEngine.UI/UnityEngine.UI/InputField.cs
I already used SetSelectedGameObject. but despite having a selected gameobject the EventSystem still does not send drag events to the new one.
Answer by Glurth · Feb 06, 2017 at 06:49 PM
You will need to track the drag focus yourself to do this.
Replace the StandaloneInputModule component, on your EventSystem game object, with this one:
public class DragInputModule : StandaloneInputModule
{
static public GameObject dragFocusObject;
protected override void ProcessDrag(PointerEventData pointerEvent)
{
if (!pointerEvent.dragging)
dragFocusObject = null;
if (dragFocusObject != null)
pointerEvent.pointerDrag = dragFocusObject;
base.ProcessDrag(pointerEvent);
}
}
The important part to note is that the PointerEventData itself, contains the reference to the dragged object. This is how the dragged object reference is passed to the EventSystem.
Thought the only relevant line in this usage sample is:
DragInputModule.dragFocusObject = anotherObject;
Here's the whole sample class anyway (at the 5 second mark, it switches the drag focus to "anotherObject"- it is assumed this object is an IDragHandler for the effect to be seen (I put two of these in my test scene):
public class DragMe : MonoBehaviour, IDragHandler
{
public GameObject anotherObject;
static public bool swapDone = false;
private void Update()
{
if (DragInputModule.dragFocusObject == null)
Debug.Log("currentDragObject is null");
else
Debug.Log(DragInputModule.dragFocusObject.name + " is the drag obect");
if ((Time.realtimeSinceStartup > 5) && (swapDone==false))
{
swapDone = true;
DragInputModule.dragFocusObject = anotherObject;
}
}
public void OnDrag(PointerEventData data)
{
//do some actual drag move stuff
transform.position += new Vector3(data.delta.x, data.delta.y, 0) * .01f;
}
}
Please note: I've only done limited testing, but initial tests show this working.
I noticed the debuglogs were not reflectng what I expected. Additional test showed the following code actually worked in the ProcessDrag override. It implies that only the first pointer event data, after pointerEvent.dragging becomes true, needs to be changed!
protected override void ProcessDrag(PointerEventData pointerEvent)
{
if(pointerEvent.dragging && (dragFocusObject != null))
pointerEvent.pointerDrag = dragFocusObject;
base.ProcessDrag(pointerEvent);
dragFocusObject = null;
}
oh, that looks like something. pointerDrag... yeah, I'll have a look thanks