Search code examples
c#unity-game-engineaccess-modifiers

Unity- Player Jump Height / Public, Private, Static, nothing


I have been following a tutorial on 2D Player Controller in Unity (It's 'Live Training 16 Dec 2013 - 2D Character Controllers' video).

I was able to implement everything the tutorial showed successfully with some edits to make it work in Unity 5. Afterwards, I decided to play around with it so that I can gain a better understanding. One thing I tried to do was changing the jump height when pressing the Space key. Here is the code:

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

public class RobotControllerScript : MonoBehaviour {
    public float maxSpeed = 10f;
    bool facingRight = true;

    Animator anim;

    bool grounded = false;
    public Transform groundCheck;
    float groundRadius = 0.2f;
    public LayerMask whatIsGround;
    public float jumpForce = 700f;

    // Use this for initialization
    void Start () {
        anim = GetComponent<Animator>();
    }

    // Update is called once per frame
    void FixedUpdate () {

        grounded = Physics2D.OverlapCircle(groundCheck.position, groundRadius, whatIsGround);
        anim.SetBool("Ground", grounded);

        //vSpeed = vertical speed
        anim.SetFloat("vSpeed", GetComponent<Rigidbody2D>().velocity.y);

        float move = Input.GetAxis("Horizontal");

        anim.SetFloat("Speed", Mathf.Abs(move));

        GetComponent<Rigidbody2D>().velocity = new Vector2(move * maxSpeed, 
                                        GetComponent<Rigidbody2D>().velocity.y);

        if (move > 0 && !facingRight)
        {
            Flip();
        }
        else if (move < 0 && facingRight)
        {
            Flip();
        }
    }

    void Update()
    {
        if(grounded && Input.GetKeyDown(KeyCode.Space))
        {
            anim.SetBool("Ground", false);
            GetComponent<Rigidbody2D>().AddForce(new Vector2(0, jumpForce));
        }
    }

    void Flip()
    {
        facingRight = !facingRight;
        Vector3 theScale = transform.localScale;
        theScale.x *= -1;
        transform.localScale = theScale;
    }
}

Looking at the code and the tutorial explanations, jumpForce is the variable that controls how high the character will jump (force applied). So, I changed 700f to a 5f. I expected the character to make a really small jump, but this was not the case. It jumped at the same height as 700f.

public float jumpForce = 700f;

After playing around with the code, I was able to have the expected result by removing the 'public' next to jumpForce. Other ways to fix this was setting it to private or static. I remember I had a similar problem when making a temperature widget on QT Creator. I had to set a variable to static or else it would not return to the default value after C to F conversion, but I don't remember exactly why.

Can anyone explain why 'public' does not work and why a private/static/nothing might? What is the best/efficient solution for this problem? Thank you very much.


Solution

  • When a field is public (or serializable), it is shown in inspector. When it is shown in inspector, you tweak it's value, a you expect the tweaks you make to the value, in the inspector, to be preserved between play mode runs.

    When you declare a variable in the code, you may specify an initial value, like this:

    public float jumpForce = 700f;
    

    So, the first time this object gets inspected, after created, it has a reasonable value. Then, you tweak and choose a better value (or back to the same, whatever). That's the value you preferred! You want the object to keep functioning like this while you go ahead and finish making your game.

    So, once a field is tweaked in Inspector, it doesn't respect the initial value you hardcoded anymore, and that's usually what everyone want. Imagine how annoying would be if everytime you make a change in your class, all the tweaked fields got back to the initial hardcoded value...

    If a field was previously public, and then you make it private (or hidden in inspector by any mean), then the hardcoded initial value will stand.

    But, what if I really want my object to get back to it's initial/default configuration? That's why the Reset method and the reset button in inspector were made!