0

I followed this tutorial to form a table in Unity.

What I like to do is (1)I like to change the Cell's width x height dynamically in the code. (2)I like to set height of the first row of grids higher than the rest.

My code is

public class PopulateCellsToLeftPanel : MonoBehaviour {
    public GameObject cell;
    private int numberOfCells;
    private float cellWidth;
    private float cellHeight;

    public PopulateCellsToLeftPanel(int num, float w, float h)
    {
        numberOfCells = num;
        cellWidth = w;
        cellHeight = h;        
    }
    // Use this for initialization
    void Start()
    {

        GameObject newObj; // Create GameObject instance
        GridLayoutGroup grid = this.GetComponent<GridLayoutGroup>();
        grid.cellSize = new Vector2(cellWidth, cellHeight);
        int numRow = numberOfCells % 4;
        for (int i = 0; i < numRow; i++)//row
        {
            for (int j = 0; j < 4; j++)//column
            {                
                newObj = (GameObject)Instantiate(cell, transform);
                if(i%2 == 0)
                    newObj.GetComponent<Image>().color = Color.white;
                else
                    newObj.GetComponent<Image>().color = Color.red;
            }
        }
    }

}

Then from the main class, I tried to set using the class's constructor.

public class Historycanvas : MonoBehaviour, IPointerClickHandler
{
    PopulateCellsToLeftPanel pL;
    pL = new PopulateCellsToLeftPanel(30, CellWidth, CellHeight);

}

But numberOfCells, cellWidth and cellHeight are always 0. Is that void Start() is called earlier than class constructor?

Is it possible to set the height of first row of cells in the grid is different from the rest?

EDIT:

I did Debug.Log at both constructor function and Start function as below.

public PopulateCellsToLeftPanel(int num, float w, float h)
    {
        Debug.Log("i am from constructor start");
        numberOfCells = num;
        cellWidth = w;
        cellHeight = h;
        Debug.Log("i am from constructor end");
    }
    // Use this for initialization
    void Start()
    {
        Debug.Log("i am from Start start");
        GameObject newObj; // Create GameObject instance
        GridLayoutGroup grid = this.GetComponent<GridLayoutGroup>();
        grid.cellSize = new Vector2(cellWidth, cellHeight);
        int numRow = numberOfCells % 4;
        for (int i = 0; i < numRow; i++)//row
        {
            for (int j = 0; j < 4; j++)//column
            {                
                newObj = (GameObject)Instantiate(cell, transform);
                if(i%2 == 0)
                    newObj.GetComponent<Image>().color = Color.white;
                else
                    newObj.GetComponent<Image>().color = Color.red;
            }
        }
        Debug.Log("i am from Start end");
    }

But I am surprised as Debug.log from Start() function was printed earlier than those from constructor(). Please look at in the following attached image. That is why my variables are always 0. enter image description here

EDIT 2:

I tried to make a separate public function to instantiate image into grid as below, but images are not populated. Does it work only in Start()? Because if I put the same thing in Start() function, it works and the only issue with Start() is those parameters (int rows, float cellWidth, float cellHeight) I can't change dynamically. I need to change dynamically.

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

public class PopulateCellToLeftPanel : MonoBehaviour {

    public GameObject cell; 

    // Use this for initialization
    void Start()
    {


    }

    public void Plot(int rows, float cellWidth, float cellHeight)
    {
        Debug.Log("cell width " + cellWidth + " cell height " + cellHeight + " num rows " + rows);
        GameObject newObj; // Create GameObject instance
        GridLayoutGroup grid = this.GetComponent<GridLayoutGroup>();
        if (grid == null)
            Debug.Log("grid is null");
        grid.cellSize = new Vector2(cellWidth, cellHeight);

        for (int i = 0; i < rows; i++)//row
        {
            for (int j = 0; j < 4; j++)//column
            {
                newObj = (GameObject)Instantiate(cell, transform);
                if (i % 2 == 0)
                    newObj.GetComponent<Image>().color = Color.white;
                else
                    newObj.GetComponent<Image>().color = Color.red;
            }
        }
    }

}

Main Class

