accessing global variables in a project

Announcements, support questions, and discussion for the Dialogue System.
Post Reply
Smoky
Posts: 9
Joined: Mon Aug 07, 2023 3:26 pm

accessing global variables in a project

Post by Smoky »

Good afternoon I had a question about how to access variables from any part of the game. I have an inventory in the game where you can put items and remove them from it

Code: Select all


namespace UI.InventoryScripts
{
    [System.Serializable]
    public class Item
    {
      //  public int ID { get; set; }
        public string Name { get; set; }
        public int Count { get; set; }
        public string Img { get; set; }
        public string Description { get; set; }
        public bool IsUsed { get; set; }
        // добавить описание, bool значение одет предмет или нет, максимум два кольца и одно ожерелье
    }
}

Code: Select all

namespace UI.InventoryScripts
{
    public class ItemsDB : MonoBehaviour
    {
        public List<Item> _items = new();
    }
}

Code: Select all

using System;
using System.Collections.Generic;
using System.IO;
using TMPro;
using Newtonsoft.Json;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.EventSystems;
using Button = UnityEngine.UI.Button;
using Image = UnityEngine.UI.Image;

namespace UI.InventoryScripts
{
    public class Inventory : MonoBehaviour
    {
        [SerializeField] private ItemsDB _data;

        [SerializeField] private List<ItemInventory> _items = new();

        [SerializeField] private GameObject _gameObjShow;

        [SerializeField] private GameObject _inventoryMainObject;

        [SerializeField] private EventSystem _es;

        [SerializeField] private int _currentID;
        [SerializeField] private ItemInventory _currentItem;
        
        [SerializeField] private GameObject _backGround;

        [SerializeField] private GameObject _selectItemImage;

        [SerializeField] private Button _useButton;
        [SerializeField] private Button _deleteButton;

        [SerializeField] private TextMeshProUGUI _nameOfItem;
        [SerializeField] private TextMeshProUGUI _descriptionOfItem;
        
        public void Start()
        {
            string json = File.ReadAllText(Application.dataPath + "/items.json");
            _data._items = JsonConvert.DeserializeObject<List<Item>>(json);

            ChangeInventory();
            
            UpdateInventory();
        }

        public void Update()
        {
            UpdateInventory();
        }

        private void ChangeInventory()
        {
            if (_items.Count == 0)
            {
                foreach (var t in _data._items)
                {
                    AddGraphics(t);
                }
            }
            
            for (int i = 0; i < _data._items.Count; i++)
            {
                var item = _data._items[i];
                AddItem(i, item);
            }
        }

        private void AddItem(int id, Item item) //добавляет предмет в лист ItemInventory
        {
            Texture2D itemImage = new Texture2D(60,60);
            byte[] imageData = File.ReadAllBytes(Application.dataPath + item.Img);
            itemImage.LoadImage(imageData);
            Sprite sprite = Sprite.Create(itemImage, new Rect(0, 0, itemImage.width, itemImage.height), Vector2.one * 0.5f);
            
//            _items[id]._id = item.ID;
            _items[id]._name = item.Name;
            _items[id]._count = item.Count;
            _items[id]._itemGameObj.GetComponentInChildren<Image>().sprite =  sprite;
            _items[id]._isUsed = item.IsUsed;
            _items[id]._description = item.Description;
        
            if (item.Count > 1)
            {
                _items[id]._itemGameObj.GetComponentInChildren<TextMeshProUGUI>().text = item.Count.ToString();
            }
            else
            {
                _items[id]._itemGameObj.GetComponentInChildren<TextMeshProUGUI>().text = "";
            }
        }

        private void AddGraphics(Item t) //добавляет кнопку предмета в инвентарь
        {
            var newItem = Instantiate(_gameObjShow, _inventoryMainObject.transform);
                
            newItem.name = t.Name;

            var ii = new ItemInventory
            {
                _itemGameObj = newItem
            };

            var rt = newItem.GetComponent<RectTransform>();
            rt.localPosition = new Vector3(0, 0, 0);
            rt.localScale = new Vector3(1, 1, 1);
            newItem.GetComponentInChildren<RectTransform>().localScale = new Vector3(1, 1, 1);

            Button tempButton = newItem.GetComponent<Button>();
            
            tempButton.onClick.AddListener(SelectObject);

            _items.Add(ii);
            
        }

        // ReSharper disable Unity.PerformanceAnalysis
        public void UpdateInventory()
        {
            for (var i = 0; i < _data._items.Count; i++)
            {
                if (_items[i]._count > 1)
                {
                    _items[i]._itemGameObj.GetComponentInChildren<TextMeshProUGUI>().text = _items[i]._count.ToString();
                }
                else
                {
                    _items[i]._itemGameObj.GetComponentInChildren<TextMeshProUGUI>().text = "";
                }

                _items[i]._itemGameObj.transform.GetChild(1).GetComponent<Image>().enabled = _items[i]._isUsed;
            }
        }

        private void SelectObject()
        {
            if (_currentID == -1)
            {
                _currentItem = _items.Find(x => x._name == _es.currentSelectedGameObject.name);
                
                _selectItemImage.GetComponent<Image>().sprite = _currentItem._itemGameObj.GetComponentInChildren<Image>().sprite;
                DescriptionObject(_currentItem);
                
                _deleteButton.onClick.AddListener(DeleteObject);
                
                _useButton.onClick.AddListener(UseObject);
            }
            UpdateInventory();
        }
        
