If score is 0 then .....

Hi Guys,

I got this script almost working but there is still a problem on first spawn. When my player jumps on a new platform the score gets increased by 1. If he jumps on the same platform the score won’t be increased. Got it almost working except for the first platform he starts on. If he jumps twice or more on the first platform the score still gets increased by one every time he jumps on it.

So there should be something extra happening like: If score is > 0 then don’t increase score.

ScoreManager.instance.GetScore () returns an int with the score.

This is the code responsible for it:

                // Increment score and instantiate platform. Also check if last platform was allready landed on


                    if (ScoreManager.instance != null && GameManager.instance != null) {

           

                        if (target != lastPlatformJumpedOn) {


                            lastPlatformJumpedOn = target;
                            ScoreManager.instance.IncrementScore ();
                            ScoreManager.instance.HighScore ();
                            GameManager.instance.CreateNewPlatformAndLerp (target.transform.position.x);
                        }
                    } else {
                        ScoreManager.instance.IncrementScore ();
                        GameManager.instance.CreateNewPlatformAndLerp (target.transform.position.x);
                        lastPlatformJumpedOn = target;

                    }

            }
        }

It looks to me like you are calling IncrementScore() for both true or false results of the target equaling
the lastPlatformJumpedOn. I wonder if removing the call from one of the blocks would help. I think that
the score will incremented whether or not the platform has been recently landed on, but I don’t know
what your IncrementScore method does.

1 Like

You Are right, it should be something like this:

                // Increment score and instantiate platform. Also check if last platform was allready landed on


                    if (ScoreManager.instance != null && GameManager.instance != null) {

         

                        if (target != lastPlatformJumpedOn) {


                            lastPlatformJumpedOn = target;
                            ScoreManager.instance.IncrementScore ();
                            ScoreManager.instance.HighScore ();
                            GameManager.instance.CreateNewPlatformAndLerp (target.transform.position.x);
                        }
                    } else if (target != lastPlatformJumpedOn && ScoreManager.instance.GetScore() == 0) {
                       Do something so score won't be increased and platforms won't be instatiaded on first platform


                    }

            }
        }

This is a part of the ScoreManager:

public void IncrementScore () {
    
        score++;
        scoretext.text = "" + score;
    }



    public void DecrementScore ()
    {
        score--;
    }

    public void HighScore ()
    {



        if (score > highScore) {
            highScore = score;
            PlayerPrefs.SetInt (highScoreKey, highScore);
            PlayerPrefs.Save ();

        }

        highScorePreText.text = "New High";
        highScoreText.text = "" + highScore;


    }

I think you have closed your if statements in the wrong place. Your original code checks to see if the ScoreManager and GameManager are not null, but if they are the else statement uses them anyway?

Will the below work? Since your setting the last platform jumped on to target, will this match only 1 time even on the first platform?

                    if (ScoreManager.instance != null && GameManager.instance != null) {
        
                        if (target != lastPlatformJumpedOn) {
                            lastPlatformJumpedOn = target;
                            ScoreManager.instance.IncrementScore ();
                            ScoreManager.instance.HighScore ();
                            GameManager.instance.CreateNewPlatformAndLerp (target.transform.position.x);
                        }
                    }

What is the first platform value of last lastPlatformJumpedOn and target?

1 Like

It still gives me the same problem.

The platform only get’s its value on a OnTriggerEnter. That’s after the character jumps a bit in the air and lands on the platform again (leaving collider and entering again). It works for the other platforms except the first one. All platforms get’s instantiated as well as the first one.

Anyone?

Please post your whole platform script. There are multiple versions above, and they’re all doing various silly things. I think @gaweph 's code will work, if you’ve interpreted it correctly, but I suspect there is still silly code in your script.

As a tip, put a Debug.Log in your IncrementScore() method, and then when you examine the log message in the Console, you can see the full traceback of how it was called. (And if you’re using Script Inspector 3, you can even right-click on the log message to jump directly to any point in the call stack.) This should make it really obvious how/why your first platform is acting differently from other platforms.

1 Like

These are the scripts as a whole, responsible for instantiation of the platforms, the score and the player jump. And yes I’m sure there is something silly happening, sorry, I’m still learning a lot.

PlayerJumpScript3D

using UnityEngine;
using System.Collections;
using UnityEngine.UI;

public class PlayerJumpScript3D : MonoBehaviour {


    public static PlayerJumpScript3D instance;

    private Rigidbody myBody;
    private Animator anim;

    //Setting the ParticleSystem vars for dust at landing on ground
    public GameObject dustPuff;
    private ParticleSystem dustParticle;