public class main: MonoBehaviour
{
   PopulateCellToLeftPanel pL = null;
    void Start()
    {
       pL = gameObject.AddComponent<PopulateCellToLeftPanel>();
       pL.Plot(13, CellWidth, CellHeight);
    }
}

My console output is as follow and grid is null.

enter image description here

batuman
  • 7,066
  • 26
  • 107
  • 229
  • Create a different GridLayout Group for the first row, later you can add those two GridLayout Groups into a Vertical Group if you like. – Thalthanas Oct 16 '17 at 13:21
  • Your `Start` function is not being called. You need to read the duplicate to see what you are doing wrong. Also note that using `Debug.Log` can be helpful in the future to determine if a function is being called or not. Finally, this is C# and I fixed the title of this question to reflect your actual problem – Programmer Oct 16 '17 at 13:45
  • @Programmer thanks, I'll look into that. But if I hard-code the values in the PopulateCellsToLeftPanel class, it works. I don't think Start() is not called. Let me check again. – batuman Oct 17 '17 at 01:22
  • `Start` function in your `PopulateCellsToLeftPanel` script can never be called with your current code. Please use `Debug.Log` to prove what I just said. If it get's called then Unity has changed lately but I doubt that – Programmer Oct 17 '17 at 01:26
  • @Programmer Please look at in EDIT in the OP. I tested with Debug.Log and found that Start is called earlier than Constructor. – batuman Oct 17 '17 at 09:23
  • Thanks for the EDIT. With my version of Unity(2017.2.0b5) it's not called. I suspect that you attached `PopulateCellsToLeftPanel` to a GameObject from the Editor and that GameObject is what's showing the second log to you or the behavior changed. Regardless, *don't you see the warning you are getting in the Editor?* Please read the duplicate. You should not not use constructor if you inherit from `MonoBehavior`. Just the read duplicate and fix that. – Programmer Oct 17 '17 at 12:39
  • @Programmer thanks, now I am clear. For the class inherited from MonoBehavior, how can I have cellWidth and cellHeight change dynamically? – batuman Oct 17 '17 at 14:00
  • Add a `public` function to the `PopulateCellsToLeftPanel ` **instead** of using the constructor. After instancing the class with `AddComponent` (as described in the duplicate), call that public function to set the `cellWidth` and `cellHeight`. – Programmer Oct 17 '17 at 14:42
  • @Programmer Images can be instantiated into grid only in Start()? I create a new public function and instantiate there. But it doesn't work. – batuman Oct 17 '17 at 15:39
  • *"Images can be instantiated into grid only in Start()?"* I never mentioned `Start` in my last comment and don't understand your comment. Please post your new code. I will take a look – Programmer Oct 17 '17 at 15:43
  • @Programmer I added in EDIT 2. – batuman Oct 17 '17 at 15:57
  • The code looks fine to me. The `Plot` function should be in the `PopulateCellsToLeftPanel`...It should be working. If not, please tell me which part is not working. You don't have to add another edit. Just continue editing your **EDIT 2**. If you can update both classes in your EDIT 2 that would be good. I want to see the complete code you have now. Please add Debug.Log too and explain what exactly do not work. – Programmer Oct 17 '17 at 17:25
  • It's looking good. `grid` is `null` which means that `this.GetComponent()` is failing. You are supposed to attach `GridLayoutGroup` to **the-same** GameObject the `PopulateCellsToLeftPanel` script is attached to then `this.GetComponent()` should work. You can also do that from script by replacing that with `grid = this.AddComponent()` . – Programmer Oct 17 '17 at 23:02
  • Also not that `public GameObject cell;` is initialized that will likely be your next issue. If `cell` is supposed to be a prefab, you can load it from the [Resources folder](https://stackoverflow.com/questions/41326248/using-resources-folder-in-unity/41326276#41326276) `pL.cell = Resources.Load("yourCellPrefab", typeof(GameObject)) as GameObject;` or if it is just a new GameObject, you can use the `new` keyword on it: `pL.cell = new GameObject("Cell");`. – Programmer Oct 17 '17 at 23:17
  • @Programmer thanks it works. Since the code is attached to container inside Scroll View, I need to get GetComponent of that container object. – batuman Oct 19 '17 at 06:02

0 Answers0