Search Unity

Replicating Dragging Prefabs into the Scene but for the Player

Discussion in 'Scripting' started by Aimlessone, May 12, 2016.

  1. Aimlessone

    Aimlessone

    Joined:
    Jun 26, 2015
    Posts:
    46
    There is probably a simple solution to this problem but hard to explain. My game currently has an inventory screen, when I click a button in the game a screen comes up that covers half the scene. In that screen is an inventory of all the gameobjects for this particular scene. What I want the player to be able to do is click and drag that inventory item into the scene. The trick here is that the inventory items aren’t the gameobject itself, it’s just a picture of the gameobject I want to be able to instantiate. I also don’t want to just take the gameobject from the inventory into the screen but rather copy the prefab into the scene.



    Confusing?



    Basic bottom line goal is to replicate dragging prefabs into the scene but for the players. Click, drag, drop and it copies the prefab into the scene and give the players the freedom to make as many as those gameobject as they please.



    Perhaps I need to recode my inventory system to actually hold a gameobject, not quite sure how to tackle this one.
     
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,531
    I did this recently by having buttons in our inventory GUI for each item.

    If the person clicked down and held, then dragged off the button, I would Instantiate a prefab that was referenced by that button on screen under the mouse cursor.

    You can see how I do it here... but note, it's specialized to my software, it's certainly not copy/paste. But could be used as a guideline:
    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using UnityEngine.UI;
    4. using UnityEngine.EventSystems;
    5. using System.Collections.Generic;
    6. using System.Linq;
    7.  
    8. using com.spacepuppy;
    9. using com.spacepuppy.Spawn;
    10. using com.spacepuppy.Utils;
    11.  
    12. using com.vivarium.Interactable;
    13. using com.vivarium.UserInput;
    14.  
    15. namespace com.vivarium.Entities.UI.Menus
    16. {
    17.  
    18.     public class BuilderModeMenu : SPComponent
    19.     {
    20.  
    21.         #region Fields
    22.  
    23.         [SerializeField()]
    24.         private BuilderDragAndDropController _dragAndDropController;
    25.  
    26.         [SerializeField()]
    27.         private RectTransform _scrollArea;
    28.  
    29.         [SerializeField()]
    30.         private GameObject _buttonPrefab;
    31.  
    32.         [SerializeField()]
    33.         private RectTransform _lockButton;
    34.  
    35.         [SerializeField()]
    36.         private float _floatDistanceInFrontOfCamera = 2f;
    37.  
    38.  
    39.         [System.NonSerialized()]
    40.         private bool _buttonsDirty;
    41.         [System.NonSerialized()]
    42.         private List<ButtonActivateEvent> _buttonEvents = new List<ButtonActivateEvent>();
    43.  
    44.         #endregion
    45.  
    46.         #region CONSTRUCTOR
    47.  
    48.         protected override void Awake()
    49.         {
    50.             base.Awake();
    51.  
    52.             _buttonsDirty = true;
    53.             Notification.RegisterGlobalObserver<VivariumInventory.AvailableInventoryChangedNotification>(this.OnAvailInventoryChanged);
    54.         }
    55.  
    56.         protected override void OnStartOrEnable()
    57.         {
    58.             base.OnStartOrEnable();
    59.  
    60.             if(_buttonsDirty)
    61.             {
    62.                 _buttonsDirty = false;
    63.                 this.SyncButtons();
    64.             }
    65.  
    66.             var inventory = Singleton.GetInstance<VivariumInventory>(true);
    67.             bool touchedInventory = false;
    68.             var d = new System.EventHandler(this.OnButtonActivated);
    69.             for (int i = 0; i < _buttonEvents.Count; i++)
    70.             {
    71.                 var ev = _buttonEvents[i];
    72.                 ev.ButtonActivated += d;
    73.  
    74.                 var item = inventory.AvailableItems.GetItem(ev.ItemID);
    75.                 bool bUntouched = false;
    76.                 if(item != null)
    77.                 {
    78.                     touchedInventory = true;
    79.                     bUntouched = true;
    80.                     item.Untouched = false;
    81.                 }
    82.  
    83.                 //TODO - highlight the untouched inventory
    84.             }
    85.  
    86.             if (touchedInventory)
    87.             {
    88.                 inventory.SignalAvailableInventoryChanged();
    89.             }
    90.         }
    91.  
    92.         protected override void OnDisable()
    93.         {
    94.             base.OnDisable();
    95.  
    96.             var d = new System.EventHandler(this.OnButtonActivated);
    97.             for (int i = 0; i < _buttonEvents.Count; i++)
    98.             {
    99.                 var ev = _buttonEvents[i];
    100.                 ev.ButtonActivated -= d;
    101.             }
    102.         }
    103.  
    104.         #endregion
    105.  
    106.  
    107.         #region Methods
    108.  
    109.         private void SyncButtons()
    110.         {
    111.             //purge buttons
    112.             if(_buttonEvents.Count > 0)
    113.             {
    114.                 for(int j = 0; j < _buttonEvents.Count; j++)
    115.                 {
    116.                     _buttonEvents[j].gameObject.Kill();
    117.                 }
    118.                 _buttonEvents.Clear();
    119.             }
    120.  
    121.             //update
    122.             const float SPACING = 10f;
    123.             const float WIDTH = 60f;
    124.  
    125.             var inventory = Singleton.GetInstance<VivariumInventory>(true);
    126.             if(inventory != null)
    127.             {
    128.                 var e = inventory.AvailableItems.GetEnumerator();
    129.  
    130.                 int i = 0;
    131.                 while (e.MoveNext())
    132.                 {
    133.                     var go = SpawnPool.DefaultPool.Spawn(_buttonPrefab, _scrollArea);
    134.                     var trans = go.GetComponent<RectTransform>();
    135.  
    136.                     //create icon
    137.                     var icon = e.Current.CreateIcon();
    138.                     if (icon != null)
    139.                     {
    140.                         go.GetComponent<Image>().sprite = icon;
    141.                     }
    142.                     else
    143.                     {
    144.                         var text = trans.GetChild(0).GetComponent<Text>();
    145.                         text.text = e.Current.Id;
    146.                         text.gameObject.SetActive(true);
    147.                     }
    148.  
    149.                     //position
    150.                     trans.sizeDelta = new Vector2(WIDTH, WIDTH);
    151.                     trans.localPosition = new Vector3(i * (SPACING + WIDTH) + (SPACING + WIDTH / 2f), 0f, 0f);
    152.                     trans.localScale = Vector3.one;
    153.  
    154.                     //create event listener
    155.                     var ev = go.AddComponent<ButtonActivateEvent>();
    156.                     ev.ItemID = e.Current.Id;
    157.                     _buttonEvents.Add(ev);
    158.  
    159.                     //next
    160.                     i++;
    161.                 }
    162.  
    163.                 if(inventory.AvailableItems.Count < inventory.AllItems.Count)
    164.                 {
    165.                     _lockButton.localPosition = new Vector3(i * (SPACING + WIDTH) + (SPACING + WIDTH / 2f), 0f, 0f);
    166.                     _lockButton.gameObject.SetActive(true);
    167.                     i++;
    168.                 }
    169.                 else
    170.                 {
    171.                     _lockButton.localPosition = Vector2.zero;
    172.                     _lockButton.gameObject.SetActive(false);
    173.                 }
    174.  
    175.                 float totalWidth = i * (SPACING + WIDTH) + SPACING;
    176.                 _scrollArea.sizeDelta = new Vector2(totalWidth, 0f);
    177.  
    178.  
    179.             }
    180.             else
    181.             {
    182.                 _scrollArea.sizeDelta = Vector2.zero;
    183.             }
    184.  
    185.          
    186.         }
    187.  
    188.         private void OnAvailInventoryChanged(object sender, VivariumInventory.AvailableInventoryChangedNotification n)
    189.         {
    190.             _buttonsDirty = true;
    191.             //TODO - check if in builder-mode and the menu is open so as to update buttons immediately... need to decide how that would visually look
    192.  
    193.  
    194.         }
    195.  
    196.  
    197.  
    198.  
    199.  
    200.         private void StartAddItem(string itemId)
    201.         {
    202.             if (_dragAndDropController == null) return;
    203.  
    204.             var inventory = Singleton.GetInstance<VivariumInventory>(true);
    205.             if (inventory == null) return;
    206.  
    207.             var item = inventory.AvailableItems.GetItem(itemId);
    208.             if (item == null) return;
    209.  
    210.  
    211.  
    212.             var cam = _dragAndDropController.ClickCamera;
    213.             var input = Game.InputManager.GetDevice<VivariumInputDevice>(Game.MAIN_INPUT);
    214.             Ray ray = cam.ScreenPointToRay(input.GetCurrentCursorState(VivariumInputs.Cursor));
    215.             RaycastHit hit;
    216.  
    217.             Vector3 targPos;
    218.             if (Physics.Raycast(ray, out hit, float.PositiveInfinity, Constants.MASK_TERRAIN))
    219.             {
    220.                 targPos = hit.point;
    221.             }
    222.             else
    223.             {
    224.                 targPos = ray.GetPoint(_floatDistanceInFrontOfCamera);
    225.             }
    226.  
    227.             var go = item.Create();
    228.             BuilderDraggableObject drag = go.FindComponent<BuilderDraggableObject>();
    229.             if(drag == null)
    230.             {
    231.                 ObjUtil.SmartDestroy(go);
    232.                 return;
    233.             }
    234.  
    235.             go.transform.position = drag.Entity.GetAdjustedPosition(targPos);
    236.             _dragAndDropController.StartDrag(drag, (failed) =>
    237.             {
    238.                 if (failed) ObjUtil.SmartDestroy(go);
    239.             });
    240.         }
    241.      
    242.         private void OnButtonActivated(object sender, System.EventArgs e)
    243.         {
    244.             this.InvokeRadical(() =>
    245.             {
    246.                 this.StartAddItem((sender as ButtonActivateEvent).ItemID);
    247.             }, 0.1f);
    248.         }
    249.  
    250.         #endregion
    251.      
    252.         #region Special Types
    253.  
    254.         private class ButtonActivateEvent : MonoBehaviour, IPointerClickHandler
    255.         {
    256.  
    257.             public event System.EventHandler ButtonActivated;
    258.  
    259.             public string ItemID;
    260.  
    261.             void IPointerClickHandler.OnPointerClick(PointerEventData eventData)
    262.             {
    263.                 if (this.ButtonActivated != null) this.ButtonActivated(this, System.EventArgs.Empty);
    264.             }
    265.  
    266.         }
    267.  
    268.         #endregion
    269.  
    270.     }
    271.  
    272. }
    273.  
    You're mostly interested in the 'StartAddItem' and 'OnButtonActivated' methods towards the bottom... the 'OnButtonActivate' being called by the 'ButtonActivateEvent' script that is setup OnEnable and OnDisable.
     
    Last edited: May 12, 2016
  3. Aimlessone

    Aimlessone

    Joined:
    Jun 26, 2015
    Posts:
    46
    Thanks much LordofDuct,

    I'll look into this over the weekend and let you know if I have any further questions.