    //var for checking how long the player stays in collider
    //private float stayTime;

    // Checkin the last platform he jumped on for score management. If same platform score won increase
    Collider lastPlatformJumpedOn;

    // Var for getting score from PlayerJumpScript3D


    [SerializeField]
    private float forceX, forceY;
    private float tresholdX =7f;
    private float tresholdY = 14f;

    private bool setPower, didJump;
    private bool isGrounded = true;

    private Slider powerBar;
    private float powerBarTreshold = 10f;
    private float powerBarValue = 0f;


    void Awake ()
    {

        transform.Rotate(0,90,0);
        MakeInstance();
        Initialize();
        SetPower();
    }



    void Update ()
    {
        SetPower();

    }


    void Initialize ()
    {
        powerBar = GameObject.Find ("Power Bar").GetComponent<Slider>();
        myBody = GetComponent<Rigidbody> ();
        anim = GetComponent<Animator> ();


        powerBar.minValue = 0f;
        powerBar.maxValue = 10f;
        powerBar.value = powerBarValue;
    }



    void MakeInstance ()
    {
        if(instance == null)
            instance = this;


    }


    void SetPower ()
    {

        if (setPower) {
            forceX += tresholdX * Time.deltaTime;
            forceY += tresholdY * Time.deltaTime;

            if(forceX > 8.0f)
                forceX = 8.0f;

            if(forceY > 15.0f)
                forceY = 15.0f;


            powerBarValue += powerBarTreshold * Time.deltaTime;
            powerBar.value = powerBarValue;
        }
    }

    public void SetPower (bool setPower)
    {

        if (!isGrounded)
            return;

        this.setPower = setPower;

        if (!setPower) {
            Jump();
        }

    }


    void Jump ()
    {

        if (isGrounded)
        {

            myBody.velocity = new Vector3 (forceX, forceY);
        forceX = forceY = 0f;
        didJump = true;

        anim.SetBool("Jump", didJump);

        powerBarValue = 0f;
        powerBar.value = powerBarValue;
    }

    }

    void DisablePowerBarFillInMidAir ()
    {
        if (isGrounded == false) {
            powerBar.enabled = false;
        }
    }


    void OnTriggerEnter (Collider target)
    {

        //ResetTimer ();

        if (didJump) {

            didJump = false;
            anim.SetBool ("Jump", didJump);

            if (target.tag == "Platform") {

                //Instantiate the dust particles when landing after a jump
                GameObject dustObject = Instantiate (dustPuff, this.transform.position, this.transform.rotation) as GameObject;
                dustParticle = dustObject.GetComponent<ParticleSystem> ();
                dustParticle.transform.Rotate (0, 90, 0);

                isGrounded = true;




                // Increment score and instantiate platform. Also check if last platform was allready landed on


                    if (ScoreManager.instance != null && GameManager.instance != null) {

       

                        if (target != lastPlatformJumpedOn) {


                            lastPlatformJumpedOn = target;
                            ScoreManager.instance.IncrementScore ();
                            ScoreManager.instance.HighScore ();
                            GameManager.instance.CreateNewPlatformAndLerp (target.transform.position.x);
                        }
                    }
//                    else {
//                        //ScoreManager.instance.IncrementScore ();
//                        //GameManager.instance.CreateNewPlatformAndLerp (target.transform.position.x);
//                        //lastPlatformJumpedOn = target;
//
//                    }

            }
        }


        if (target.tag == "Dead") {
            if (GameOverManager.instance != null) {
                GameOverManager.instance.GameOverShowpanel();
            }

            Destroy(gameObject);
        }

    }


//    void OnTriggerStay (Collider target)
//    {
//
//        if (didJump) {
//
//            if (target.tag == "Platform") {
//                stayTime = stayTime * Time.deltaTime;
//
//                if (stayTime < 4f)
//                    ScoreManager.instance.DecrementScore ();
//            }
//        }
//    }



    private void OnTriggerExit(Collider target)
    {
        if (target.tag == "Platform")
            isGrounded = false;

            //ResetTimer();
            //powerBar.SetActive(false);
    
    }


//    void ResetTimer ()
//    {
//        stayTime = 0.0f;
//    }
//
}

ScoreManager

using UnityEngine;
using System.Collections;
using UnityEngine.UI;

public class ScoreManager : MonoBehaviour {


    public static ScoreManager instance;

    private Text scoretext;
    private Text highScorePreText;
    private Text highScoreText;

    private GameObject scorePreObjText;
    private GameObject highScoreObjText;


