Sprite not changing via script

Hello!

I’m using 2 scripts and one of them it’s responsible to change the SpriteRenderer sprite.
The hierarchy in my game project is:
8953158--1229313--upload_2023-4-16_20-20-2.png

  • The ItemAnimation is the one with the script ItemController, which is responsible to control almost everything related to Items.
  • Item is the one that should have its Sprite being changed
  • Smoke is another GameObject with a SpriteRenderer that have an smoke animation.
  • ItemRandomizer is a GameObject with a script named ItemRandomizer responsible for randomizing the items and delivering all the information regardind the item selected to ItemController (and it works perfectly).

ItemAnimation Inspector:
8953158--1229316--upload_2023-4-16_20-22-38.png

Item Inspector:

Smoke Inspector:

ItemRandomizer inspector:

ItemRandomizer.cs:

using UnityEngine;
using System.Collections.Generic;

[System.Serializable]
public class Item
{
    public string itemName;
    public Sprite itemImage;
    public int itemAttackPoints;
    public int itemLifePoints;
    public int itemProficiencyPoints;
    public int itemExcelencePoints;

    public Item(string name, Sprite image, int attackPoints, int lifePoints, int proficiencyPoints, int excelencePoints)
    {
        this.itemName = name;
        this.itemImage = image;
        this.itemAttackPoints = attackPoints;
        this.itemLifePoints = lifePoints;
        this.itemProficiencyPoints = proficiencyPoints;
        this.itemExcelencePoints = excelencePoints;
    }
}

public class ItemRandomizer : MonoBehaviour
{
    public Sprite[] itemSprites;
    private static List<Item> availableItems = new List<Item>();

    private void Start()
    {
        // adiciona os itens disponíveis na lista
        availableItems.Add(new Item("EntropyBoots", itemSprites[0], 10, 20, 0, 0));
        availableItems.Add(new Item("NightmareMonolyth", itemSprites[1], 0, -40, 5, 2));
        availableItems.Add(new Item("BoneOfTheDead", itemSprites[2], 50, -80, 0, 0));
        availableItems.Add(new Item("HollowLight", itemSprites[3], -10, 50, 2, 0));
        availableItems.Add(new Item("SoulessGem", itemSprites[4], 0, -100, 10, 5));
        availableItems.Add(new Item("DemonHands", itemSprites[5], 20, 50, -1, 0));
        availableItems.Add(new Item("VoidHelmet", itemSprites[6], 100, 0, 15, 10)); // Setar vida para 1
        availableItems.Add(new Item("HeavensHelmet", itemSprites[7], 0, 0, 0, 0)); // Setar vida para valor atual x2 e ataque para metade do valor atual
        availableItems.Add(new Item("OrtraxAmulet", itemSprites[8], 20, 50, 5, 3));
        availableItems.Add(new Item("LifeAmulet", itemSprites[9], -15, 80, 0, 0));
        availableItems.Add(new Item("OrtraxRing", itemSprites[10], 10, 10, 0, 0)); //Se tiver ortrax amulet, dobrar os efeitos do ortrax ring, caso contrário apenas adiciona 10 de ataque e 10 de vida
        availableItems.Add(new Item("CursedScroll", itemSprites[11], -30, -50, 10, 5));
        availableItems.Add(new Item("AncientSkull", itemSprites[12], 10, 50, -2, 0));
        availableItems.Add(new Item("BloodthirstySword", itemSprites[13], 50, -50, 10, 0));
        availableItems.Add(new Item("AngelsChestpiece", itemSprites[14], -10, 100, 0, 4));
    }

    public Item GetRandomItem()
    {
        // escolhe um item aleatório da lista de itens disponíveis
        int index = Random.Range(0, availableItems.Count);
        Item item = availableItems[index];

        // remove o item escolhido da lista de itens disponíveis
        availableItems.RemoveAt(index);

        return item;
    }
}

ItemController script:

using UnityEngine;![8953158--1229313--upload_2023-4-16_20-20-2.png|265x85](upload://sJCaDA7kJmi6Yd93IK0QaUtM6rj.png) ![8953158--1229313--upload_2023-4-16_20-20-2.png|265x85](upload://sJCaDA7kJmi6Yd93IK0QaUtM6rj.png)

public class ItemController : MonoBehaviour
{
    public Animator animator;
    public float amplitude = 0.1f;
    public float speed = 4f;
    private Item itemGameObject;
    private GameObject itemObject;
    private Vector3 originalPosition;
    private SpriteRenderer spriteRenderer;

    private void Start()
    {
        ItemRandomizer itemRandomizer = FindObjectOfType<ItemRandomizer>();
        itemGameObject = itemRandomizer.GetRandomItem();
        itemObject = GameObject.Find("Item");

        spriteRenderer = itemObject.GetComponent<SpriteRenderer>();
        Sprite itemSprite = itemGameObject.itemImage;
        spriteRenderer.sprite = itemSprite;

        originalPosition = itemObject.transform.position;

        animator.Play("Appear");
        Invoke("ActivateItem", animator.GetCurrentAnimatorStateInfo(0).length);
    }

    private void Update()
    {
        if (animator.GetCurrentAnimatorStateInfo(0).IsName("Bouncing"))
        {
            float yPosition = originalPosition.y + amplitude * Mathf.Sin(speed * Time.time);
            itemObject.transform.position = new Vector3(originalPosition.x, yPosition, originalPosition.z);
        }
    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.gameObject.CompareTag("ItemCollider"))
        {
            // Exibe a mensagem de confirmação
            Debug.Log("Deseja pegar o item? Pressione Enter para confirmar.");

            // Aguarda a entrada do jogador
            if (Input.GetKeyDown(KeyCode.Return))
            {
                // Adiciona o item ao inventário
                Inventory inventory = collision.gameObject.GetComponent<Inventory>();
                if (inventory.AddItem(itemGameObject))
                {
                    // Se o item foi adicionado com sucesso, destrói o objeto de item
                    Destroy(gameObject);
                }
            }
        }
    }

    private void ActivateItem()
    {
        animator.Play("Bouncing");

        Debug.Log("Item " + itemGameObject.itemName + " ativado");
        Debug.Log("Vida atual: " + PlayerCharacter.GetCurrentLifePoints());
        Debug.Log("Ataque atual: " + PlayerCharacter.GetCurrentAttackPoints());

        if (itemGameObject.itemName == "VoidHelmet")
        {
            PlayerCharacter.SetLifePoints(1);
            PlayerCharacter.AddAttackPoints(PlayerCharacter.GetCurrentAttackPoints() + itemGameObject.itemAttackPoints);
            PlayerCharacter.AddProficiencyPoints(PlayerCharacter.GetCurrentProficiencyPoints() + itemGameObject.itemProficiencyPoints);
            PlayerCharacter.AddExcelencePoints(PlayerCharacter.GetCurrentExcelencePoints() + itemGameObject.itemExcelencePoints);
        }
        else if (itemGameObject.itemName == "HeavensHelmet")
        {
            PlayerCharacter.SetLifePoints(PlayerCharacter.GetCurrentLifePoints() * 2);
            PlayerCharacter.SetAttackPoints(PlayerCharacter.GetCurrentAttackPoints() / 2);
        }
        // else if (itemGameObject.itemName == "OrtraxRing")
        // {
        //     if (HasOrtraxAmulet())
        //     {
        //         PlayerCharacter.AddAttackPoints(PlayerCharacter.GetCurrentAttackPoints() + itemGameObject.itemAttackPoints*2);
        //         PlayerCharacter.AddLifePoints(PlayerCharacter.GetCurrentLifePoints() + itemGameObject.itemLifePoints*2);
        //     }

        //     else
        //     {
        //         PlayerCharacter.AddAttackPoints(PlayerCharacter.GetCurrentAttackPoints() + itemGameObject.itemAttackPoints);
        //         PlayerCharacter.AddLifePoints(PlayerCharacter.GetCurrentLifePoints() + itemGameObject.itemLifePoints);
        //     }
        // }

        else
        {
            PlayerCharacter.AddLifePoints(PlayerCharacter.GetCurrentLifePoints() + itemGameObject.itemLifePoints);
            PlayerCharacter.AddAttackPoints(PlayerCharacter.GetCurrentAttackPoints() + itemGameObject.itemAttackPoints);
            PlayerCharacter.AddProficiencyPoints(PlayerCharacter.GetCurrentProficiencyPoints() + itemGameObject.itemProficiencyPoints);
            PlayerCharacter.AddExcelencePoints(PlayerCharacter.GetCurrentExcelencePoints() + itemGameObject.itemExcelencePoints);
        }

        Debug.Log("Vida atual: " + PlayerCharacter.GetCurrentLifePoints());
        Debug.Log("Ataque atual: " + PlayerCharacter.GetCurrentAttackPoints());
    }
}

