Search code examples
c#unity-game-enginehexagonal-tiles

only the first cloned object in hierarchy gets changes? Unity3D C#


This is a problem i have been working on for days, i haven't been able to find questions on here or the unity forums that can help, could anybody help?

I have code in unity 3D C# that takes a hexagon prefab and clones it into a grid. But with my code that changes the colour of the Hexagons when clicked on only the First one in the hierarchy is affected, if i click on any of the other tiles nothing changes. No errors are given.

HERE is a video showing what i mean (you cannot see the mouse but i also try clicking on the tiles adjacent to the first one).

Grid Generation Code:

//Method to initialise Hexagon width and height
    void setSizes()
    {
        //renderer component attached to the Hex prefab is used to get the current width and height
        hexWidth = Hex.renderer.bounds.size.x;
        hexHeight = Hex.renderer.bounds.size.z;
    }

    //Method to calculate the position of the first hexagon tile
    //The center of the hex grid is (0,0,0)
    Vector3 calcInitPos()
    {
        Vector3 initPos;
        //the initial position will be in the left upper corner
        initPos = new Vector3(-hexWidth * gridWidthInHexes / 2f + hexWidth / 2, 0,
                              gridHeightInHexes / 2f * hexHeight - hexHeight / 2);

        return initPos;
    }

    //method used to convert hex grid coordinates to game world coordinates
    public Vector3 calcWorldCoord(Vector2 gridPos)
    {
        //Position of the first hex tile
        Vector3 initPos = calcInitPos();
        //Every second row is offset by half of the tile width
        float offset = 0;
        if (gridPos.y % 2 != 0)
            offset = hexWidth / 2;

        float x =  initPos.x + offset + gridPos.x * hexWidth;
        //Every new line is offset in z direction by 3/4 of the hexagon height
        float z = initPos.z - gridPos.y * hexHeight * 0.75f;
        return new Vector3(x, 0, z);
    }

    //Finally the method which initialises and positions all the tiles
    void createGrid()
    {
        //Game object which is the parent of all the hex tiles
        GameObject hexGridGO = new GameObject("HexGrid");

        for (float y = 0; y < gridHeightInHexes; y++)
        {
            for (float x = 0; x < gridWidthInHexes; x++)
            {
                //GameObject assigned to Hex public variable is cloned
                GameObject hex = (GameObject)Instantiate(Hex);
                //Current position in grid
                Vector2 gridPos = new Vector2(x, y);
                hex.transform.position = calcWorldCoord(gridPos);
                hex.transform.parent = hexGridGO.transform;
            }
        }
    }


    //The grid should be generated on game start
    void Start()
    {
        setSizes();
        createGrid();
    }
}

Colour Chaning code:

using UnityEngine;
using System.Collections;

public class tilechange : MonoBehaviour {

    public Material Black;
    public Material Grey;
    public Material OGrey;
    public int colour;

    void Start()
    {
        renderer.material = Grey;
    }

    void OnGUI()
    {
        if (GUI.Button (new Rect (400,300, 60, 25), "Black")) 
        {
            colour = 2;
            Debug.Log ("colour black");
        }
        if (GUI.Button (new Rect (400,330, 60, 25), "Grey")) 
        {
            colour = 1;
            Debug.Log ("colour grey");
        }
        if (GUI.Button (new Rect (400,360, 60, 25), "Orange Border")) 
        {
            colour = 3;
            Debug.Log ("colour OGrey");
        }
    }


    void OnMouseDown () {

        Debug.Log ("click worked");


        if(colour == 1)
        {
            renderer.material = Grey;
            Debug.Log ("grey");
        }

        if(colour == 2)
        {
            renderer.material = Black;
            Debug.Log ("black");
        }
        if(colour == 3)
        {
            renderer.material = OGrey;
            Debug.Log ("OGrey");
        }
    }
}

If anyone could help me with this it would be much appreciated :)


Solution

  • Because each clone will call its OnGUI(), so you will have lots of "Black" buttons at the same position, the button you clicked is the first clone's OnGUI button.

    You should not let clone objects call OnGUI(). And you can use PlayerPref() to store value.

    Have one object to handle GUI.

    public class MyGUI : MonoBehaviour {
        void OnGUI()
        {
            if (GUI.Button(new Rect(400, 300, 60, 25), "Black"))
            {
                Debug.Log("colour black");
                PlayerPrefs.SetInt("Colour", 2);
            }
            if (GUI.Button(new Rect(400, 330, 60, 25), "Grey"))
            {
                Debug.Log("colour grey");
                PlayerPrefs.SetInt("Colour", 1);
            }
            if (GUI.Button(new Rect(400, 360, 60, 25), "Orange Border"))
            {
                Debug.Log("colour OGrey");
                PlayerPrefs.SetInt("Colour", 3);
            }
        }
    }  
    

    Then colour change component to each clone.

    public class tilechange : MonoBehaviour {
        public Material Black;
        public Material Grey;
        public Material OGrey;
    
        void Start()
        {
            renderer.material = Grey;
        }
    
        void OnMouseDown()
        {
    
            Debug.Log("click worked");
    
            if (PlayerPrefs.GetInt("Colour") == 1)
            {
                renderer.material = Grey;
                Debug.Log("grey");
            }
            if (PlayerPrefs.GetInt("Colour") == 2)
            {
                renderer.material = Black;
                Debug.Log("black");
            }
            if (PlayerPrefs.GetInt("Colour") == 3)
            {
                renderer.material = OGrey;
                Debug.Log("OGrey");
            }
        }
    }