Forum rules - please read before posting.

Creating a searchable "database"

Hi everyone,

So I think I have an idea of how to do this within unity itself, but I was wondering if there was a way that we could use adventure creator to create a "database" that we can search.

It's kind of similar to the terminals in Gemini Rue and the computer / phone search in the Blackwell series.

Attached a screenshot of what I am trying to do here: https://drive.google.com/file/d/1k-jTkp0PyjTj-4rqYqUkp2-ByAdlvSLN/view?usp=sharing.

I currently have it as a prefab, which I am planning to use as a menu.

So when the player searches something up, there will be a list of matches on the left that pop up, based on specific phrases / keywords the player typed out once they hit enter. I suppose the closest thing it could be likened to is a dictionary, where a key could lead to multiple matches.

The player can then click on any of the matches to get an expanded description of them on the center panel.

Another thing to ask on a side note -- is it possible to reset the scrollbar to the top each time the user presses enter, for both the matches and the center panel? I'm wondering if this is possible for dialogue menus as well, each time the dialogue conversation opens.

Thank you!

Comments

  • Speaking generally: you'd need to rely on a fair bit of custom scripting, but the data itself should be store-able as Inventory items, placed in a separate Category so as to be left out of your regular Inventory menu.

    The list of entries on the left would be an InventoryBox of the type "Custom Script", which you can then populate with your items (reading the contents of an Input box to filter out unwanted entries).

    The expanded description that appears when clicking an entry can be an Inventory String property. Properties can be assigned per-Category, so you could assign such descriptions to these items without affecting your regular Inventory.

    Another thing to ask on a side note -- is it possible to reset the scrollbar to the top each time the user presses enter, for both the matches and the center panel? I'm wondering if this is possible for dialogue menus as well, each time the dialogue conversation opens.

    If you're using Unity's ScrollRect component, you can call its SetNormalizedPosition to reset its view to the top. To run this when a Menu turns on, for example, you can hook into the OnMenuTurnOn custom event:

    using UnityEngine;
    using UnityEngine.UI;
    using AC;
    
    public class ResetScrollRect : MonoBehaviour
    {
    
        public Canvas canvas;
        public ScrollRect scrollRect;
    
        private void OnEnable () { EventManager.OnMenuTurnOn += OnMenuTurnOn; }
        private void OnDisable () { EventManager.OnMenuTurnOn -= OnMenuTurnOn; }
    
        private void OnMenuTurnOn (AC.Menu menu, bool isInstant)
        {
            if (menu.RuntimeCanvas == canvas)
            {
                scrollRect.SetNormalizedPosition (0f, 1);
            }
        }
    
    }
    
  • Thank you so much! I will try this out! :)

  • edited January 2023

    I might not be looking in the right place, but is there a way to grab all the entries within an inventory box? Just working on filtering them, so I was just trying to see how I should go about it in the script :)

    Also just wondering -- but is it possible to remove all items from a specific category?
    I want to clear the matches if the user does not enter a valid search term, but I do not want to clear all the inventory items across all categories.

  • An InventoryBox element merely displays items from a collection - if you want to filter what's in there, you'll need to amend the original collection.

    If you set an InventoryBox element's Inventory box type property to Custom Script, you can then map it to a specific Container by settings its OverrideContainer property:

    MenuInventoryBox inventoryBox = PlayerMenus.GetElementWithName ("Inventory", "InventoryBox") as MenuInventoryBox;
    inventoryBox.OverrideContainer = myContainer;
    

    Where "Inventory" and "InventoryBox" are the names of the Menu / InventoryBox element respectively.

    Once mapped, you can then go and modify items in the Container "myContainer" by accessing its InvCollection:

    myContainer.InvCollection
    

    After making the desired changes to this collection, you can update the InventoryBox's display of that collection by calling the Menu's Recalculate function:

    PlayerMenus.GetMenuWithName ("Inventory").Recalculate ();
    
  • Ah thank you so much!

    It seems like the list is being updated, and the OnStart() function is being called, but the display / list on the panel is not changing. I reassigned the inventoryBox.OverrideContainer = curInventoryList; portion in the ListMatches() function as well just in case, but it did not seem to change anything. Might there be anything I am missing? I have the following:

    I have this OnStart():

    //called before the first frame update
    void Start()
            {
                Debug.Log("IN HERE IN HERE START");
                //grab terminal list and map container to temp invbox add + remove matches
                inventoryBox = PlayerMenus.GetElementWithName("Terminal", "Matches") as MenuInventoryBox;
                curInventoryList = new Container();
                inventoryBox.OverrideContainer = curInventoryList;
                PlayerMenus.GetMenuWithName("Terminal").Recalculate();
    
                //list of search terms and their corresponding results / matches
                searchMatches = new Dictionary<string, string[]>
                {
                    { "Corsivia", new string[] { "Galacia Corsivia" } },
                    { "Cities", new string[] { "Solarvale", "Mecha View"} }
                };
    }
    

    And in the same script, this function is called OnEndEdit():

    public void ListMatches()
        {
            Debug.Log("searchText is" + searchText.text);
    
            // valid search term in database 
            if (searchMatches.ContainsKey(searchText.text))
            {
                Debug.Log("NUM OF RESULTS ARE " + searchMatches[searchText.text].Length);
    
                // populate list with search term matches
                foreach(string i in searchMatches[searchText.text])
                {
                    curInventoryList.InvCollection.Add(new InvInstance(i));
                }
            }
            else{ // no matches
                Debug.Log("NO MATCHES");
                //clear all matches from the list
                curInventoryList.InvCollection.DeleteAll();
            }
    
    
            Debug.Log("ITEMS AFTER UPDATE ARE " + curInventoryList.items);
    
            //Update display with new matches
            inventoryBox.OverrideContainer = curInventoryList;
            PlayerMenus.GetMenuWithName("Terminal").Recalculate();
        }
    

    Thank you so much! :)

  • What exactly is showing in the InventoryBox element?

    Two things I see at this point:

    1. Container is a MonoBehaviour (i.e. component) script. You can't declare a "new Container" - it must be attached to a GameObject, though this too can be generated through script.
    2. You likely want to call DeleteAll at the start of ListMatches regardless of the results, and then repopulate the whole thing from scratch each time.
  • Oh looks like that was it! (the first point)
    I'll see if can move DeleteAll as well -- thank you for your help! :)

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Welcome to the official forum for Adventure Creator.