2D - Change sprite depending on what block is selected.

I have a canvas displaying what block you have selected via Text however I want to ad the image of the block also… so if I have “Moonrock” chosen I want the “Moonrock” block sprite to show beneath the text… so on and so forth.

Help would be appreciated!

  • I HAVE MARKED WHAT I HAVE ATTEMPTED WITH AN “<-------------” -
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class inventory : MonoBehaviour {

    public Text InventoryText;
    public Text selectionText;
    public Sprite selectedItem; <-----------

    int[] counts = new int[8];

    int selectedTile;

    string[] names = new string[] {"MOONROCK", "MUD", "MOONSTONE", "COPPER", "SILVER", "GOLD", "GLASS", "MOONSAND"};

    public GameObject[] tiles = new GameObject[8];


    void Update ()
    {
        selectionText.text = "SELECTED: " + names [selectedTile];

        selectedItem.texture = GameObject.Find ("selected_item").GetComponent<Sprite> ().texture as Sprite; <-------------

        InventoryText.text = "MOONROCK: " + counts [0] + "\nMUD: " + counts [1] + "\nMOONSTONE: " + counts [2] + "\nCOPPER: " + counts [3] + "\nSILVER: " + counts [4] + "\nGOLD: " + counts [5] + "\nGLASS: " + counts [6] + "\nMOONSAND: " + counts [7];



        if(selectionText.text = ("MOONROCK"))
        {
            selectedItem.texture = new Sprite("moonrock"); <------------
        }



        if(selectedTile < 0)
        {
            selectedTile = counts.Length - 1;
        }

        if(selectedTile > counts.Length - 1)
        {
            selectedTile = 0;
        }

        if(Input.GetKeyDown(KeyCode.UpArrow)) //Scroll up
        {
            selectedTile ++;
        }

        if(Input.GetKeyDown(KeyCode.DownArrow)) //Scroll up
        {
            selectedTile --;
        }

        //Place blocks
        if (Input.GetMouseButtonDown (1))
        {
            if(counts [selectedTile] > 0)
            {
                Vector3 mousePos = Camera.main.ScreenToWorldPoint (Input.mousePosition);

                Vector3 placePos = new Vector3 (Mathf.Round (mousePos.x), Mathf.Round (mousePos.y), 0f);

                if (Physics2D.OverlapCircleAll (placePos, 0.25f).Length == 0)
                {
                    GameObject newTile = Instantiate (tiles [selectedTile], placePos, Quaternion.identity) as GameObject;
                    counts [selectedTile]--;
                }
            }
        }

        if (selectedTile == 0)
        {
            if (Input.GetKeyDown (KeyCode.C))
            {
                if(counts[7] >= 2)
                {
                    counts [6]++;
                    counts [7] -= 2;
                }
            }
        }
    }

    public void Add (int tileType, int count)
    {
        counts [tileType] += count;
    }
}

Dean

For a Canvas UI element you’ll want to use the Image component to display your sprites.

You actually have a bunch of data using the same indexing system, so you can easily change this to be more object-oriented by creating a class to hold one “item” of data.

I took your code, added that class, and then consolidated your arrays to use that class instead. Hopefully you can see the benefits of doing things in this way. I can’t promise this will work straight away, because I haven’t tested this.

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class inventory : MonoBehaviour {

    // a class of data representing one item
    [Serializable] public class Item {
        public string name;
        public GameObject prefab;
        public Sprite previewSprite;
        public int Count;
    }

    public List<Item> items; // setup in the inspector

    // component references
    public Text InventoryText;
    public Text selectionText;
    public Image previewImage;

    Item selectedItem;
    int selectedIndex;

    void Update() {
        if(selectedIndex < 0) {
            selectedIndex = items.Count - 1;
        }

        if(selectedIndex > items.Count - 1) {
            selectedIndex = 0;
        }

        if(Input.GetKeyDown(KeyCode.UpArrow)) //Scroll up
        {
            selectedIndex++;
        }

        if(Input.GetKeyDown(KeyCode.DownArrow)) //Scroll up
        {
            selectedIndex--;
        }

        //Place blocks
        if(Input.GetMouseButtonDown(1)) {
            if(items[selectedIndex].Count > 0) {
                Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);

                Vector3 placePos = new Vector3(Mathf.Round(mousePos.x), Mathf.Round(mousePos.y), 0f);

                if(Physics2D.OverlapCircleAll(placePos, 0.25f).Length == 0) {
                    GameObject newTile = Instantiate(items[selectedIndex].prefab, placePos, Quaternion.identity) as GameObject;
                    items[selectedIndex].Count--;
                }
            }
        }

        if(selectedIndex == 0) {
            if(Input.GetKeyDown(KeyCode.C)) {
                if(items[7].Count >= 2) {
                    Add(6, 1);
                    Add(7, -2);
                }
            }
        }

        SetSelectedItem(items[selectedIndex]);
    }

    public void Add(int tileType, int count) {
        items[tileType].Count += count;
    }

    private void SetSelectedItem(Item newSelection) {
        if(selectedItem != newSelection) {
            selectedItem = newSelection;
            selectionText.text = "SELECTED: " + selectedItem.name;

            UpdateInventoryText();
        }
    }

    private void UpdateInventoryText() {
        // make an array of all the item names
        string[] itemNames = new string[items.Count];
        for(int i = 0; i < itemNames.Length; i++) {
            Item item = items[i];
            // format the display string
            itemNames[i] = string.Format("{0}: {1}", item.name, item.Count);
        }
        // join the array with new lines
        InventoryText.text = string.Join("\n", itemNames);
    }
}

The key function call to update your preview stuff is “SetSelectedItem(items[selectedIndex])” at the bottom of the Update. That could go earlier in the update if your spawning code needs it. I didn’t clean that part up, just the data management parts. Try to get in the habit of making functions to do the work, it makes your code easier to read and debug.

Hope this helps you moving forward.

2 Likes

Hi jeffreyschoch,

Thanks for the help, I can see how organized and easily set up it is now… thank you! Just another quick one, the preview image isnt set up, what would be the best way to go about it in your opinion?

Thanks again and thank you in advance xD

  • Dean

Hey Dean,

I assume you have a Canvas object, where you display your SelectionText, correct? You could add a new Image object as a child of that Canvas, to go along with the changing text. Just right click on your Canvas object in the hierarchy and go to UI->Image. You can assign a sprite to setup how it will look, and then drag that Image component to the script so it can change the sprite at runtime.

Hey jeffreyschoch,

Thanks for replying, I had already set and image up and dragged it into the variable and ran the game with your version of the script and when i used the up and bottom arrows, it didnt changed the image to that block it stayed white as default.

Thanks,

Dean

Ah yes, my mistake I forgot to include the code that actually sets that sprite on the image component.

Inside the “SetSelectedItem” function, you can add a line with “previewImage.sprite = selectedItem.previewSprite;” after the selectedItem is set to the new one.

It works!

Thanks a lot! If you dont mind could I add you on Discord or something similar for future help? I wont spam haha.
Anyways thanks again, it looks awesome now!

Dean

I won’t always be available, and I won’t always have the best answer, so your best bet is to continue to ask your questions here on the forums and in the Unity answer hub. There’s a lot of smart people here. If you really need some help and can’t find it elsewhere, you can direct message me but I can’t promise I’ll be able to help you in a timely manner.

Thats no problem, thanks again for the help! :slight_smile: