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.
// 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?
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.
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.
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");
}
}
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.:
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.
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?
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?
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.