- Home /
The question is answered, right answer was accepted
I'm trying to load a sprite from StreamingAssets. At the end of the import method, the sprite is null again. Why?
I'm trying to add support for mods in my game. The mods should have icons that I can display in some fancy list for the player. Therefore I need to import a single sprite for each mod. But there's the problem. I just can't.
The mods are organized in a list of structs, like this:
public List<Mod> Mods { get; private set; }
And they're loaded on awake. Their content is pretty simple. A name:
public string Name { get; private set;}
And an icon.
public Sprite Icon { get; private set; }
The issue lies with the Icon thingy. I just can't manage to find out what is happening. The mods are being loaded from the Streaming Assets folder. Any help is appreciated.
Info that may help:
The Icon gets successfully assigned during the loading process and is re-setted right after it for some reason.
There are no scripts interfering with the loading, this script has been tested in a mostly empty scene, holding only dependencies.
Mystery...
The loading code:
public static IEnumerator ImportSprite (string spritePath, Sprite _sprite, FilterMode filterMode, Vector2 pivot)
{
string finalPath;
WWW localFile;
Texture texture;
Sprite sprite;
finalPath = "file://" + spritePath;
localFile = new WWW(finalPath);
yield return localFile;
texture = localFile.texture;
_sprite = Sprite.Create(texture as Texture2D, new Rect(0, 0, texture.width, texture.height), pivot);
_sprite.texture.filterMode = filterMode;
//_sprite = sprite;
}
Hey. You asked me where to put the action. Please change you coroutine like this :
public static IEnumerator ImportSprite (string spritePath, Action<Sprite> onFinished, Filter$$anonymous$$ode filter$$anonymous$$ode, Vector2 pivot)
{
string finalPath;
WWW localFile;
Texture texture;
Sprite sprite;
finalPath = "file://" + spritePath;
localFile = new WWW(finalPath);
yield return localFile;
texture = localFile.texture;
sprite= Sprite.Create(texture as Texture2D, new Rect(0, 0, texture.width, texture.height), pivot);
sprite.texture.filter$$anonymous$$ode = filter$$anonymous$$ode;
onFinished.invoke(sprite);
}
and add this method to the class you want to grab the value like this :
StartCoroutine(ImportSprite("a path to sprite", (text) =>
{
// Here, text is the returned sprite from the invoke line
// So here you can save the sprite to your struct or wherever you want
}, Filter$$anonymous$$ode, AVector2));
Remember that you dont have to use a lambda expression if you dont want. You can create a function and parse it ins$$anonymous$$d of the lambda like so :
public void onFinishe (Sprite sp)
{
// The sp is the sprite that will be returned
....
So you can now call it like that :
StartCoroutine(ImportSprite("a path to sprite", onFinishe, Filter$$anonymous$$ode, AVector2));
OnFinishe will be called when coroutine gets to line that invokes this method.
Just one more thing. You can make parameters with actions optional by setting
Action<Sprite> onFinished = null
Remember that optional parameters are put to the end of the parameters list. To invoke a null parameter, remeber to chack if null
if (onFinished != null) onFinished.invoke(sprite);
or for newer c# versions :
onFinished?.invoke(sprite);
I'll test this as soon as I have some time. Then I'll tell you if it works in my case.
It didn't work. That's really weird since your method should do it.
EDIT: Never$$anonymous$$d, it works. It's just that, ins$$anonymous$$d of using an IEnumerator for the method, I'm using a void now. Someday I may change it to an async method, who knows.
Anyway, thanks @gvergidis. It works! :)
Well, glad it helps even that way. I would suggest you to try implementing my way one day to learn more about callbacks and invokes. It is really usefull function of C# and if you learn it, which is very easy since you understand it once, you will possess the power of C#!
Answer by gvergidis · Aug 21, 2018 at 11:57 AM
Where exactly are you getting the returned texture? From the parameter _sprite? Is this the returned sprite? If yes, notice that you should use the ref or the out keyword. Otherwise you are doing nothing in your coroutine.
Yes, that's the conclusion that I got to. But the coroutine does not let me put an out or a ref there. Also, the _sprite I'm passing to this coroutine is a property which could indeed be changed, but it's not ideal. Any ideas?
Ok, so, remove the _sprite parameter and add this Action onFinished
and to return the sprite you should write : onFinished.invoke(sprite);
Finally, you should parse a method with Sprite as parameter like so : public void GetSprite (Sprite theSpriteFromCoroutine) { ... }
Add this function to the other class where you want to get the sprite and you will be ok :)
Where am I supposed to add the Action? And how does that return my sprite? Could you be a little clearer on what you mean?
Answer by JChilton · Aug 22, 2018 at 09:46 PM
_sprite is no longer the same Sprite that you called this coroutine with.
Sprite.Create returns a new Sprite object.
Pass your Mod into the coroutine, then set the sprite of the Icon directly.
Although you can't use a ref in a coroutine, you can pass the Mod object entirely and edit its contents.
public static IEnumerator ImportSprite (string spritePath, Mod _mod, FilterMode filterMode, Vector2 pivot)
{
...
_mod.Icon = Sprite.Create(texture as Texture2D, new Rect(0, 0, texture.width, texture.height), pivot);
}
Your Icon has a private setter, so you'll either need to make that public, or add some public method to create it internally.
That makes sense. I totally forgot about the reference change. But there's just a problem. $$anonymous$$y mod is a structure, so I can't get it's values back. It is a struct because I'm caching it in RA$$anonymous$$ to make loading time faster - having it as a class would definitely slow things down a bit.
Follow this Question
Related Questions
How does sprite extrude edges work? 1 Answer
Imported sprites are not pixel perfect 0 Answers
Editor script to slice sprites 4 Answers
Pixels Per Unit good practice query 0 Answers
Sprite sheet not visualized correctly 0 Answers