    private int score;
    private int coinScore;
    private int highScore;
    private int prevHighScore;

    string highScoreKey = "HighScore";
    //string prevHighScoreKey = "PrevHighScore";


    void Awake ()
    {

        // Find the gameObject of the text ellement
        scorePreObjText = GameObject.Find("High Score Pre");
        highScoreObjText = GameObject.Find("High Score");

        // Find the text ellement
        scoretext = GameObject.Find ("Score Text").GetComponent<Text> ();
        highScorePreText = GameObject.Find ("High Score Pre").GetComponent<Text> ();
        highScoreText = GameObject.Find ("High Score").GetComponent<Text>();

        //Loading in the scores from latest round
        highScore = PlayerPrefs.GetInt(highScoreKey, highScore);
        prevHighScore = PlayerPrefs.GetInt(highScoreKey, highScore);

        MakeInstance();


        highScoreObjText.SetActive (false);
        scorePreObjText.SetActive (false);
    }

    void MakeInstance () {
        if (instance == null)
            instance = this;
    }


    public void IncrementScore () {
   
        score++;
        scoretext.text = "" + score;
    }



    public void DecrementScore ()
    {
        score--;
    }

    public void HighScore ()
    {



        if (score > highScore) {
            highScore = score;
            PlayerPrefs.SetInt (highScoreKey, highScore);
            PlayerPrefs.Save ();

        }

        highScorePreText.text = "New High";
        highScoreText.text = "" + highScore;


    }


    // Also part of the score. Helpt the GameOverPanel to get the HighScore from previous round.
    public void UpdatePrev ()
    {
        prevHighScore = highScore;
        }


    // ----- Sends info to GameOverManager class for the GameOverPanel() function ------

    public int GetHighScore ()
    {
        //Debug.Log ("GetHighScore () = " + highScore);
        return this.highScore;
    }

    public int GetPrevHighScore ()
    {
        //prevHighScore = PlayerPrefs.GetInt (prevHighScoreKey, prevHighScore);
        Debug.Log ("SHOW GetPrevHighScore() is: " + prevHighScore + " --- HighScore is: " + highScore);

        return this.prevHighScore;

    }


    public int GetScore ()
    {
        //Debug.Log ("GetScore() =  " + score);
        return this.score;
    }

    // ---------------------------------------------------------------------------------
}

And GameOverManager

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class GameOverManager : MonoBehaviour {



    public static GameOverManager instance;

    private GameObject gameOverpanel;
    private GameObject panelNewHigh;
    private Animator gameOverAnim;

    private Button playAgainBtn, backBtn, highScoreButtonOK;

    private GameObject scoreText;
    private Text finalScore;
    private Text finalHighScore;
    private Text newHigh;

    private GameObject hScorePreText;
    private GameObject hScoreText;


    void Awake ()
    {
        MakeInstance ();
        InitializeVariables();
    }


    void MakeInstance ()
    {
        if (instance == null)
        instance = this;
    }

    // shows the Game Over Panels. Also shows the High Score Panel if a High Score is made
    public void GameOverShowpanel ()
    {

        if (ScoreManager.instance.GetPrevHighScore () >= ScoreManager.instance.GetScore ()) {

            Debug.Log(" PrevHighScore is: " + ScoreManager.instance.GetPrevHighScore() + ", Score was : " + ScoreManager.instance.GetScore());

            scoreText.SetActive (false);
            gameOverpanel.SetActive (true);

            finalScore.text = "Score: " + "" + ScoreManager.instance.GetScore ();
            finalHighScore.text = "High Score: " + "" + ScoreManager.instance.GetHighScore ();

            gameOverAnim.Play ("FadeIn");

        // Shows the High Score Panel if a High Score is made
        } else {

            Debug.Log(" PrevHighScore is: " + ScoreManager.instance.GetPrevHighScore() + ", Score was : " + ScoreManager.instance.GetScore());

            scoreText.SetActive (false);
            hScorePreText.SetActive (true);
            hScoreText.SetActive (true);
            panelNewHigh.SetActive (true);

            ScoreManager.instance.UpdatePrev();
        }
    }


    void InitializeVariables ()
    {
        gameOverpanel = GameObject.Find ("Game Over Panel Holder");
        panelNewHigh = GameObject.Find ("Panel Ok High");

        gameOverAnim = gameOverpanel.GetComponent<Animator> ();
        playAgainBtn = GameObject.Find ("Restart Button").GetComponent<Button> ();
        backBtn = GameObject.Find ("Back Button").GetComponent<Button> ();

        highScoreButtonOK = GameObject.Find ("Button OK High").GetComponent<Button> ();
        ScoreManager scoreManager = GetComponent<ScoreManager>();
        newHigh = GameObject.Find ("High Score").GetComponent<Text> ();

        hScorePreText = GameObject.Find("High Score Pre");
        hScoreText = GameObject.Find("High Score");

        playAgainBtn.onClick.AddListener (() => PlayAgain());
        backBtn.onClick.AddListener (() => BackToMenu ());

        scoreText = GameObject.Find("Score Text");
        finalScore = GameObject.Find("Final Score").GetComponent<Text> ();
        finalHighScore = GameObject.Find("Final High Score").GetComponent<Text> ();

        gameOverpanel.SetActive (false);
        panelNewHigh.SetActive (false);
    }

    public void PlayAgain () {
        SceneManager.LoadScene ("GamePlay");
    }


    public void BackToMenu ()
    {
        SceneManager.LoadScene ("MainMenu");
    }


    // When button highScoreButtonOK is clicked it will show the GameOverPanel again
    public void HighScoreButtonPopupClicked ()
    {

        hScorePreText.SetActive (false);
        hScoreText.SetActive (false);
        panelNewHigh.SetActive (false);

        gameOverpanel.SetActive (true);

        finalScore.text = "Score: " + "" + ScoreManager.instance.GetScore ();
        finalHighScore.text = "High Score: " + "" + ScoreManager.instance.GetHighScore ();

        gameOverAnim.Play ("FadeIn");


    }

}

