How to change sprite image from script?

How can I change the sprite image from script? In the editor I have setup a texture with multiple frames (fruits_0, fruits_1 … etc.) then I have assigned (fruits_0) to a game object named fruit. Now I want to be able to change fruit’s image to display frame (fruits_1) instead of (fruits_0), how to do that in script?

Thanks.

2 Likes

Create a reference variable for each sprite you want to use in code. You can then assig these references to the sprite property of the sprite renderer of your game object.

3 Likes

This should help. :slight_smile:
http://forum.unity3d.com/threads/211817-Changing-sprite-during-run-time

3 Likes

@unitylover: thanks, but bear with me for a moment, why can’t I just assign it directly, why do I need a reference? when I want to change the position, I just assign a new x,y,z coordinates to the object:
transform.position = new Vector3(0f, 0f, 0f);

I mean why can’t I use this: SpriteRenderer.Sprite=new Sprite(fruits_1);

If you are not using a reference how is the code going to know where the image you want to use as the sprite is?

You would have to load the image first with Resources.Load. Something like:

Sprite myFruit = Resources.Load("fruits_1", typeof(Sprite)) as Sprite;
12 Likes

Don’t put sprites in Resources; they can’t be auto-atlased if you do that. Just use public references.

var spriteImage : Sprite;

function Start () {
    GetComponent(SpriteRenderer).sprite = spriteImage;
}

–Eric

3 Likes

Thanks everybody, the solution I’m seeking is posted here.

Is there any other way to do that? I have about 40 sprites in tileset, and I need to assign a sprite to rendered basing on random seed in script parameters. Is there a way to do that using only name/index of sprite in particular sprite sheet?

I have been looking all over to find exactly this piece of information. Hopefully someone will come around and provide an answer. I have to think that there is a way to reference an individual sprite from a texture of type sprite-multiple

For lack of having a method to directly access individual sprites created by Unity, I found the following workaround to get the job done. This requires that the individual sprites in the texture are in a grid. Basically, instead of having Unity build the individual sprite frames, you build them yourself.

Add the sprite texture to your project as normal, with Type: “Sprite” and Sprite Mode “Single” (will not work if set to Multiple). I also have the Pixels to Units set to 1, which is consistent with the way I have my project setup. I then have the following class to build and allow access to the individual sprite frames:

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

public class MapDisplay : BaseBehavior 
{

    public Texture2D TilesTexture;

    List<Sprite> _tileFrames;

    private float TILE_UNIT_WIDTH = 48f;
    private float TILE_UNIT_HEIGHT = 48f;

    private int NUM_FRAMES_X = 8;
    private int NUM_FRAMES_Y = 5;

	// Use this for initialization
	void Awake () {
        SetupSpriteFrames();
	}
	
	// Update is called once per frame
	void Update () {
	
	}

    public Sprite GetSpriteFrame(int tx, int ty)
    {
        return (tx >= 0  tx < NUM_FRAMES_X  ty >= 0  ty < NUM_FRAMES_Y) ? _tileFrames[ty * NUM_FRAMES_X + tx] : _tileFrames[0];
    }

    private void SetupSpriteFrames()
    {
        _tileFrames = new List<Sprite>();
        
        Vector2 pv = new Vector2(0f, 0f);

        for (int j = 0; j < NUM_FRAMES_Y; j++)
        {
            for (int i = 0; i < NUM_FRAMES_X; i++)
            {
                Rect loc = new Rect(i * TILE_UNIT_WIDTH, (NUM_FRAMES_Y - (j+1)) * TILE_UNIT_HEIGHT, TILE_UNIT_WIDTH, TILE_UNIT_HEIGHT);
                Sprite s = Sprite.Create(TilesTexture, loc, pv, 1f);
                
                _tileFrames.Add(s);
            }
        }
    }



}

Note: BaseBehavior, in addition to being mis-spelled, is just a wrapper around MonoBehaviour, and my tile size in pixels is 48x48.
Once you attach this script to a GameObject, drag the texture you imported into the TilesTexture property and you should be good to go.

Here is an example of how the class is then used, where the individual frame is identified by its x and y coordinates within the texture image starting at the top left:

public void SetTileGraphic(MapTerrain mt, MapDisplay parentMap)
    {
        // get reference to sprite renderer
        SpriteRenderer sr = this.transform.FindChild("MapTileSprite").gameObject.GetComponent<SpriteRenderer>();

        switch (mt.TerrainType)
        {
            case MapTerrain.TERRAIN_FOREST:
                sr.sprite = parentMap.GetSpriteFrame(1, 0);
                break;
            case MapTerrain.TERRAIN_HILLS:
                sr.sprite = parentMap.GetSpriteFrame(2, 0);
                break;
            case MapTerrain.TERRAIN_WATER:
                sr.sprite = parentMap.GetSpriteFrame(3, 0);
                break;
            case MapTerrain.TERRAIN_PLAINS::
                sr.sprite = parentMap.GetSpriteFrame(0, 0);
                break;
        }
    }

Still hoping there is a way to reference Sprites created in the editor via code, either which I do not know about, or in a future release.

2 Likes

@Checkmark Without using sprite sheet, the draw call count is increased significantly, right?

@musiko I think you have it right. Building sprite frames like this is likely going to cost you, but I have not dug into the rendering code.

This is one of the reasons I ended up purchasing 2DToolkit, which has worked out very well and is providing the solution I needed. I hope that the Unity team adds a way to access individual sprite frames in a Multi-Sprite texture in a future release.

1 Like

What image format do you use as the sprite image? gif, png, jpeg or tiff?

Hello there,

I got your script working but I can’t do it with other sprite, just the one that I got my script in. How can I define which Sprite I want to change?

I made a little script to make this really easy:

To use it you just do:

Javascript

var sprites : SpriteCollection;

function Start()
{
    sprites = new SpriteCollection("Spritesheet"); // Spritesheet = path + name of sprite in Resources folder

    GetComponent("SpriteRenderer").sprite = sprites.GetSprite("Sprite1"); //name of specific sprite in spritesheet
}

C#

SpriteCollection sprites;

function Start()
{
    sprites = new SpriteCollection("Spritesheet");

    GetComponent<SpriteRenderer>().sprite = sprites.GetSprite("Sprite1");
}

1571790–93149–$SpriteCollection.js (446 Bytes)
1571790–93150–$SpriteCollection.cs (459 Bytes)

2 Likes

Cheers dude, thanks for the help :smile:

But that wasn’t what I wanted. I have the script running on my character so when it collides whit some objects the background image changes. My problem it’s instead of changing the background I’m changing the character because I put the script in the character. My problem it’s how can I swap the new sprite with the background instead of the character?

Then instead of doing:

GetComponent("SpriteRenderer").sprite = sprites.GetSprite("Sprite1");

You should do:

GameObject.Find("nameOfBackgroundGameObject").GetComponent("SpriteRenderer").sprite = sprites.GetSprite("Sprite1");

I need also to change the image in runtime, I have this code:

    GameObject background;
    background = new GameObject("background");
    background.AddComponent("SpriteRenderer");
    background.GetComponent<SpriteRenderer>().sprite = Resources.Load<Sprite>("background");

But then how I change the size of background?

1 Like

well i using this to change my sprite in runtime

    public Sprite[] sprites;
    private SpriteRenderer spriteRenderer;

    public int index = 0;

    // Use this for initialization
    void Start () {
        spriteRenderer = renderer as SpriteRenderer;
    }
  
    // Update is called once per frame
    void Update () {
        spriteRenderer.sprite = sprites[index];
    }

so that is the basic and you just need to tweak the index number to showing the sprite you want
and if you want to achieve spriteanimation like looping all your sprite to showing animation then just
tweak it into this

    public Sprite[] sprites;
    public float framesPerSecond;
    private SpriteRenderer spriteRenderer;

    // Use this for initialization
    void Start () {
        spriteRenderer = renderer as SpriteRenderer;
    }
  
    // Update is called once per frame
    void Update () {
        int index = (int)(Time.timeSinceLevelLoad * framesPerSecond);
        index = index % sprites.Length;
        spriteRenderer.sprite = sprites[index];
    }
1 Like

Check this out might be this link will help you out - → [云顶777070-云顶777070【官网】

](云顶777070-云顶777070【官网】)
You also can check out the full video tutorial on Photoshop - - > http://www.brotsky.tv/2013/09/22/how-to-make-an-image-sprite/