The game is running slow for no reason

Hi,
I’m making a sort of tetris game that i want to run on WP8.1.

The game is almost finished but when it comes to play, at the beginning the game is smooth but the more there are blocks added the more is slows down. It’s not supposed to happen since everytime you place a block its script is disabled (and so update is not called anymore) so why would it slow the game?

I saw on other questions that some people had problems with 3d game using like 3000 objects a bit slow on a device cheaper than mine while my game is 2d and only uses about 20/30 objects max.

Any clue to what i could check ?

Thanks.

PS : I must warn you, I’m under unity 4.
I tried to port it to unity 5 but I couldn’t and hopefully I made a backup before because I would have lost my project entirely :frowning:

Yep, it will be imposible to determine the problem without sources. The best is to give us full project, if possible.

If not, try to beat the problem on your own.
Try to use profiler with windows phone to figure which part of gameplay is causing the problem. The profiler is free now since Unity 5 released.
It’ll be helpful to use Profiler.BeginSample and Profiler.EndSample to check out pieces of code that may hit performance. Good luck

Here’s the main class :

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

public class Grid : MonoBehaviour
{

    public static int score = 0;
    public static string message = "";
    public static string recordText = "RECORD

<size=20>“+PlayerPrefs.GetInt(“Player Best Score”)+”";
public static bool stocked = false;

    public static Group stockedGroup = null;
    public static Group actualGroup = null;
    public static Group cancelActualGroup = null;
    public static Group cancelRandomGroup = null;
    public static int cancelScore = 0;

    public static int w = 10;
    public static int h = 10;
    public static bool quitCheck = false;
    public static bool muted = false;

    public static List<int> deletedRows;
    public static List<int> deletedColumns;

    public static Transform[,] grid = new Transform[w, h];
    public static Transform[,] deleted = new Transform[w, h];

    public static Spawner spawner;

    void Start()
    {
        quitCheck = false;
    }

    public static Vector2 roundVec2(Vector2 v)
    {
        return new Vector2(Mathf.Round(v.x),
                           Mathf.Round(v.y));
    }

    public static Vector3 roundVec3(Vector3 v)
    {
        return new Vector3(Mathf.Round(v.x),
                           Mathf.Round(v.y),
                           v.z);
    }

    public static bool insideBorder(Vector2 pos)
    {
        return ((int)pos.x >= 0 &&
                (int)pos.x < w &&
                (int)pos.y >= 0 &&
                (int)pos.y < h);
    }

    public static void deleteRow(int y)
    {
        for (int x = 0; x < w; x++)
        {
            grid[x, y].renderer.enabled = false;
            //grid[x, y].position += new Vector3(-10F,0F,0F);
            deleted[x, y] = grid[x, y];
            grid[x, y] = null;
        }
    }

    public static void deleteColumn(int x)
    {
        for (int y = 0; y < h; y++)
        {
            if (grid[x, y] != null)
            {
                grid[x, y].renderer.enabled = false;
                //grid[x, y].position += new Vector3(-10F, 0F, 0F);
                deleted[x, y] = grid[x, y];
                grid[x, y] = null;
            }
        }
    }

    public static void decreaseRow(int y)
    {
        for (int x = 0; x < w; x++)
        {
            grid[x, y - 1] = grid[x, y]; // Move one towards bottom
            if (grid[x, y - 1] != null) { grid[x, y - 1].position += new Vector3(0, -1, 0); } // Update Block position
            grid[x, y] = null;
        }
    }

    public static void increaseRow(int y)
    {
        for (int x = 0; x < w; x++)
        {
            grid[x, y + 1] = grid[x, y]; // Move one towards top
            if (grid[x, y + 1] != null) { grid[x, y + 1].position += new Vector3(0, 1, 0); } // Update Block position
            grid[x, y] = null;
        }
    }

    public static void decreaseColumn(int x)
    {
        for (int y = 0; y < h; y++)
        {
            grid[x - 1, y] = grid[x, y]; // Move one towards left
            if (grid[x - 1, y] != null) { grid[x - 1, y].position += new Vector3(-1, 0, 0); } // Update Block position
            grid[x, y] = null;
        }
    }

    public static void increaseColumn(int x)
    {
        for (int y = 0; y < h; y++)
        {
            if (grid[x, y] != null)
            {
                grid[x + 1, y] = grid[x, y]; // Move one towards right
                if (grid[x + 1, y] != null) { grid[x + 1, y].position += new Vector3(1, 0, 0); } // Update Block position
                grid[x, y] = null;   
            }
        }
    }

    public static void decreaseRowsAbove(int y)
    {
        for (int i = y; i < h; i++)
            decreaseRow(i);
    }

    public static void increaseRowsAbove(int y)
    {
        for (int i = h-2; i >= y; i--)
            increaseRow(i);
    }

    public static void increaseRowsUnder(int y)
    {
        for (int i = y; i >= 0; i--)
            increaseRow(i);
    }

    public static void decreaseRowsUnder(int y)
    {
        for (int i = 1; i <= y; i++)
            decreaseRow(i);
    }

    public static void decreaseColumnsAbove(int x)
    {
        for (int i = x; i < w; i++)
            decreaseColumn(i);
    }

    public static void decreaseColumnsUnder(int x)
    {
        for (int i = 1; i <= x; i++)
            decreaseColumn(i);
    }

    public static void increaseColumnsUnder(int x)
    {
        for (int i = x; i >= 0; i--)
            increaseColumn(i);
    }

    public static void increaseColumnsAbove(int x)
    {
        for (int i = w-2; i >= x; i--)
            increaseColumn(i);
    }

    public static bool isRowFull(int y)
    {
        for (int x = 0; x < w; ++x)
            if (grid[x, y] == null)
                return false;
        return true;
    }

    public static bool isColumnFull(int x)
    {
        int compteur = 0;
        for (int y = 0; y < h; ++y)
        {
            if (grid[x, y] != null)
            { compteur++; }
        }
        if (compteur >= h - deletedRows.Count) { return true; }
        else { return false; }
    }

    public static void clearDeleted()
    {
        for (int y = 0; y < h; ++y)
        {
            for (int x = 0; x < w; ++x)
            {
                if (deleted[x,y] != null)
                {
                    Destroy(deleted[x, y].gameObject);
                    deleted[x, y] = null;
                }
            }
        }
    }

    public static void deleteFullRowsAndColumns()
    {
        clearDeleted();
        deletedRows = new List<int>();
        for (int y = 0; y < 5; ++y)
        {
            if (isRowFull(y))
            {
                deleteRow(y);
                deletedRows.Add(y);
                increaseRowsUnder(y - 1);
            }
        }
        for (int y = h-1; y >= 5; --y)
        {
            if (isRowFull(y))
            {
                deleteRow(y);
                deletedRows.Add(y);
                decreaseRowsAbove(y + 1);
            }
        }
        deletedColumns = new List<int>(); ;
        for (int x = 0; x < 5; ++x)
        {
            if (isColumnFull(x))
            {
                deleteColumn(x);
                deletedColumns.Add(x);
                increaseColumnsUnder(x - 1);
            }
        }
        for (int x = w-1; x >= 5; --x)
        {
            if (isColumnFull(x))
            {
                deleteColumn(x);
                deletedColumns.Add(x);
                decreaseColumnsAbove(x + 1);
            }
        }
        score += (deletedRows.Count + deletedColumns.Count) * (deletedRows.Count + deletedColumns.Count);
        if (deletedRows.Count + deletedColumns.Count > 0)
        {
            if (score > PlayerPrefs.GetInt("Player Best Score"))
            {
                recordText = "

NEW RECORD";
PlayerPrefs.SetInt(“Player Best Score”, score);
PlayerPrefs.Save();
}
spawner.updateScore();
}
foreach (Group grp in FindObjectsOfType())
{
if (grp.transform.childCount == 0)
{ Destroy(grp.gameObject); }
}
}

    public static void restoreRow(int y)
    {
        for (int x = 0; x<w; x++)
        {
            if (deleted[x, y] != null)
            {
                grid[x, y] = deleted[x, y];
                grid[x, y].renderer.enabled = true;
                //deleted[x, y].position -= new Vector3(-10F, 0F, 0F);
                deleted[x, y] = null;
            }
        }
    }

    public static void restoreColumn(int x)
    {
        for (int y = 0; y < h; y++)
        {
            if (deleted[x, y] != null)
            {
                grid[x, y] = deleted[x, y];
                grid[x, y].renderer.enabled = true;
                //deleted[x, y].position -= new Vector3(-10F, 0F, 0F);
                deleted[x, y] = null;
            }
        }
    }

