I'm having trouble getting custom sprites to render in the scene. Any ideas? [SOLVED]

Hey all I’m creating a tile set engine and I’m having issues with getting the sprites for the tiles to render in the scene but everything else seems to work. The following code is where my engine will cut the source sprite into smaller sprite tiles using a grid.

Any ideas?
Thanks.

        void CreateSet(){
            if (newSetName == "") {
                Debug.LogWarning ("Your new tile set must have a name.");
            }
            else if (tar.ContainsTileSet (newSetName)) {
                Debug.LogWarning ("There is already a tile set with the name : \"" + newSetName + "\".");
            }
            else if (newSetSprite == null) {
                Debug.LogWarning ("The tile set image has not been defined.");
            }
            else {
                try{
                    var tex = newSetSprite.texture;
                    int x = 0, y = 0, w = tex.width, h = tex.height;
                    List<Sprite> tiles = new List<Sprite>();
                    while(y < h){
                        var pix = tex.GetPixels(x, y, tileSize, tileSize);
                        Texture2D tileTex = new Texture2D(tileSize, tileSize, TextureFormat.RGBA32, false);
                        tileTex.SetPixels(pix);
                        tileTex.Apply();
                        Sprite tile = Sprite.Create(tileTex, new Rect(0, 0, tileSize, tileSize), newSetSprite.pivot, newSetSprite.pixelsPerUnit);
                        tile.name = (x / tileSize).ToString() + "-" + (y / tileSize).ToString();
                        tiles.Add(tile);
                        x += tileSize;
                        if(x >= w){
                            x = 0;
                            y += tileSize;
                        }
                    }
                    var s = new TileSet(newSetName, newSetSprite, tileSize, tiles.ToArray());
                    tileSets.Add(s);
                    newSetName = "";
                }
                catch(System.Exception e){
                    Debug.LogWarning ("The tile set could not be created.");
                    throw e;
                }
            }
        }

There must be something wrong in how your taking these sprites and trying to put them on the screen. I created a project and used your texture chopping code it and it works 100%

I created a new 2D project. I added 5 sprites to my scene called WholeSprite, TopLeft, TopRight, BotLeft, BotRight.
Then I Created and empty game object and added this script to it. I dragged the 5 sprites to the appropriate spot in the inspector on this script. It has your chopping code in it , slightly modified since i don’t have your infrastructure for TileSets. I just take the List of chopped up sprites directly.
TileChopper

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

public class TileChopper : MonoBehaviour
{
    public GameObject WholeSprite;
    public GameObject TopLeft;
    public GameObject TopRight;
    public GameObject BotLeft;
    public GameObject BotRight;

    Texture2D wholeTex;
    Sprite wholeSprite;
    int tileSize = 100;
    Color[] colors = new Color[4] { Color.red, Color.green, Color.blue, Color.black };

    void Start()
    {
        wholeTex = new Texture2D(2 * tileSize, 2 * tileSize);
        // just makes a tile with 4 squares of colors
        for (int a = 0; a < 2; ++a)
        {
            for (int b = 0; b < 2; ++b)
            {
                int colorIndex = a * 2 + b;
                for (int i = b * tileSize; i < b * tileSize + tileSize; ++i)
                    for (int j = a * tileSize; j < a * tileSize + tileSize; ++j)
                        wholeTex.SetPixel(i, j, colors[colorIndex]);
            }
        }
        wholeTex.Apply();
        wholeSprite = Sprite.Create(wholeTex, new Rect(0, 0, wholeTex.width, wholeTex.height), Vector2.zero, 100f);
        List<Sprite> choppedSprites = ChopSprite();

        WholeSprite.GetComponent<SpriteRenderer>().sprite = wholeSprite;
        BotLeft.GetComponent<SpriteRenderer>().sprite = choppedSprites[0];
        BotRight.GetComponent<SpriteRenderer>().sprite = choppedSprites[1];
        TopLeft.GetComponent<SpriteRenderer>().sprite = choppedSprites[2];
        TopRight.GetComponent<SpriteRenderer>().sprite = choppedSprites[3];

        WholeSprite.transform.position = new Vector3(-1, -1, 0);
        BotLeft.transform.position = new Vector3(-2, -2, 0);
        BotRight.transform.position = new Vector3(1, -2, 0);
        TopLeft.transform.position = new Vector3(-2, 1, 0);
        TopRight.transform.position = new Vector3(1, 1, 0);
    }

    private List<Sprite> ChopSprite()
    {
        var tex = wholeSprite.texture;
        int x = 0, y = 0, w = tex.width, h = tex.height;
        List<Sprite> tiles = new List<Sprite>();
        while (y < h)
        {
            var pix = tex.GetPixels(x, y, tileSize, tileSize);
            Texture2D tileTex = new Texture2D(tileSize, tileSize, TextureFormat.RGBA32, false);
            tileTex.SetPixels(pix);
            tileTex.Apply();
            Sprite tile = Sprite.Create(tileTex, new Rect(0, 0, tileSize, tileSize), wholeSprite.pivot, wholeSprite.pixelsPerUnit);
            tile.name = (x / tileSize).ToString() + "-" + (y / tileSize).ToString();
            tiles.Add(tile);
            x += tileSize;
            if (x >= w)
            {
                x = 0;
                y += tileSize;
            }
        }
        return tiles;
    }


}

Try making this project you’ll see it creates a sprite thats 200x200 with 4 colors in it. It then chops that sprite up into 4 100x100 sprites each of a solid color. So your error must be somewhere else in the TileSet code and how your getting the sprites out of it, or assigning them in your scene. The sprites this code creates are perfect.

Another possibility is somehow your newSetSprite is incorrectly set or corrupted and thus newSetSprite.texture will be as well.

1 Like

Cool thanks it was actually a problem with how I was invoking Sprite.Create. I just changed it to how you have it in yours and it worked perfectly.

Thanks

1 Like

For those of you who are building your own I thought id add that its better to make the pixels per unit the same as the tile size like this.

Sprite tile = Sprite.Create(tileTex, new Rect(0, 0, tileSize, tileSize), Vector2.zero, tileSize);

This way the transform positions line up 1 2 3… and so on if that makes sense.

There are other ratios you might use to that might be useful. I quick run down on what the PixelPerUnits is actually doing in case you didn’t know:

Any orthographic camera (default for Unity 2D projects) has an orthographicSize. It defaults to 5. That means your screen’s y-Axis will run from +5 to -5. So each unit will equal ScreenHeight/2*orthographicSize. Say your running in 1600x900. Then each Unit of space on your screen will equal 90 pixels. it uses this value to calculate the X axis range. I will be: 1600/90 = 17.77777 so your X-Axis will go from -8.88888 to +8.88888

Now PixelsPerUnit means that if you take your raw Image,it will take that many pixels to equal 1 unit on your screen. So this scales your sprite. Say you set Pixels per Unit = 100. Then a 100x100 image will show up as a 90x90 image on the screen. So when you set PixelsPerUnit = tileSize that means you are fitting exactly 10 tiles up and down your screen. and 17.7777 tiles left to right. It seems to line up nicely because it converts your sprite to exactly 1x1 unit of screen space.

You can use this knowledge to set your PixelPerUnits to something else, say you always want to fit 20 across the screen (left to right) then you PIxelPerUnits should be TileSize 900/1600 * 20/(2cameraSize)

Yeah I was just going to use game object transforms for scene assembly using my grid window so the units being the same size as the tile will make things like snapping and painting tiles easier to accomplish.

that also makes it easier to create one big collider for a section of tiles rather than one collider for each tile (Polygon Status basically).

Thanks man.