I don’t know what could possibly be the problem. If I manually change the sprite of Item, everything works perfectly. The proble is that the sprite is not being changed by the script. I did debug everything possible, the image is correctly acessed and passed via scripts.

Turn off the animation. Perhaps it is setting the sprite? If it is, check / uncheck the “Write Defaults” option:

Otherwise, maybe your code isn’t even running!

Time to start debugging! Here is how you can begin your exciting new debugging adventures:

You must find a way to get the information you need in order to reason about what the problem is.

Once you understand what the problem is, you may begin to reason about a solution to the problem.

What is often happening in these cases is one of the following:

  • the code you think is executing is not actually executing at all
  • the code is executing far EARLIER or LATER than you think
  • the code is executing far LESS OFTEN than you think
  • the code is executing far MORE OFTEN than you think
  • the code is executing on another GameObject than you think it is
  • you’re getting an error or warning and you haven’t noticed it in the console window

To help gain more insight into your problem, I recommend liberally sprinkling Debug.Log() statements through your code to display information in realtime.

Doing this should help you answer these types of questions:

  • is this code even running? which parts are running? how often does it run? what order does it run in?
  • what are the names of the GameObjects or Components involved?
  • what are the values of the variables involved? Are they initialized? Are the values reasonable?
  • are you meeting ALL the requirements to receive callbacks such as triggers / colliders (review the documentation)

Knowing this information will help you reason about the behavior you are seeing.

You can also supply a second argument to Debug.Log() and when you click the message, it will highlight the object in scene, such as Debug.Log("Problem!",this);

If your problem would benefit from in-scene or in-game visualization, Debug.DrawRay() or Debug.DrawLine() can help you visualize things like rays (used in raycasting) or distances.

You can also call Debug.Break() to pause the Editor when certain interesting pieces of code run, and then study the scene manually, looking for all the parts, where they are, what scripts are on them, etc.

You can also call GameObject.CreatePrimitive() to emplace debug-marker-ish objects in the scene at runtime.

You could also just display various important quantities in UI Text elements to watch them change as you play the game.

Visit Google for how to see console output from builds. If you are running a mobile device you can also view the console output. Google for how on your particular mobile target, such as this answer or iOS: How To - Capturing Device Logs on iOS or this answer for Android: How To - Capturing Device Logs on Android

If you are working in VR, it might be useful to make your on onscreen log output, or integrate one from the asset store, so you can see what is happening as you operate your software.

Another useful approach is to temporarily strip out everything besides what is necessary to prove your issue. This can simplify and isolate compounding effects of other items in your scene or prefab.

Here’s an example of putting in a laser-focused Debug.Log() and how that can save you a TON of time wallowing around speculating what might be going wrong:

“When in doubt, print it out!™” - Kurt Dekker (and many others)

Note: the print() function is an alias for Debug.Log() provided by the MonoBehaviour class.

Hey! Thanks for the reply!

I did run a lot of Debugs in the code and it is indeed running. The debugs shows that the right sprite is being acessed by the ItemController. It shows that it accessing the right GameObject and the right SpriteRenderer.

The strangest part is that when I run Debug.Log to see if the SpriteRenderer.sprite starts with Null (it should start like that), it does. However, if the image is not rendering or showing, the result should still be null after the code, right? Although, when I run Debug.Log after the sprite change line of code, it says that the sprite was loaded and is NOT nulln anymore.

I’ll try to build the game and run because it could be a bug of some kind.

Thanks again for the reply!

your post is too long for me to read

however i just want to inform you that if you have an animator on the same object as a spriterenderer, the animator completely hijacks it and you can never change it, its controlled by the animator

i could elaborate further but this might not be relevant to you

Bro, THANK YOU SO MUCH. I’d never know that I couldn’t have the animator and the SpriteRenderer in the same object. For real, you saved my life.

1 Like