Help with trying to change the value of x value of the localScale of a game object with code

Hi there,

I’m trying to create a simple platformer game where I can just move the player game object left or right on the x-axis using the arrow keys on my keyboard.
Although I’ve succeeded in making this functionality work properly through the usage of Rigidbody2D and code, I don’t understand a couple of lines of code that I’ve written and why it works. You can see below in my code I’ve created a two part if else statement that makes the player sprite image flip depending on which direction the player is moving.
Here’s the code I’ve written:

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

public class Player : MonoBehaviour
{
    private Rigidbody2D _rb;
    public float _moveInput;
    private int _speed = 7;
    public Vector3 _scaler;
    public bool isFacingRight = true;


    // Start is called before the first frame update
    void Start()
    {
        _rb = GetComponent<Rigidbody2D>();
    }

    // Update is called once per frame
    void Update()
    {
        _scaler = transform.localScale;
        _moveInput = Input.GetAxisRaw("Horizontal");
        _rb.velocity = new Vector2(_moveInput * _speed, _rb.velocity.y);


  

        if(isFacingRight == false && _moveInput > 0)
        {
            isFacingRight = true;
           _scaler.x = _scaler.x * -1;
            transform.localScale = _scaler;
            Debug.Log("transform.localScale equals to " + _scaler.x);



        } else if (isFacingRight == true && _moveInput <0)

        {

            isFacingRight = false;
           _scaler.x = _scaler.x * -1;
            transform.localScale = _scaler;
            Debug.Log("transform.localScale equals to " + _scaler.x);


        }
     


    }//update



}

What I don’t understand is if I remove the line “transform.localScale = _scaler;” from the two parts of the if statement the function wont work. I don’t understand why it doesn’t just work if I just write the if statements with that line removed like so:

        if(isFacingRight == false && _moveInput > 0)

        {
            isFacingRight = true;
           _scaler.x = _scaler.x * -1;
            Debug.Log("transform.localScale equals to " + _scaler.x);



        } else if (isFacingRight == true && _moveInput <0)

        {

            isFacingRight = false;
           _scaler.x = _scaler.x * -1;
            Debug.Log("transform.localScale equals to " + _scaler.x);


        }

Can anyone explain why I need to include “transform.localScale = _scaler;” in order for the x value of the localScale to change correctly in my if statement?

Vector2 and Vector3 objects are value types.

This means:

takes a snapshot of transform.localScale and copies it to _scaler, which is just a field in your script.

There is no relationship between those two things beyond that one initial copy of the data.

If you want more general info, look into the difference between value types and reference types. It’s important.

2 Likes

I understand that examples of datatypes are int, float ,string etc. Am I wrong in saying that Vector2 and Vector3 in this context are also datatypes? I’m wondering why do you refer to them as objects? I understand that Vector2 and Vector3 represent xyz co ordinates etc but I’m also wondering what exactly do I call “_scaler” when I write the following:

  public Vector3 _scaler;

Do I call it a Vector 3 variable? I’m obviously storing xyz co ordinates inside of it…

I’m doing research on the difference between value types and reference types. From watching the following video, examples of value types are supposed to be things like int, floats and bools and examples of reference types are classes and objects:
https://www.youtube.com/watch?v=KGFAnwkO0Pk

I’m just wondering why do you refer Vector2 and Vector3’s as objects if they’re supposed to be value types?

“Object” is a loose term, usually used to refer to a thing that has more than one item inside, but objects can even have ZERO things inside them, such as an empty class or interface with no methods.

And technically at some level everything is an object in some sense. Like an int is actually a handy alias for a System.Int32… same exact animal. Hover over an int and see:

6779456--784505--Screen Shot 2021-01-29 at 6.37.46 AM.png

All those interfaces are also implemented for integers, telling you what all you can do with them: comparable, equatable, formattable, convertible, etc.

Really the main thing here is:

  • value types : the equal sign makes a fresh clean unrelated copy of the value to the new variable

  • reference types : the equal sign makes a new variable that is an arrow saying “I am that same exact thing over there by a different name” (but it does NOT make a copy of the thing)

1 Like

Okay I get it, I think.

So in the update function I have the _scaler variable equal to the game object’s current localScale values:

_scaler = transform.localScale

Later on in the code I change the value of the x value that’s stored within the _scaler variable.

But just because I have changed this value within the _scaler variable it does not mean that I have changed the x value of the game object’s localScale.
The reason for this is because the _scaler variable was declared as a Vector2 variable which is a value type. Therefore _scaler only stores a copy of the value of localScale and does not directly refer to its value.

Exactly, Egon!

As for terminology, many folks (myself included) are not always precise in their language. Variable, field, object, struct, class, property, are often mis-used slightly (even thought they all imply different things), and the same goes for function, method, as well as for delegate, callback, functor, etc.

1 Like

I understand. I’m just trying to think of times when I would use variables that are “reference types” as opposed to “value types” in Unity.

For example when I declare a string or an array at the top of a script like so:

private string _name = "Egon"
private int[] _array = {0,1,2,3,4,5};

Are these two examples of declaring variables that are “reference types”?

There’s more subtlety here actually… strings are reference types and they are also immutable, so there’s this weird gray area.

That means if you have two things pointed to “Egon” and change one of them, the other does not change.

Arrays are also immutable but passed as reference types. You can change their contents but you can’t change them (or their size).

To further muddy the water, generally a value type cannot be null… because it’s just the data.

BUT! You can make a nullable value type that CAN be null as well!

int? MyNullableInteger = null;  // perfectly legal

MyNullableInteger = 234;   // legal

But if someone wants an integer, you have to cast your nullable integer (int?) to a regular integer (int) first.

Furthermore Unity’s API sometimes returns a copy of things for you rather than the original thing. This can get really mind boggling.

tl;dr, “It’s complicated, just beware of possible combinations and outcomes.”