Yeah, actually looks about right to me. Try adding this in line 170 of your player jump script:

Debug.Log("Entered " + target.name + ", last platform was " + lastPlatformJumpedOn.name);

And maybe also add a Debug.Log in IncrementScore().

1 Like

From your suggested Debug.Log at line 170 this is what the console gives me after reaching the first platform:

NullReferenceException: Object reference not set to an instance of an object
PlayerJumpScript3D.OnTriggerEnter (UnityEngine.Collider target) (at Assets/Scripts/Player Scripts/PlayerJumpScript3D.cs:170)

Btw, this is the GameManager for instantiate platforms etc.:

using UnityEngine;
using System.Collections;

public class GameManager : MonoBehaviour {



    public static GameManager instance;

    [SerializeField]
    private GameObject playerM3D;

    [SerializeField]
    private GameObject DirtPilar3d;

    private float minX = -2.5f, maxX = 2.5f, minY = -4.7f, maxY = -3.7f;


    private bool lerpCamera;
    private float lerpTime = 3.5f;
    private float lerpX;


    //CoinFlight spawn variables
    public static bool spawnCoin = true;
    private int oldScore;

    [SerializeField]
    private GameObject coinPrefab;



    void Awake ()
    {
        MakeInstance ();
        CreateInitialPlatforms ();
    }


    void Update ()
    {
        CreateCoinFlight();

        if (lerpCamera) {
            LerpTheCamera();
        }
    }

    void MakeInstance ()
    {
        if(instance == null)
            instance = this;
    }

    void CreateInitialPlatforms ()
    {
        Vector3 temp = new Vector3 (Random.Range(minX, minX + 1.2f), Random.Range(minY, maxY), 0);

        Instantiate (DirtPilar3d, temp, Quaternion.identity);

        temp.y += 2f;

        Instantiate (playerM3D, temp, Quaternion.identity);

        temp = new Vector3 (Random.Range(maxX, maxX - 1.2f), Random.Range(minY, maxY), 0);

        Instantiate (DirtPilar3d, temp, Quaternion.identity);
    }






    // Create Initial Platforms



    void LerpTheCamera ()
    {
        float x = Camera.main.transform.position.x;

        x = Mathf.Lerp(x, lerpX, lerpTime * Time.deltaTime);

        Camera.main.transform.position = new Vector3 (x, Camera.main.transform.position.y, Camera.main.transform.position.z);

        if(Camera.main.transform.position.x >= (lerpX - 0.07f)) {
            lerpCamera = false;
        }
    }

    public void CreateNewPlatformAndLerp (float lerpPosition)
    {
        CreateNewPlatform ();

        lerpX = lerpPosition + maxX;
        lerpCamera = true;

    }

    void CreateNewPlatform ()
    {
        float cameraX = Camera.main.transform.position.x;

        float newMaxX = (maxX * 2) + cameraX;

        Instantiate (DirtPilar3d, new Vector3(Random.Range(newMaxX, newMaxX - 1.2f), Random.Range(maxY, maxY - 1.2f), 0), Quaternion.identity);
   
    }