        private void DeleteObject()
        {
            _data._items.Remove(_data._items.Find(x => x.Name == _currentItem._name));
            _items.Remove(_items.Find(x => x._name == _currentItem._name));
            GameObject childObject = _inventoryMainObject.transform.Find(_currentItem._name).gameObject;
            Destroy(childObject);
            UpdateInventory();
        }

        private void UseObject()
        {
            
        }

        // ReSharper disable Unity.PerformanceAnalysis
        public void AddObject(Item itemForAdd)
        {

            if (_data._items.Find(x => x.Name == itemForAdd.Name) != null)
            {
                _data._items.Find(x => x.Name == itemForAdd.Name).Count++;
                _items.Find(x => x._name == itemForAdd.Name)._count++;
            }
            else
            {
                _data._items.Add(itemForAdd);
                //ChangeInventory();
                AddGraphics(itemForAdd);
                Debug.Log(_items.Count);

                AddItem(_items.Count - 1, itemForAdd);
            }
            
            UpdateInventory();
        }

        private void DescriptionObject(ItemInventory currentItem)
        {
            _nameOfItem.text = currentItem._name;
            _descriptionOfItem.text = currentItem._description;
        }

        private void OnApplicationQuit()
        {
            string path = Application.dataPath + "/items.json";
            
            File.WriteAllText(path, JsonConvert.SerializeObject(_data._items));
        }

        
    }
    

    [Serializable]
    public class ItemInventory
    {
        //public int _id;
        public string _name;
        public GameObject _itemGameObj;
        public int _count;
        public bool _isUsed;
        public string _description;
    }
}
The question is how to make the dialogue system always keep track of the number of items in the inventory. For example, I have 2 torches and 1 cloth. The dialog has 2 nodes

1 - always shown
2 - appears if the inventory has 1 torch and 1 rag.

After the dialogue through the 2nd node, we remove items from the inventory
User avatar
Tony Li
Posts: 22102
Joined: Thu Jul 18, 2013 1:27 pm

Re: accessing global variables in a project

Post by Tony Li »

Hi,

First write a C# method that returns the amount of an item that's in the player's inventory. Rough example:

Code: Select all

public class Inventory : MonoBehaviour
{
    ...
    public double GetItemAmount(string itemName)
    {
        var item = _items.Find(x => x.name == itemName);
        return (item != null) ? item._count : 0;
    }
}
Then register it with Lua so you can use it in the dialogue entry's Conditions field.
Smoky
Posts: 9
Joined: Mon Aug 07, 2023 3:26 pm

Re: accessing global variables in a project

Post by Smoky »

At the moment I have 3 variables registered with this code

Code: Select all

 [SerializeField] private double _physicalAbilities = 1; // физические способности
    [SerializeField] private double _perception = 1;        // восприятие
    [SerializeField] private double _intellect  = 0;        // интеллект 
    // private double _physicalAbilitiesDouble;
    // private double _perceptionDouble;
    // private double _intellectDouble;
    //
    // private void Update()
    // {
    //     _physicalAbilitiesDouble = (Int32)_physicalAbilities;
    //     _perceptionDouble = (Int32)_perception;
    //     _intellectDouble = (Int32)_intellect;
    // }

    private void OnEnable()
    {
        // Lua.RegisterFunction("PhysicalAbilities", this, SymbolExtensions.GetMethodInfo(() => _physicalAbilities((int)0)));
        Lua.RegisterFunction("PhysicalAbilities", this, SymbolExtensions.GetMethodInfo(() => GetPhysicalAbilities(1)));
        Lua.RegisterFunction("Perception", this, SymbolExtensions.GetMethodInfo(() => GetPerception(1)));
        Lua.RegisterFunction("Intellect", this, SymbolExtensions.GetMethodInfo(() => GetIntellect(1)));
    }

    private void OnDisable()
    {
        Lua.UnregisterFunction("PhysicalAbilities");
        Lua.UnregisterFunction("Perception");
        Lua.UnregisterFunction("Intellect");
    }

If I have more than 100 variables, will I have to register them all this way, or can lists, sheets, etc. be registered at once?
Attachments
statst.jpg
statst.jpg (36.96 KiB) Viewed 382 times
User avatar
Tony Li
Posts: 22102
Joined: Thu Jul 18, 2013 1:27 pm

Re: accessing global variables in a project

Post by Tony Li »

Hi,

You could register a single C# method that accepts the variable name as a parameter:

Code: Select all

public double GetSkill(string skillName)
{
    switch (skillName)
    {
        case "PhysicalAbilities": return _physicalAbilities;
        case "Perception": return _perception;
        case "Intellect": return _intellect;
        ...
        default: 
            Debug.Log($"GetSkill('{skillName}') is not a valid skill name.");
            return 0;
}

Code: Select all

Lua.RegisterFunction("GetSkill", this, SymbolExtensions.GetMethodInfo(() => GetSkill("")));
Smoky
Posts: 9
Joined: Mon Aug 07, 2023 3:26 pm

Re: accessing global variables in a project

Post by Smoky »

And one more small question. Is there a problem with the scrollbar setting. And it turns out that I create a vertical scrollbar in the prefab and it appears during the dialogue. When scrolling the dialog with the mouse, the slider on the scrollbar changes its position, but it is not possible to grab the slider itself and scroll through the dialog. Maybe I'm doing something wrong.
Attachments
fff.jpg
fff.jpg (87.94 KiB) Viewed 357 times
User avatar
Tony Li
Posts: 22102
Joined: Thu Jul 18, 2013 1:27 pm

Re: accessing global variables in a project

Post by Tony Li »

Hi,

Try assigning the Scroll Content GameObject to the Scrollbar Vertical's Viewport field.
Post Reply