I have been searching in this forum on how to change a sprite image during runtime but could not find a complete answer to address this issue. Can someone just post a short (but complete) c# code that would show us how to do this simple task giving that a certain sprite was created in the editor named “fruits” and was sliced to be “fruits_0, fruits_1 …etc.” also an object was created in the editor named “fruitObject”, what code should I use to assign different frames to “fruitObject”? And please don’t tell me to use prefabs because I have a lot of frames and it seems it’s not the right way to do this using them.
There does not seem to be an API reference to a sprite sheet, UnityEngine.Sprite only gives parameters of a single sprite within a sheet. Maybe you could make an animation that has one frame per sprite and sample from it?
I’m pretty sure the API doesn’t support that. I posted a question on Answers and someone offered a decent alternative. I think the “proper” way to do sprite animations is the process shown by Max in this video.
Finally I have figured it out, here is how I have accomplished it:
1- First, I created a Resources folder inside my assets folder and put my texture “fruits.png” inside it.
2- In the Project pane I clicked on the fruits assets that I have created in step (1) then in the inspector I changed the Sprite Mode from Single to Multiple, using the sprite editor I created my sprite sheet with 60 frames “fruits_0, fruits_1 … fruits_59”.
3- Now it’s time for the code
public Sprite[] fruitSprites;
void Awake()
{
// load all frames in fruitsSprites array
fruitSprites = Resources.LoadAll<Sprite>("fruits");
}
void Start ()
{
// create the object
GameObject fruit = new GameObject();
// add a "SpriteRenderer" component to the newly created object
fruit.AddComponent<SpriteRenderer>();
// assign "fruit_9" sprite to it
fruit.GetComponent<SpriteRenderer>().sprite = fruitSprites[9];
// to assign the 5th frame
fruit.GetComponent<SpriteRenderer>().sprite = fruitSprites[5];
}
So basically we just loaded our sprites into an array of sprites and used them as a reference.
It took me some time to figure it out because someone in a another post has stated that sprites cannot be auto-atlased when put in Resources folder, that statement has discouraged me from using the Resources.LoadAll for a while until I decided to try it.
Interesting. I did this without knowing about “Resources”, which may have been much easier. But I did.
public Sprite[] sprites;
In the script on my sprite.
I then set the created Size property in the inspector to 13 for the 13 different images I needed (this number could be whatever for anyone else), and clicked and dragged each individual image I wanted to change, into elements 0-12 in the inspector.
I would really like to know how to do this on spite atlas loaded at runtime via web call? Suppose I load a sprite sheet / atlas in runtime and I like to show all the images that are in that atlas and perform mouse click / touch event on all of them.
Also what if the sprite sheet that is loaded at runtime having different sized images (not fixed size sheet) ? Where to store the information of x/y/width/height ? Like we used to do in a XML file in actionscript3/flash or cocos2d.
Trying to solve a similar problem, thot I’d post an alternative solution in case people are interested. Check out the solution breakdown on my site. Code below. Cheers!
// new stuff
using System.Linq;
using System;
using UnityEditor;
// standard
using UnityEngine;
using System.Collections;
public class SkinController : MonoBehaviour {
// drop all the "skins" you want to be swappable here, these are the multi-sprite textures in your Assets
public Texture2D[] skins;
// the skin you want to use, you could add a public accessor so this can be changed at runtime.
public int activeSkin;
// Use this for initialization
void Awake ()
{
// default loaded sprites
SpriteRenderer[] loadedRenderers = GetComponentsInChildren <SpriteRenderer>(true);
// sprites we want
Sprite[] sprites = AssetDatabase.LoadAllAssetRepresentationsAtPath("Assets/Sprites/" + skins[activeSkin].name + ".png").OfType<Sprite>().ToArray();
for (int i = 0; i < sprites.Length; i++)
{
replaceMatchingSprite (loadedRenderers, sprites[i]);
}
}
void replaceMatchingSprite (SpriteRenderer[] loaded, Sprite newSprite)
{
for (int i = 0; i < loaded.Length; i++)
{
try
{
if (loaded[i].sprite.rect.x == newSprite.rect.x loaded[i].sprite.rect.y == newSprite.rect.y)
{
// we found a match, replaced loaded with new, we can have multiple matches
loaded[i].sprite = newSprite;
}
}
catch (Exception e)
{
// do nothing, we seem to get a few null values when looking through the loaded sprites, but seems we can safely ignore them :).
}
}
}
}
Which of those method are best for memory optimazation ?
I am thinking changing the state of a static object for example from deactivated to activate,
by only changing the Sprite Renderer “sprite” would save memory than adding an animation.
Just getting back from a major hard drive failure otherwise I would have replied to this sooner.
I came across this method which I’ve found really helpful on the game (my first) I’m currently making. It allows you to replace a sprite sheet on a prefabbed model, effectively allowing you to skin and reuse one model for a variety of character.
There’s probably a better way of doing it (I’m a three month beginner) but I made a video about my walk cycle a few weeks ago but it has the skinning in there if anybody is interested in seeing the results.
This is the code I’m using. Not sure it’s the most efficient but it seems to do the job.
Texture2D sprite_sheet = Resources.Load<Texture2D> ("Character" + character_skin.ToString ());
Component[] parts;
parts = gameObject.GetComponentsInChildren<SpriteRenderer> ();
foreach (SpriteRenderer sr in parts) {
MaterialPropertyBlock myblock = new MaterialPropertyBlock ();
myblock.AddTexture ("_MainTex", sprite_sheet);
sr.SetPropertyBlock (myblock);
}
}
Im facing a problem I have sprite in scene. When i load a sprite from resources its exactly the same as the one in the scene. But when i Load it from AssetBundle the bounds of the sprite change and if i do ti like
Sprite.Create(tex, sprite.rect, new Vector2(0.5f,0.5f), 80);
Hey Guys,
I was really happy to find the code “amjadyahya” posted. I tried to use it for a code in my project (to create a SpriteFont) but It’s not working…
public var font : Sprite[];
function Awake(){
// the File is a PNG in "Assets/Resources/Font/SpriteFont.png" sliced into 101 pieces
font = Resources.LoadAll("Font/SpriteFont", Sprite) as Sprite[];
if (font != null){
Char = new GameObject();
Char.AddComponent(SpriteRenderer);
Char.GetComponent(SpriteRenderer).sprite = font[0];
Char.transform.position.Set(0,0,0);
}
else {
Debug.LogWarning("Loaded no SpriteSheet for Font."); // it always ends up here
}
}
I was really jazzed when I came across this thread, but when I went to implement it, it didn’t work.
Although as a slight difference, I’m using these as textures to display on my game’s HUD. I’ve drawn a lot of textures on the screen before, but I’d love to be able to use “multiple sprites” instead of having a separate file for each individual graphic I want to display; especially for oddly-sized graphics and boxes that get divided into pieces.
That last function is one I made to keep everything the right size on all resolutions and aspect ratios. The first item it requires is a texture. When I run this code, it stops on that line giving me the error: “IndexOutOfRangeException: Array index is out of range.” so it feels like the array doesn’t include a “1” index.
I never got any errors from telling it to load those textures though, so it looks like it loaded right. And I double checked the spelling of the path. I do not see why this did not work.