    public static void stock()
    {
        if (stockedGroup == null)
        {
            stockedGroup = actualGroup;
            actualGroup = null;
            FindObjectOfType<Spawner>().spawnNext(); // Spawn next Group
            stockedGroup.recolorate();
            stockedGroup.enabled = false;
            stockedGroup.transform.position = new Vector3(1, h+1.75F, (float)-0.5);
            stockedGroup.transform.localScale = new Vector3(0.5F, 0.5F, 1);
        }
        else
        {
            Group temp = stockedGroup;
            stockedGroup = actualGroup;
            actualGroup = temp;
            stockedGroup.recolorate();
            stockedGroup.enabled = false;
            actualGroup.enabled = true;
            stockedGroup.transform.position = new Vector3(1, h + 1.75F, (float)-0.5);
            stockedGroup.transform.localScale = new Vector3(0.5F, 0.5F, 1);
            actualGroup.transform.position = new Vector3((int)(w/2), (int)(h/2), (float)-0.5);
            actualGroup.transform.localScale = new Vector3(1, 1, 1);
        }
        stocked = !stocked;
    }

    //public static bool lost()
    //{
    //    if (stockedGroup != null && actualGroup != null)
    //    { return !actualGroup.canPlace() && !stockedGroup.canPlace(); }
    //    Debug.Log("Result : False");
    //    return false;
    //}

    public static void blit()
    {
        actualGroup.blit();
        spawner.updateMessage();
    }

    public static void rotate()
    {
        actualGroup.rotate();
    }

    public static List<int> mySort(List<int> l)
    {
        List<int> l1 = new List<int>();
        List<int> l2 = new List<int>();
        l1 = l.FindAll(delegate(int i) { return i < 5; });
        l2 = l.FindAll(delegate(int i) { return i >= 5; });
        l1.Sort(delegate(int x, int y) { return -x.CompareTo(y); });
        l2.Sort(delegate(int x, int y) { return x.CompareTo(y); });
        l1.AddRange(l2);
        return l1;
    }

    public static void cancel()
    {
        if (cancelActualGroup != null)
        {
            score = cancelScore;
            spawner.updateScore();
            if (deletedColumns.Count > 0)
            {
                deletedColumns = mySort(deletedColumns);
                foreach (int y in deletedColumns)
                {
                    if (y >= 5)
                    {
                        increaseColumnsAbove(y);
                        restoreColumn(y);
                    }
                    else
                    {
                        decreaseColumnsUnder(y);
                        restoreColumn(y);
                    }
                }
            }
            if (deletedRows.Count > 0)
            {
                deletedRows = mySort(deletedRows);
                foreach (int x in deletedRows)
                {
                    if (x >= 5)
                    {
                        increaseRowsAbove(x);
                        restoreRow(x);
                    }
                    else
                    {
                        decreaseRowsUnder(x);
                        restoreRow(x);
                    }
                }
            }
            if (stocked) // if the actualGroup had been stocked then it means that stockedGroup is supposed to be actualGroup
            {
                stock();
            }
            cancelRandomGroup = actualGroup;
            cancelRandomGroup.enabled = false;
            foreach (Transform child in cancelRandomGroup.transform)
            {
                child.renderer.enabled = false;
            }
            actualGroup = cancelActualGroup;
            actualGroup.unblit();
            actualGroup.enabled = true;
            cancelActualGroup = null;
        }
        else
        {
            message = "Sorry, you can only revert once in a row !";
            spawner.updateMessage();
        }
    }

    public static void mute()
    {
        AudioListener.pause = true;
        //AudioListener.volume = 100;
        muted = true;
    }

    public static void unmute()
    {
        AudioListener.pause = false;
        //AudioListener.volume = 0;
        muted = false;
    }

    public static void quit()
    {
        if (quitCheck)
        {
            Application.LoadLevel("Menu");
        }
        else
        {
            spawner.quitText.text = "SURE ?";
            quitCheck = true;
        }
    }

    public static void unquit()
    {
        spawner.quitText.text = "QUIT";
        quitCheck = false;
    }
}

The group class :

using UnityEngine;
using System.Collections;

public class Group : MonoBehaviour
{
    public Sprite block;
    public Sprite original;
    private Color colour;

