Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Voting for the Unity Awards are OPEN! We’re looking to celebrate creators across games, industry, film, and many more categories. Cast your vote now for all categories
    Dismiss Notice
  3. Dismiss Notice

Any idea why this SpriteRenderer only works once?

Discussion in 'General Graphics' started by KrakenUpJP, May 10, 2018.

  1. KrakenUpJP

    KrakenUpJP

    Joined:
    Apr 22, 2018
    Posts:
    9
    Hello Unity Forums,

    Been working on making a goofy little clicker game with a friend of mine. I have a method written to change the sprite from a resting state (sprite1) to a hit state (sprite2). I'm calling it from my GameManager class. I can get the Debug.Log to print for every time changeSprite is called, but the sprite only actually changes the first time. Any ideas?

    Thanks.

    Code (CSharp):
    1. public static void changeSprite()
    2.     {
    3.         Sprite testsprite1 = Resources.Load<Sprite>("sprite1");
    4.         Sprite testsprite2 = Resources.Load<Sprite>("sprite2");
    5.  
    6.         if (spriteRenderer.sprite != testsprite2)
    7.         {
    8.             Debug.Log("I tried");
    9.             spriteRenderer.sprite = testsprite2;
    10.         }
    11.     }
     
    Last edited: May 21, 2018
  2. aleksandrk

    aleksandrk

    Unity Technologies

    Joined:
    Jul 3, 2017
    Posts:
    2,836
    Hi!
    Each time you load a sprite like this, you get a new object of type Sprite, which is not equal to the previously loaded one, and then assign it to the renderer.
    The sprite itself, however, is always "sprite2", and that's the one being displayed.
     
    KrakenUpJP likes this.
  3. KrakenUpJP

    KrakenUpJP

    Joined:
    Apr 22, 2018
    Posts:
    9
    I apologize my friend, I have been reading and re-reading your post for the last few hours, trying different things with my code, and I still cannot get this to resolve.

    I have a code to change this sprite (attached to the sprite) when it's clicked, as follows:
    Code (CSharp):
    1. void Hit() // sprite was poked
    2.     {
    3.         changeSprite();
    4.     }
    which calls changeSprite

    Code (CSharp):
    1.  
    2. public static void changeSprite()
    3.     {
    4.         Sprite testsprite1 = Resources.Load<Sprite>("sprite1");
    5.         Sprite testsprite2 = Resources.Load<Sprite>("sprite2");
    6.  
    7.         if (spriteRenderer.sprite != testsprite2)
    8.         {
    9.             spriteRenderer.sprite = testsprite2;
    10.         }
    11.     }
    This code works perfectly fine each time, with the desire result of the sprite flipping when this script is assigned to the sprite. It's worth mentioning I have code elsewhere to flip the sprite back to testsprite1 which is rigged to an invokeRepeating to always flip it back to testsprite 1 every half a second.

    Code (CSharp):
    1.  
    2. void Start()
    3.     {
    4.         InvokeRepeating("Rest", 0.5f, 0.5f); // invoke repeating calls a method and repeats it every X seconds
    5. }
    6. void Rest() // change sprite back to resting state
    7.     {
    8.         if (spriteRenderer)
    9.         {
    10.             if (spriteRenderer.sprite != sprite1) // if the spriteRenderer sprite = sprite1 then change to sprite2
    11.             {
    12.                 spriteRenderer.sprite = sprite1;
    13.             }
    14.         }
    15.     }
    In my game manager code, I have this snippet set to unlock where the sprite will change once a second, which is not evaluating properly:

    Code (CSharp):
    1. void UpdateEverySecond()
    2.     {
    3.         hitSprite.changeSprite();
    4.     }
    5. }
    I have other code inside the UpdateEverySecond function that performs correctly, updating the score as the variable dictates. The only thing not working is the dang sprite only changes the first go around. If you could explain it any further, it would be greatly appreciated. Thanks.
     
    Last edited: May 21, 2018
  4. KrakenUpJP

    KrakenUpJP

    Joined:
    Apr 22, 2018
    Posts:
    9
    Please if anyone could give me some ideas how to handle this stubborn bug it would be a huge help. Thanks.
     
  5. bobisgod234

    bobisgod234

    Joined:
    Nov 15, 2016
    Posts:
    1,042
    Load your sprite once, in Awake(), and assign it to a class variable called "testsprite1" and "testsprite2", do this instead of loading new sprites each time changeSprite is called.

    See if that makes a difference.

    Also you can insert code into your post with the little paper icon with the <> symbols on it. It makes it much easier to read.
     
    KrakenUpJP likes this.
  6. KrakenUpJP

    KrakenUpJP

    Joined:
    Apr 22, 2018
    Posts:
    9
    Thanks for the idea. I will try that later tonight and update. Also thanks for the tip on inserting code, missed that button when posting.
     
  7. AkiraWong89

    AkiraWong89

    Joined:
    Oct 30, 2015
    Posts:
    662
    @KrakenUpJP I suggest...
    Make public variables and store references on inspector.
    Code (CSharp):
    1. public Sprite spriteA;
    2. public Sprite spriteB;
    Then make a more generic function...
    Code (CSharp):
    1. public void ChangeSprite (GameObject _target, Sprite _sprite)
    2. {
    3.     _target.GetComponent<Image>().sprite = _sprite;
    4. }
    When you want to change sprite, just use this one general function all over your project.

    I see "public static" in your code. Try to avoid using that as much as you can.
    It's convenience but also a chaos when your project getting bigger. Plus, it's insecure.
     
    KrakenUpJP likes this.
  8. KrakenUpJP

    KrakenUpJP

    Joined:
    Apr 22, 2018
    Posts:
    9
    Thank you for the ideas. I will try that when I get home here in a bit. Out of curiosity, how would I call this function from my gameManager script without a public static declaration? Also, can you explain a bit more about the reason to avoid public static? I have several global variables I need to access from multiple scripts and public static is the only way I currently know how to give them that kind of reach. Sorry if this is totally idiotic, I'm new to object oriented coding.
     
  9. AkiraWong89

    AkiraWong89

    Joined:
    Oct 30, 2015
    Posts:
    662
    You can use Singleton to do that. Please have a look on the link below:
    http://wiki.unity3d.com/index.php/Singleton
    http://wiki.unity3d.com/index.php/Toolbox

    There's some other different ways to implement Singleton too.
    You can search on YouTube. There's a lots of nice examples there. Like this one:


    I personally like to use GameObject group based while some people like Type based Singeton.
    Just depend on your flow. Nothing right or wrong.

    Public static methods can be accessed everywhere. It's convenience but also chaos because you will get a super long list of auto completion once your project is getting bigger which make you and team confuse sometimes. You can use them, just use less.

    It's insecure because it's very easy to get hacked due to its global exposure level, said by my friends who have about 7 years on C# programming experience. Usually we will hide our database by using private field, delegate functions and so on.

    You can take a look at this thread too:
    https://forum.unity.com/threads/why-is-static-considered-bad-practice.200363

    Just ask anything. It's fine. It's a common learning progress.
    I'm not a coding expert too and also not 100% understanding OOP concept.
    I just self-taught C# on free time since 3 years ago. I'm actually a 3D artist.
    Just never stop learning what you passion about.;)
     
    Last edited: May 23, 2018
  10. KrakenUpJP

    KrakenUpJP

    Joined:
    Apr 22, 2018
    Posts:
    9
    Thank you for your help Akira. I've learned plenty about when to use public static variables, and about singletons. However, my issue still remains. I can't find a reliable way to call the changeSprite() function from another class. I want to change the sprite the exact same way I change it when I do a normal click, but from the script instead. I feel like this is something simple I'm overlooking.