Search Unity

Help adding (UI) events at RunTime

Discussion in 'Scripting' started by CodeFang, Apr 19, 2021.

  1. CodeFang

    CodeFang

    Joined:
    Nov 20, 2020
    Posts:
    12
    Hello everybody, I've been following some inventory tutorial and making some changes here and there, but now I have run into a bit of a problem.

    I have an inventory that dynamically creates gameObjects for its slots and adds various Pointer Events to them (OnDragBegin, etc.). However the trouble I have here is that left and rightclick do exactly the same thing, while I might want only left click to start dragging the item or maybe right click to just drag a single item and not the whole stack.

    I think I need the Pointer Event Data to differentiate between left and right click dragging.

    Some of the code I am currently using:
    Code (CSharp):
    1.     protected void AddEvent(GameObject obj, EventTriggerType type, UnityAction<BaseEventData> action)
    2.     {
    3.         EventTrigger trigger = obj.GetComponent<EventTrigger>();
    4.         if (!trigger) { Debug.LogWarning("No EventTrigger component found!"); return; }
    5.         var eventTrigger = new EventTrigger.Entry { eventID = type };
    6.         eventTrigger.callback.AddListener(action);
    7.         trigger.triggers.Add(eventTrigger);
    8.     }
    Code (CSharp):
    1. private void CreateSlot(int i, InventorySlot slot)
    2.     {
    3.         var obj = Instantiate(inventoryPrefab, layoutGroup.transform);
    4.  
    5.         AddEvent(obj, EventTriggerType.PointerEnter, delegate { OnEnter(obj); });
    6.         AddEvent(obj, EventTriggerType.PointerExit, delegate { OnExit(obj); });
    7.         AddEvent(obj, EventTriggerType.BeginDrag, delegate { OnBeginDrag(obj);});
    8.         AddEvent(obj, EventTriggerType.EndDrag, delegate { OnEndDrag(obj); });
    9.         AddEvent(obj, EventTriggerType.Drag, delegate { OnDrag(obj); });
    10.  
    11.         GameObjectToInventorySlot.Add(obj, slot);
    12.         InventorySlotToGameObject.Add(slot, obj);
    13.     }
    Code (CSharp):
    1.     public void OnBeginDrag(GameObject obj)
    2.     {
    3.         if (GameObjectToInventorySlot[obj].item.Id >= 0)
    4.         {
    5.             var mouseObject = Instantiate(mouseItemPrefab, Vector2.zero, Quaternion.identity, GetComponentInParent<Canvas>().transform);
    6.             var img = mouseObject.GetComponent<Image>();
    7.             img.sprite = GetItemSprite(GameObjectToInventorySlot[obj]);
    8.             img.raycastTarget = false;
    9.             MouseData.tempItemBeingDragged = mouseObject;
    10.         }
    11.     }
    I really don't know how to dynamically add the event that also passes me the Pointer Event data. I can create a script using the needed interfaces (IBeginDraghandler, etc.) but even then I would not know how to write an "Addevent" function to add them dynamically.

    Help is appreciated. Thank you very much!
     
  2. MDADigital

    MDADigital

    Joined:
    Apr 18, 2020
    Posts:
    2,198
    change delegate { OnEnter(obj); } to e => OnEnter(e, obj)


    e is the event data

    edit, btw, that will allocate becasue of closure
     
  3. CodeFang

    CodeFang

    Joined:
    Nov 20, 2020
    Posts:
    12
    Thanks this works!!! Amazing. It felt kind of unintuitive to me. Probably need to read up on Closure Allocation? Is there any resource you would recommend. I'll try to google in the mean time.
     
  4. MDADigital

    MDADigital

    Joined:
    Apr 18, 2020
    Posts:
    2,198
    When a delegate needs be scoped (in this case becasue of the reference to the gameobject) it will box the delegate in a reference. That will allocate. If you can remove the gameobject and only use the data from the argument sent into the action you will remove the allocation.
     
    CodeFang likes this.
  5. MDADigital

    MDADigital

    Joined:
    Apr 18, 2020
    Posts:
    2,198
    Btw it will only allocate once, when you subscribe. So if you dont subscribe that often its probably fine.