Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

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

Discussion in 'Scripting' started by egonspengler_84, Jan 28, 2021.

  1. egonspengler_84

    egonspengler_84

    Joined:
    Jan 26, 2021
    Posts:
    153
    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:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class Player : MonoBehaviour
    6. {
    7.     private Rigidbody2D _rb;
    8.     public float _moveInput;
    9.     private int _speed = 7;
    10.     public Vector3 _scaler;
    11.     public bool isFacingRight = true;
    12.  
    13.  
    14.     // Start is called before the first frame update
    15.     void Start()
    16.     {
    17.         _rb = GetComponent<Rigidbody2D>();
    18.     }
    19.  
    20.     // Update is called once per frame
    21.     void Update()
    22.     {
    23.         _scaler = transform.localScale;
    24.         _moveInput = Input.GetAxisRaw("Horizontal");
    25.         _rb.velocity = new Vector2(_moveInput * _speed, _rb.velocity.y);
    26.  
    27.  
    28.  
    29.  
    30.         if(isFacingRight == false && _moveInput > 0)
    31.         {
    32.             isFacingRight = true;
    33.            _scaler.x = _scaler.x * -1;
    34.             transform.localScale = _scaler;
    35.             Debug.Log("transform.localScale equals to " + _scaler.x);
    36.  
    37.  
    38.  
    39.         } else if (isFacingRight == true && _moveInput <0)
    40.  
    41.         {
    42.  
    43.             isFacingRight = false;
    44.            _scaler.x = _scaler.x * -1;
    45.             transform.localScale = _scaler;
    46.             Debug.Log("transform.localScale equals to " + _scaler.x);
    47.  
    48.  
    49.         }
    50.      
    51.  
    52.  
    53.     }//update
    54.  
    55.  
    56.  
    57. }
    58.  

    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:

    Code (CSharp):
    1.  
    2.  
    3.         if(isFacingRight == false && _moveInput > 0)
    4.  
    5.         {
    6.             isFacingRight = true;
    7.            _scaler.x = _scaler.x * -1;
    8.             Debug.Log("transform.localScale equals to " + _scaler.x);
    9.  
    10.  
    11.  
    12.         } else if (isFacingRight == true && _moveInput <0)
    13.  
    14.         {
    15.  
    16.             isFacingRight = false;
    17.            _scaler.x = _scaler.x * -1;
    18.             Debug.Log("transform.localScale equals to " + _scaler.x);
    19.  
    20.  
    21.         }

    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?
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,520
    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.
     
    Joe-Censored and egonspengler_84 like this.
  3. egonspengler_84

    egonspengler_84

    Joined:
    Jan 26, 2021
    Posts:
    153
    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:

    Code (CSharp):
    1.   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:


    I'm just wondering why do you refer Vector2 and Vector3's as objects if they're supposed to be value types?
     
    Last edited: Jan 29, 2021
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,520
    "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:

    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)
     
    Last edited: Oct 24, 2021
    Joe-Censored likes this.
  5. egonspengler_84

    egonspengler_84

    Joined:
    Jan 26, 2021
    Posts:
    153
    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:
    Code (CSharp):
    1. _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.
     
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,520
    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.
     
    egonspengler_84 likes this.
  7. egonspengler_84

    egonspengler_84

    Joined:
    Jan 26, 2021
    Posts:
    153
    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:

    Code (CSharp):
    1. private string _name = "Egon"
    2. private int[] _array = {0,1,2,3,4,5};

    Are these two examples of declaring variables that are "reference types"?
     
  8. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,520
    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!

    Code (csharp):
    1. int? MyNullableInteger = null;  // perfectly legal
    2.  
    3. 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."