How do I create "Two texture" or "Two state" blocks with a condition?

So, I’m trying out mechanics to a game, and I thougt of a “Gravity changer” level, where you take an item and the gravity is inverted.

For that, I want the blocks/ground in the scene to change color when the gravity is inverted. For that, I created two tilesets (It’s a pixel art-esque game, so I’m creating empty objects as ground, where I add the collider, and add children to the ground object with just the Sprite renderer with the correct tile, this will be important later), one blue (for normal gravity, downGround) and one red (for inverted gravity, upGround). I also added a public boolean variable to my Character controller script to know when is the gravity inverted.

I thought about using the animator, but since I’m using two tilesets, it means I’d have to animate every single tile to change from one state to another, and I’m sure there must be a better way.

What I did was creating two ground objects (one with the downGround tileset and other one with the upGround tileset), and adding those as children into another ground object where I actually add the collider and the script that will manage the ground changing. At the beginning of the program, the upGround is disabled by default, so I figured out I needed to toggle the enable and disable of both grounds so they change (so, if gravity is inverted, downGround will be disabled instead and upGround enabled, and vice versa). For that I used this code:

public class GravityTileSwitch : MonoBehaviour
{
    private PlayerController player;
    public GameObject downGround, upGround;
        
    void Start()
    {
        //Get PlayerController component public variables access
        player = GetComponent<PlayerController>();
    }

    private void Update()
    {
        //Show upGround
        if (player.invGravity)
        {
            downGround.SetActive(false);
            upGround.SetActive(true);
        }
        //Show downGround
        else if (!player.invGravity)
        {
            downGround.SetActive(true);
            upGround.SetActive(false);
        }
    }
}

In the public GameObject variables I attach the corresponding object, downGround and upGround.

The problem is that, when I run the program, not only is the ground not changing, but the console displays an error that says

NullReferenceException: Object reference not set to an instance of an object GravityTileSwitch.Update () (at Assets/Scripts/GravityTileSwitch.cs:19)

Does somebody know why is my code not working? I’d appreciate a lot your help, thank you!

change this to public so you can see it in the inspector

private PlayerController player;

it looks like its not getting assigned

1 Like

I tried it, and attached my Player Object into the inspector (since it’s the object that is managing my gravity bool), but when I press play to try it out the error keeps appearing.

I checked the inspector while In-game, and it turns out that it disappeared (the slot says "None (PlayerController) instead of "Player(P.C.)"), and when I stop it and check it, the script is still attached there

do you have a playercontroller attached to the same object as gravitytileswitch? if not thats the problem

1 Like

I don’t have it attached, because there is all the control like jumping, moving, etc. Or then I should create a different script just for the Gravity so I can attach that to the ground?

well its because when you do this:

  player = GetComponent<PlayerController>();

it takes the script that is attached to the object

since you dont have it attached this is the same as doing:

  player = null;

which gives you that null exception. What you want is something like this:

    public class GravityTileSwitch : MonoBehaviour
    {
        public GameObject playerObj;
        public PlayerController player;
        public GameObject downGround, upGround;
         
        void Start()
        {
            //Get PlayerController component public variables access
            player = playerObj.GetComponent<PlayerController>();
        }
   
        private void Update()
        {
            //Show upGround
            if (player.invGravity)
            {
                downGround.SetActive(false);
                upGround.SetActive(true);
            }
            //Show downGround
            else if (!player.invGravity)
            {
                downGround.SetActive(true);
                upGround.SetActive(false);
            }
        }
    }

player obj is the game object that has your player controler script

or you can just remove

player = playerObj.GetComponent();

from your code and drag it in the inspector

1 Like

Thank you! It solved my problem

1 Like