    void CreateCoinFlight ()
    {

        float cameraCoinX = Camera.main.transform.position.x;

        float newCoinMaxX = (maxX * 2) + cameraCoinX;

        if (spawnCoin == true) {

            if (ScoreManager.instance.GetScore () == oldScore + 2) {
                Instantiate (coinPrefab, new Vector3(cameraCoinX + 16f, 0, 0), Quaternion.identity);
                oldScore = ScoreManager.instance.GetScore();

                Debug.Log ("GetScore() is now: " + ScoreManager.instance.GetScore() + " -- And oldScore is now: " + oldScore);
            }
        }

    }

} // GameManager

Oops — you’re getting a null reference exception, probably because lastPlatformJumpedOn is null. Just remove “.name” (in both places) from that line and give it another try.

1 Like

After jumping on the first platform the console gives me:

Entered DirtPilar3d(Clone) (UnityEngine.BoxCollider), last platform was
UnityEngine.Debug:Log(Object)
PlayerJumpScript3D:OnTriggerEnter(Collider) (at Assets/Scripts/Player Scripts/PlayerJumpScript3D.cs:170)

If I jump once more is gives me this:

Entered DirtPilar3d(Clone) (UnityEngine.BoxCollider), last platform was DirtPilar3d(Clone) (UnityEngine.BoxCollider)
UnityEngine.Debug:Log(Object)
PlayerJumpScript3D:OnTriggerEnter(Collider) (at Assets/Scripts/Player Scripts/PlayerJumpScript3D.cs:170)

So lastPlatformJumpedOn is null for the very first platform.

Yes, that’s what you would expect, right?

So… what is the problem, again? The score is getting double-incremented on the first platform? Did you learn anything from the Debug.Logs in the IncrementScore method?

1 Like

Yes the score gets double-incremented on the first platform. It looks to me that the first platform isnt assigned as lastPlatformJumpedOn in any way. So the logic responsible for checking if it is a platform where we allready jumped on can’t be verified (if i’m correct). But why? :slight_smile:

No, at the start of the game there isn’t a last platform jumped on. So it’s null. That’s what we would expect.

After you jump on a platform, then you assign lastPlatformJumpedOn = target on line 172. All good.

So focus on the Debug.Logs that come from IncrementScore. They will tell you exactly what code is calling it.

1 Like

I put a debug for score in IncrementScore() in the ScoreManager script:
After the first jump it gives me this:

Score called: 1
UnityEngine.Debug:Log(Object)
ScoreManager:IncrementScore() (at Assets/Scripts/ScoreManager/ScoreManager.cs:64)
PlayerJumpScript3D:OnTriggerEnter(Collider) (at Assets/Scripts/Player Scripts/PlayerJumpScript3D.cs:176)

And after the second jump it gives me this (the same but incremented with 1 as expected:

Score called: 2
UnityEngine.Debug:Log(Object)
ScoreManager:IncrementScore() (at Assets/Scripts/ScoreManager/ScoreManager.cs:64)
PlayerJumpScript3D:OnTriggerEnter(Collider) (at Assets/Scripts/Player Scripts/PlayerJumpScript3D.cs:176)

Any more suggestions? Sorry for being so noobish, still learning.

OK, so if I understand correctly, you want it to increment only once even if you jump on the same platform twice. But it’s actually incrementing again on the second jump, which isn’t desired.

OK, part of the problem in debugging this is that all of your platforms have the same name. So when the console says

Entered DirtPilar3d(Clone) (UnityEngine.BoxCollider), last platform was DirtPilar3d(Clone) (UnityEngine.BoxCollider)

…this isn’t very helpful. We know these must be different DirtPilar3d’s, because the line just before this Debug.Log is an if statement requiring that they be different. But we can’t really tell what’s what because they’re all named “DirtPilar3d(Clone)”.

So, one quick test would be to pause the game before you land on the first platform, and in the Hierarchy window, rename each of your platforms to something unique. Somewhat better would be to give each platform a unique name as you instantiate them, with code something like this:

  noob = Instantiate(platformPrefab);
  platformCount++;   // (where platformCount is a static or member variable)
  noob.name = "DirtPilar #" + platformCount;

Then run your tests again. I think you will discover that on the second jump, it’s actually hitting a different platform from the first jump.

And how can that be, you ask? I think you have two platforms at exactly the same position.

That’s my guess, anyway! But giving them unique names will help in any case.

Hello, you can check the theory above by outputting

target.GetInstanceID() instead of target.name

This will give you the unity unique id for this object, hope this helps find the problem.

1 Like