    // Use this for initialization
    void Start()
    {
        Grid.actualGroup = this;
        colour = RandomColour();
        foreach (Transform child in transform)
        {
            child.renderer.material.color = colour;
            child.localScale = new Vector3(0.75F, 0.75F, 1);
        }

        //Debug.Log("Verif defaite");
        //if (Grid.lost()) { Debug.Log("			DEFAAAAIIIIITE"); } //Application.LoadLevel("Menu"); }

    }

    public Color RandomColour()
    {
        int rnd = Random.Range(0, 6);
        switch (rnd)
        {
            case 0: return Color.blue;
            case 1: return Color.cyan;
            case 2: return Color.white;
            case 3: return Color.grey;
            case 4: return Color.magenta;
            case 5: return Color.yellow;
            case 6: return Color.green;
            default: return Color.white;
        }
    }

    // Update is called once per frame
    void Update()
    {
        colorate();

        // Only if 1 finger :
        //for (int i = 0; i < Input.touchCount; i++)
        if (Input.touchCount == 1)
        {
            Touch touch = Input.GetTouch(0);            

            // -- Touch
            // ------------------------------------------------
            if ( touch.phase == TouchPhase.Ended || touch.phase == TouchPhase.Began || touch.phase == TouchPhase.Moved )
            {
                // Touch are screens location. Convert to world
                Vector3 position = Camera.main.ScreenToWorldPoint(touch.position);
                //Grid.message = "Touch position : " + touch.position + ", world position : " + position;
                if (position.y >= -1 && position.y < Grid.h )
                {
                    // Reset quit
                    Grid.unquit();

                    // Effect for feedback
                    position.z = (float)-0.5;
                    transform.position = Grid.roundVec3(position);
                    validatePos();
                }
            }
        }

        #if UNITY_EDITOR
        
        if (Input.GetMouseButtonDown(0))
        {
            Vector3 position = Camera.main.ScreenToWorldPoint(Input.mousePosition);
            //Grid.message = "Touch position : " + touch.position + ", world position : " + position;
            if (position.y >= -1 && position.y < Grid.h)
            {
                // Reset quit
                Grid.unquit();

                // Effect for feedback
                position.z = (float)-0.5;
                transform.position = Grid.roundVec3(position);
                validatePos();
            }
        }
        #endif
    }

    public void colorate()
    {
        foreach (Transform child in transform)
        {
            Vector2 v = Grid.roundVec2(child.position);
            { child.renderer.material.color = colour; }
            if (Grid.grid[(int)v.x, (int)v.y] != null)
            { child.renderer.material.color = Color.red; }
        }
    }

    public void recolorate()
    {
        foreach (Transform child in transform)
        {
            { child.renderer.material.color = colour; }
        }
    }

    public bool canBlit()
    {
        foreach (Transform child in transform)
        {
            Vector2 v = Grid.roundVec2(child.position);
            if (Grid.grid[(int)v.x, (int)v.y] != null)
            { return false; }
        }
        return true;
    }

    public void blit()
    {
        if (canBlit())
        {
            // Blit children
            foreach (Transform child in transform)
            {
                Vector2 v = Grid.roundVec2(child.position);
                child.position += new Vector3(0, 0, (float)0.5);
                Grid.grid[(int)v.x, (int)v.y] = child;
                child.renderer.material.color = colour;
                child.localScale = new Vector3(1, 1, 1);
                child.GetComponent<SpriteRenderer>().sprite = block;
            }

            // Disable script
            enabled = false;

            // Save groups to enventually revert later
            Grid.cancelActualGroup = this;
            Grid.cancelScore = Grid.score;

            // Clear filled horizontal lines
            Grid.deleteFullRowsAndColumns();

            // Spawn next Group
            FindObjectOfType<Spawner>().spawnNext();

            // Reset stocked
            Grid.stocked = false;

            // Reset message
            Grid.message = "";
        }
    }

    public void unblit()
    {
        foreach (Transform child in transform)
        {
            Vector2 v = Grid.roundVec2(child.position);
            child.position -= new Vector3(0, 0, (float)0.5);
            Grid.grid[(int)v.x, (int)v.y] = null;
            child.localScale = new Vector3(0.75F, 0.75F, 1);
            child.GetComponent<SpriteRenderer>().sprite = original;
        }
    }

    public static int min ( int a, int b)
    {
        if (a < b) { return a; }
        else { return b; }
    }

