I'm trying to create an object that will be responsible of creating and showing different sprites, so I would like to access directly the assets/sprites programmatically instead of drag and drop a sprite in the hierarchy under that object.
There's a way to programmatically create a new sprite and assign what I have in the assets folder?
I also would like to have a sort of data structure with a few images loaded at the start of the game, an array or a dictionary or something like that so I can change based on some situation which images I need to show. But what confuses me since I'm new to Unity is how to create a sprite taking the reference to the sprite programmatically using the assets folder.
edit with progress:
I've created an array of sprites like this:
public Sprite[] mySprites;
in Unity I've added sprites inside the array manually (I just dragged png's inside the variable array) so actually in this Object I have a Component with this array full of sprites
inside the component I also have done this:
public SpriteRenderer renderer;
renderer = transform.GetComponent<SpriteRenderer>();
renderer.sprite = (Sprite)mySprites [0];
I got no error until I run the game, then the sprite is NOT assigned and I got this:
"PPtr cast failed when dereferencing! Castin from Texture2D to Sprite!"
I got this error even without casting (Sprite) and btw I don't know why he is telling my about Texture2D since verything is setted as sprite
To create a sprite programmatically might be a little too difficult to do. You'd probably need to create a Texture in memory, fill in the data, and then write that texture on the disk. After that, you should be able to read that using C#'s File, or Unity's WWW.LoadFromCacheOrDownload.
Here is how you would create a texture dynamically: http://answers.unity3d.com/questions/9919/how-do-i-create-a-texture-dynamically-in-unity.html
To load your sprites programmatically (not the ones created dynamically though), they need to be under a folder with the name Resources (which is a special folder).
I.e. suppose you have a sprite named MySprite.png under a folder named Sprites which is under a folder named Resources. You would then load it like this:
renderer.sprite = Resources.Load<Sprite>("Sprites/MySprite");
(notice how you do not include the Resources folder and the extension of the sprite)
You can find more details in the Loading Resources at Runtime documentation.
PPtr cast failed when dereferencing!
I did some searching and found out from this forum post that usually that happens when you had a list of one type and then changed it into another type. I.e. if mySprites was at some point GameObject[] and you linked a bunch of Sprites, and then changed it to Sprite[]. And since it specifically says Texture2D, I'm assuming that the import settings of your Sprites (or some of them) are set to Texture instead of Sprite:
Also, all MonoBehaviours have already a field named renderer, which is of type Renderer. I would suggest you rename that field to avoid confusion, unless you only used that as an example.
Here is real code.. will help you
void SetSprite(UI2DSprite uiSprite, Sprite[] sprites, string strKey)
{
foreach (Sprite stexture in sprites)
{
if (stexture.name == strKey)
{
uiSprite.sprite2D = stexture;
break;
}
}
}
use it following the way..
UI2DSprite[] uiSprites = tmpObject.GetComponentsInChildren<UI2DSprite>();
Sprite[] sprites = Resources.LoadAll<Sprite>("Textures");
string resName = "icon_favorite_2";
foreach (UI2DSprite uiSprite in uiSprites)
{
if(uiSprite.name = "icon")
SetSprite(uiSprite, sprites , resName);
}
Just to throw my tuppence worth in. I had this problem when I changed a SerializedField from Texture2D to Sprite in the code. The texture was already a sprite in the editor but it needed to be Sprite in the code. The field in the editor initially said type mismatch and then displayed the sprite texture again.
To cure it I set the field in the editor to none and the reset it to the required sprite.
Related
I'm trying to make an application that has sprites going down the screen with numbers in them. The Text(Script) component only works for 3D objects. I've tried using Text Mesh and making that a child of the sprites but I need them to be instantiated as a Prefab. So when I load the sprite in as a prefab it loses it's relationship to the Text Mesh. Does anyone know of a solution that worked for them?
There are many ways to do it depending upon your requirement. I will show you two of the most basic.
1- Use 2D Sprite and TextMesh.
2- Use Canvas Image and Text Objects.
P.S First one, that is 2D Sprite can be Instantiated directly in the hierarchy but for 2nd(Canvas Image) you need to instantiate it inside the canvas obj means as a child of canvas object.
I'm making a tile based board game (on a grid). In going about making the gameboard, the easy thing would be to instantiate all of the tiles in code, but then they only appear in play mode. I want to be able to edit the tiles in the editor, but I still want my tiles to be stored in a 2D array in my controller class. If I build the board in the editor, how might I go about loading them in at runtime?
Keep The Tiles in the Resources Folder Unity. At Run-time Load from the Resources and instantiate Tiles To Your Grid Positions in the Scene.
GameObject[] Tiles= (Resources.LoadAll<GameObject> ("Tiles"));
Is it possible in Unity 3D using C# to create an array to load sprites randomly from a folder rather than from a sprite sheet? If it is, what code do I use to refer to the folder? From what I can find, sprites are usually coded to load using random.range with an array using a sprite sheet instead of actually accessing the folder. The only thing even similar to this that I have been able to find is here:
http://docs.unity3d.com/ScriptReference/Resources.html
but as you can see with this you can only load from a folder titled "Resources" in the "Assets" folder, and possibly I'm mistaken but it would also seem that this can only be done with a game object. (?)
You are looking at the right docs.
A sprite is a GameObject, just a more specific one meant to be used in 2d games. So you would create your sprites and make prefab of them. Those prefabs go in the Resources folder and here is the code:
GameObject [] objs = (GameObject[])Resources.LoadAll("SpriteFolder");
GameObject randomSprite = objs[Random.Range(0, objs.Length)];
Here is what I ended up using:
Sprite[] enemySprites = Resources.LoadAll("Sprites/Enemies");
I am just getting into XNA programming and have been unable to figure out how can I access the texture from a ".x" model. I am using a custom shader to display my model (just a cube with a texture mapped on it) with the filters set to point. To do this I needed to pass the effect my texture file which needed to be imported separately from my model or else it would complain since it is included in my model as well. This works perfectly how I want it, however this isn't really an agreeable method when I have many different models with their own textures.
My question is:
How am I able to access the texture included in my model directly from it and send that to my shader? Or am I able to access it directly with HLSL?
What I have tried:
I have found posts saying that it can assigned to a texture variable with:
Texture2d texture = ((BasicEffect)model.Meshes[0].Effects[0]).Texture
When I tried this the game runs but the cubes are just black. I can see that the texture variable is holding info and has the right dimensions but I can't tell if it is correctly holding the actual image. When I used just the BasicEffect they rendered just fine with their texture.
Update:
I have managed to get this to work after a little bit of fiddling. My game loads in a few hundred of the same cube and upon creation of each it would try save the texture of the model using the code above and then go through the mesh parts and change the effects to my custom effect. I discovered that the first cube created would save the texture okay but any subsequent cubes created would complain that they can't be cast as a BasicEffect. This resulted in one textured cube and then a lot of black ones. I am guessing that when it reuses the same model over and over like that it will just use the one that was modified to use my custom effect which was done on the first instance of the cube. Is this normal? I have got them all to render as textured by changing the texture variable to static.
Please observe that you are assigning the texture of your model to a temporary Texture2D variable, and not setting the Texture present in the Effect currently tied to your mesh.
If you do the following:
Texture2D textureToSet = Content.Load<Texture2D>("MyTex");
//Keep in mind that this method requires a basic effect type and that only one
//effect is present on each mesh to work properly.
foreach(Mesh mesh in model.Meshes)
{
((BasicEffect)(mesh.Effects[0])).Texture = textureToSet;
}
The quirky stuff going on inside the foreach is simply that you are grabbing the effect, then casting it to a BasicEffect and using its Texture property to give it a new texture to draw when used. Please see the documentation and Shawn's blog for a more detailed introduction.
If anyone else is wondering about this as I was then saving the texture using:
Texture2d texture = ((BasicEffect)model.Meshes[0].Effects[0]).Texture
This does work but there is one thing to watch for which is what was causing me problems. If you change the effect of the model from the default BasicEffect for one instance it will be changed for every instance of the model created thereafter. So you will only be able to use the above code before you change the effect for the first time on a particular model.
I later found this book which describes exactly how to extract the texture and other information from a model: 3D Graphics with XNA Game Studio 4.0 by Sean James - Specifically chapter 2
I have a scene that contains mutiple objects. How can i import it in xna and mentain each objects position? right now i export the scene in .fbx and load it in a model like this :
cube.model = contentManager.Load<Model>("cub");
but the objects don't retain their position and are all gathered in one point.
I need a method to import all the objects as individual objects but to retain the objects position in the scene?
(i.e. i need to import the scene so that i may manipulate the objects and retain their position in the scene so that i shouldn't reposition all the objects by myself)
Each object's scene position is in the fbx. The way to get it and implement it is to create a matrix array to hold every object's transform relative to the scene origin, then utilize the appropriate transforms when setting the effect.World for each object during draw time.
//class variables
Matrix[] objectTransforms;
//LoadContent section
cube.model = contentManager.Load<Model>("cub");
objectTransforms = new Matrix[cube.model.Bones.Count];
cube.model.CopyAbsoluteTransformsTo(objectTransforms);// the magic is done here
//draw method
foreach(ModelMesh mm in cube.model.Meshes)
{
foreach (BasicEffect bfx in mm.Effects)
{
bfx.World = objectTransforms[mm.ParentBone.Index] * whateverLocalTransformYouWant;
//draw here
}
}
Without utilizing 'objectTransforms' all objects will be drawn with their local origins located at the world origin, which sounds like what you are experiencing.
I personally made a level editor for most of the things in my game, but I do have a large scene in blender that links to other models. That way I can arrange all the level pieces in blender. When I export each individual piece, it does retain is global position and import correctly in the game. I would say that the issue resides in your fbx exporter. There should be an option to preserve location.
What modelling program do you use? If you use blender, there is an fbx exporter set made specifically for XNA that you should use.