    bool isValidGridPos()
    {
        foreach (Transform child in transform)
        {
            Vector2 v = Grid.roundVec2(child.position);

            // Not inside Border?
            if (!Grid.insideBorder(v))
                return false;
        }
        return true;
    }

    void validatePos()
    {
        bool invalid = true;
        while (invalid)
        {
            invalid = false;
            foreach (Transform child in transform)
            {
                Vector2 v = Grid.roundVec2(child.position);
                if (v.x >= Grid.w) { transform.position += new Vector3(-1, 0, 0); invalid = true; }
                if (v.x < 0) { transform.position += new Vector3(1, 0, 0); invalid = true; }
                if (v.y >= Grid.h) { transform.position += new Vector3(0, -1, 0); invalid = true; }
                if (v.y < 0) { transform.position += new Vector3(0, 1, 0); invalid = true; }
            }
        }
    }

    //public bool canPlace()
    //{
    //    for (int k = 0; k < 4; k++)
    //    {
    //        for (int i = 0; i < Grid.w; i++)
    //        {
    //            for (int j = 0; j < Grid.h; j++)
    //            {
    //                if (canPlace(i, j)) { Debug.Log("CAN PLACE "+transform+" AT : ("+i+","+j+")"); return true; }
    //            }
    //        }
    //        transform.Rotate(0, 0, -90);
    //    }
    //    return false;
    //}

    //public bool canPlace(int x, int y)
    //{
    //    foreach (Transform child in transform)
    //    {
    //        Vector2 v = Grid.roundVec2(child.localPosition);
    //        v.x += x;
    //        v.y += y;
    //        if (v.x >= Grid.w || v.x < 0 || v.y >= Grid.h || v.y < 0) { Debug.Log("	 Check (" + v.x + "," + v.y + ") : HORS LIMITES"); return false; }
    //        if (Grid.grid[(int)v.x, (int)v.y] != null) { Debug.Log("	 Check (" + v.x + "," + v.y + ") : PEUT PAS POSER"); return false; }
    //    }
    //    return true;
    //}

    public void rotate()
    {
        // Rotate
        transform.Rotate(0, 0, -90);
        validatePos();
        colorate();
    }
}

And finally the Spawner class :

using UnityEngine;
using UnityEngine.UI;
using System.Collections;

public class Spawner : MonoBehaviour
{
    // Groups
    public Text buttonText;
    public Text scoreText;
    public Text messageText;
    public Text muteText;
    public Text quitText;
    public GameObject[] groups;
    

    public void spawnNext()
    {
        if (Grid.cancelRandomGroup != null)
        {
            Grid.actualGroup = Grid.cancelRandomGroup;
            Grid.cancelRandomGroup = null;
            Grid.actualGroup.enabled = true;
            foreach (Transform child in Grid.actualGroup.transform)
            {
                child.renderer.enabled = true;
            }
        }
        else
        {
            // Random Index
            int i = Random.Range(0, Group.min((groups.Length), (int)(6 + (Grid.score) / 6)));
            // Spawn Group at current Position
            Instantiate(groups*, transform.position, Quaternion.identity);*

}
}

void Start()
{
// Mute if set to true
if (Grid.muted) { Grid.mute(); muteText.text = “UNMUTE”; }
else { muteText.text = “MUTE”; }

// Refer to Spawner in Grid
Grid.spawner = this;

// Spawn initial Group
spawnNext();

// Set score to 0
scoreText.text = “SCORE
<color=red><size=20>” + Grid.score + "<color=cyan>
" + Grid.recordText + “”;

}

void Update()
{

}

public void updateScore()
{
scoreText.text = “SCORE
<color=red><size=20>” + Grid.score + "<color=cyan>
" + Grid.recordText + “”;

}

public void updateMessage()
{
messageText.text = Grid.message;
}

public void demandeStock() { buttonText.text = “” ; Grid.stock(); }
public void demandeTourner() { Grid.rotate(); }
public void demandeBlit() { Grid.blit(); }
public void demandeCancel() { Grid.cancel(); }
public void demandeQuit() { Grid.quit(); }
public void demandeMute()
{
if (Grid.muted) { Grid.unmute(); muteText.text = “MUTE”; }
else { Grid.mute(); muteText.text = “UNMUTE”; }
}

}