how can i increase a number inside OnTriggerEnter - c#

so i'm trying to increase my score every time i hit a wall (IsTrigger) but when i try to increase it, it doesn't work and still 100
so this is the code im having problem with
public Text scoreText;
public int score = 0;
void Start()
{
scoreText.text = score.ToString();
}
// Add Some Score To The Text When The Player Hit The CheckPoint
void OnTriggerEnter(Collider collider)
{
if (collider.name == "Player")
{
score += 100;
scoreText.text = score.ToString();
Debug.Log(score);
}
}

When doing the trigger/collision test, make sure you add one
Debug.Log() outside of the condition check. In your case,
void OnTriggerEnter(Collider collider)
{
if (collider.name == "Player")
{
score += 100;
scoreText.text = score.ToString();
Debug.Log(score);
}
Debug.Log("Just want make sure it indeed triggered.");
}
In most case, other than the issue with the code, it is highly possible the Rigidbody component is not added to the GO.
Another part which I am not sure since I am not using Unity for quite a long time now. You can move the UI text update code outside of the trigger if you want.

You need to update the text after changing the value, in your case you have to update "scoreText" according to the new "score" value. The simple way to do it is like that:
public Text scoreText;
public int score = 0;
void Start()
{
scoreText.text = score.ToString();
}
// Add Some Score To The Text When The Player Hit The CheckPoint
void OnTriggerEnter(Collider collider)
{
if (collider.name == "Player")
{
score += 100;
scoreText.text = score.ToString();
Debug.Log(score);
}
}
It is better to have a method called "ChangeScore" which includes updating the "score" value and updating the "scoreText" at the same time. It is better to do so since you might forget to update the text in other cases if you have to change the score somewhere else.
Example:
[Tooltip("The player's initial score.")]
[SerializeField] private int initScore = 0;
// Serialized since you have to set the reference for it.
[SerializeField] private Text scoreText;
private int score = 0;
void Start()
{
ChangeScore(initScore);
}
// Method used to change the current player's score and update the text.
void ChangeScore(int changeValue)
{
this.score += changeValue;
scoreText.text = score.ToString();
}
// Add Some Score To The Text When The Player Hit The CheckPoint
void OnTriggerEnter(Collider collider)
{
if (collider.gameObject.name == "Player")
{
ChangeScore(100);
Debug.Log(score);
}
}
Another side note: I wouldn't use tags or names while checking colliding, its better to check if the colliding object got the PlayerController script
if(collider.GetComponent<PlayerController>())
instead of
if (collider.gameObject.name == "Player")

i fixed it i put the code on the Player script not on the CheckPoint script
void OnTriggerEnter(Collider collider)
{
if (collider.tag == "ScoreCheckPoint")
{
score += 100;
scoreText.text = score.ToString();
Debug.Log(score);
}
}

Related

How to switch between the OnTriggerExit/Enter logic depending on the situation?

The script is attached to two gameobjects.
One it's colliding area the collider is big enough so when the game start the player is already inside the collider area and then when he exit the area everything is working fine.
The problem is when I attached the object to another gameobject with collider but this time the collider s smaller and he is inside the bigger collider so now the player is entering the smaller collider and not first time exiting. but I want in both case to make the same effect.
If the player exit the collider he slow down wait then turn around and move inside back.
The same I want to make when the player getting closer to the fire flames slow down wait turn around and move back in it's just with the flames the player entering the collider area and then exit while in the bigger collider he first exit then enter.
Screenshot of the two colliders areas. The small one on the left is the one the player entering first and not exiting. The game start when the player is in the bigger collider area.
And the script :
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using UnityStandardAssets.Characters.ThirdPerson;
public class DistanceCheck : MonoBehaviour
{
public Transform targetToRotateTowards;
public Transform colliderArea;
public float lerpDuration;
public float rotationSpeed;
[TextArea(1, 2)]
public string textToShow;
public GameObject descriptionTextImage;
public TextMeshProUGUI text;
public ThirdPersonUserControl thirdPersonUserControl;
private Animator anim;
private float timeElapsed = 0;
private float startValue = 1;
private float endValue = 0;
private float valueToLerp = 0;
private bool startRotating = false;
private bool slowOnBack = true;
private bool exited = false;
private Vector3 exitPosition;
private float distance;
void Start()
{
anim = transform.GetComponent<Animator>();
}
private void FixedUpdate()
{
if (startRotating)
{
transform.rotation = Quaternion.RotateTowards(transform.rotation,
Quaternion.LookRotation(targetToRotateTowards.position - transform.position),
rotationSpeed * Time.deltaTime);
}
if (exitPosition != new Vector3(0, 0, 0) && slowOnBack)
{
distance = Vector3.Distance(transform.position, exitPosition);
}
if (distance > 5 && slowOnBack)
{
slowOnBack = false;
StartCoroutine(SlowDown());
}
}
private void OnTriggerExit(Collider other)
{
if (other.name == colliderArea.name)
{
exited = true;
slowOnBack = true;
exitPosition = transform.position;
thirdPersonUserControl.enabled = false;
descriptionTextImage.SetActive(true);
text.text = textToShow;
StartCoroutine(SlowDown());
}
}
private void OnTriggerEnter(Collider other)
{
if (other.name == colliderArea.name)
{
exited = false;
startRotating = false;
text.text = "";
descriptionTextImage.SetActive(false);
}
}
IEnumerator SlowDown()
{
timeElapsed = 0;
while (timeElapsed < lerpDuration)
{
valueToLerp = Mathf.Lerp(startValue, endValue, timeElapsed / lerpDuration);
anim.SetFloat("Forward", valueToLerp);
timeElapsed += Time.deltaTime;
yield return null;
}
if (exited)
{
yield return new WaitForSeconds(3f);
startRotating = true;
StartCoroutine(SpeedUp());
}
if (slowOnBack == false)
{
thirdPersonUserControl.enabled = true;
}
}
IEnumerator SpeedUp()
{
timeElapsed = 0;
while (timeElapsed < lerpDuration)
{
valueToLerp = Mathf.Lerp(endValue, startValue, timeElapsed / lerpDuration);
anim.SetFloat("Forward", valueToLerp);
timeElapsed += Time.deltaTime;
yield return null;
}
}
}
Two problems I'm facing right now :
The smaller collider the player enter it then exit and the bigger collider the player exit it then enter so I need to change somehow the OnTriggerExit/Enter behavior logic in the script. but how to make the logic ?
Maybe it's better to make the script to be on the player object only and make it some how generic so I can drag to it many colliders and to make the effect in each one of the colliders the problem is how to make a text field for each collider area ? Now because I attach the script to each collider object I have one colliderArea variable but if I want to make the script only attached to the player I need to change the colliderArea variable to a List<Transform> collidersAreas and then how to create a text field/area to each collider area in the List ?
I think I would do this by creating two tags, NoExit and NoEntry. Once the tags are created you can set the tag on the GameObjects that hold your colliders. Then you can check for tags in the OnTriggerEnter and OnTriggerExit and act accordingly.
I can't tell for sure which functionality you've got written is for which case, or if it's both - everything looks muddled. Ultimately what you should be going for is a function like RepositionPlayer, that moves them back to before they're violating the no entry or no exit rules, and then some kind of OnPlayerRepositioned event that restores their control.
I'll leave it up to you to split out your functionality, but in general I'd look to do something like the following:
private void OnTriggerExit(Collider other)
{
if (other.tag == "NoExit")
{
RepositionPlayer();
}
else if(other.tag == "NoEntry")
{
OnPlayerRepositioned();
}
}
private void OnTriggerEnter(Collider other)
{
if (other.tag == "NoExit")
{
OnPlayerRepositioned();
}
else if(other.tag == "NoEntry")
{
RepositionPlayer();
}
}
And again here it's not clear to me what you're trying to do to reposition the player, but it looks like it's something like:
private void RepositionPlayer()
{
// Stuff that needs to happen to reposition the player
exited = true;
slowOnBack = true;
exitPosition = transform.position;
thirdPersonUserControl.enabled = false;
descriptionTextImage.SetActive(true);
text.text = textToShow;
StartCoroutine(SlowDown());
}
private void OnPlayerRepositioned()
{
// stuff you need to do to clear the "repositioning" status
exited = false;
startRotating = false;
text.text = "";
descriptionTextImage.SetActive(false);
}
Splitting up the logic like this makes it easier to both read and maintain.

How to assign a value from another script variable?

I accessing another script but her value is by default null.
I want to increase a score when colliding with the obstacle(+5).
Code:
playerscore.cs
public static class playerscore
{
public static int Score = 0; //static variable
}
TouchControll.cs
public Text scoretext;
void Awake()
{
//when I game quit and reenter the game then display the last score
PlayerPrefs.GetInt("score", playerscore.Score);
//this data on my ram not in harddisk
playerscore.Score = PlayerPrefs.GetInt("score", playerscore.Score);
//last score text update when I Reenter the game
scoretext.text = PlayerPrefs.GetInt("score").ToString();
print(scoretext.text);
//pass a score one scene to another scene
PlayerPrefs.SetInt("score", playerscore.Score);
scoretext.text = ("" + playerscore.Score);
PlayerPrefs.SetInt("score", playerscore.Score);
}
void OnCollisionEnter2D(Collision2D col)
{
//Debug.Log("oncollisionenter");
//when my player reaches the finish line then the score add=100; //work fine
if (col.gameObject.tag == "successfinishtag")
{
playerscore.Score += 100;
PlayerPrefs.SetInt("score", playerscore.Score);
scoretext.text = ("" + playerscore.Score);
//Debug.Log("scoreadd:" + playerscore.Score);
}
}
problem is here
I want the when my player collided with the obstacle then increment my score(+5) but the issue is not increasing my score
obstacle.cs
int incrementscore = 5;
TouchControll touchcontroll;
void Start()
{
GetComponent<TouchControll>();
}
//here player colliding with the obstacle
void OnTriggerEnter2D(Collider2D other)
{
foreach (Transform child in transform)
{
//Debug.Log("Inside foreach");
if (child.tag == "obstacleobject")
{
Animator anim = gameObject.GetComponent<Animator>();
anim.Play("animone");
}
}
playerscore.Score = PlayerPrefs.GetInt("score", playerscore.Score);
print(playerscore.Score);
Debug.Log(touchcontroll); //null
if (touchcontroll!= null)//null by default if(null != null) condition false
{
IncrementScore();
touchcontroll.scoretext.text = playerscore.Score.ToString();
}
}
void IncrementScore()
{
//Debug.Log("Inside Increment score");
playerscore.Score = playerscore.Score + incrementscore;
PlayerPrefs.GetInt("score", playerscore.Score);
//print(PlayerPrefs.GetInt("score", playerscore.Score));
PlayerPrefs.SetInt("score", playerscore.Score);
touchcontroll.scoretext.text = playerscore.Score.ToString();
}
I want the when my player collided with the obstacle then increment my score(+5) but the issue is not increasing my score how to solve the problem plz help.
How to solve this problem??
You're not assigning the result of GetComponent back to anything. Change obstacle.cs:
TouchControll touchcontroll;
void Start()
{
touchcontroll = GetComponent<TouchControll>();
}
However, GetComponent() only returns something if there is an instance of whatever object attached to the current game object. Are obstacle.cs and TouchControll.cs both attached to the current GameObject?
If not GetComponent is not going to work, use FindObjectOfType() instead:
void Start()
{
touchcontroll = FindObjectOfType<TouchControll>();
}
Here are the relevant pages from Unity scripting API for more info:
https://docs.unity3d.com/ScriptReference/GameObject.GetComponent.html
https://docs.unity3d.com/ScriptReference/Object.FindObjectOfType.html
I have used in my game this scenario, where Player collide with coin and it increment coin value smoothly in my case. And I have also noticed there is simple difference with your script from me. U have to used FindObjectOfType<> and also have to called public int incrementscore = 5; Where U didn't use any access modifier. Below also include my code, U can take a look and get the idea. Hopefully this will work for U. thanks
public class CoinScript : MonoBehaviour
{
public int coinValue;
private LevelManager gameLevelManager;
// Start is called before the first frame update
void Start()
{
gameLevelManager = FindObjectOfType<LevelManager>();
}
// Update is called once per frame
void Update()
{
}
void OnTriggerEnter2D(Collider2D other) {
Debug.Log("Triggered");
if (other.tag == "Player")
{
gameLevelManager.AddCoins(coinValue);
Destroy(gameObject);
}
}
}
//In LevelManager scripts
public void AddCoins(int numberOfCoins)
{
coins += numberOfCoins;
coinText.text = "Coins : " + coins;
}
Be simply , no use PlayerPrefs to other place
public static class playerscore
{
public static int Score
{
get { return PlayerPrefs.GetInt("score", 0);}
set { PlayerPrefs.SetInt("score", value); }
}
}

How can I get the Highscore to Update and Stay the same until beaten

Google Drive of Project
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class GameControl : MonoBehaviour
{
public static GameControl instance; //A reference to our game control script so we can access it statically.
public Text scoreText; //A reference to the UI text component that displays the player's score.
public Text highscoreText; //A reference to the UI text component that displays the player's highscore.
public GameObject gameOvertext; //A reference to the object that displays the text which appears when the player dies.
private int highScore = 0; //The games highscore
private int score = 0; //The player's score.
public bool gameOver = false; //Is the game over?
public float scrollSpeed = -1.5f;
void Start()
{
highScore = PlayerPrefs.GetInt("HighScore");
highscoreText.text = "HighScore: " + highScore.ToString();
}
void Awake()
{
//If we don't currently have a game control set this one to be it otherwise destroy this one
if (instance == null)
instance = this;
else if(instance != this)
Destroy (gameObject);
}
void Update()
{
//If the game is over and the player has pressed some input
if (gameOver && Input.GetMouseButtonDown(0))
{
//reload the current scene.
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
}
public void BirdScored()
{
//The bird can't score if the game is over.
if (gameOver)
return;
//If the game is not over, increase the score and set highscore
score++;
//adjust the score text.
scoreText.text = "Score: " + score.ToString();
// Check if this score beats the highscore
//if (score > highScore)
//{
// highScore = score;
// PlayerPrefs.SetInt("HighScore", highScore);
//}
//highscoreText.text = "HighScore: " + highScore.ToString();
}
public void BirdDied()
{
//Activate the game over text.
gameOvertext.SetActive(true);
//The game is over.
gameOver = true;
// Check if this score beats the highscore
if (score > highScore)
{
highScore = score;
PlayerPrefs.SetInt("HighScore", highScore);
}
highscoreText.text = "HighScore: " + highScore.ToString();
}
}
I am looking to get a highscore to display, and update when the player dies. The base score is working correctly, but I can't get the highscore to update. If someone could please help me with this it would be much appreciated. If you need to see other code, let me know what you think and hot to go about it.
You need to separate your Game-State logic from your Out-Of-Game State logic.
For example, one of my projects has a static1 class to hold all of the statistics2 I'm interested in without being reliant on a MonoBehaviour component. This statistics class also handles the serialization and deserialization for the statistics, although it doesn't have to.
I also created a special HighScore class to handle dealing with values that can be reset, but that I still want to know what the "best" value ever stored was.
Not going to say that my code is the best, just these are the principles you need to follow.
1 Static fields also let me access these properties from anywhere.
2 All of these are still game-state values for this particular project, but they will still persist if I were to change scenes
Doing something along these lines should work perfectly.
public void BirdDied()
{
//Activate the game over text.
gameOvertext.SetActive(true);
//The game is over.
gameOver = true;
// Check if this score beats the highscore
if (score > highScore)
{
highScore = score;
PlayerPrefs.SetInt("HighScore", highScore);
}
highscoreText.text = "HighScore: " + highScore.ToString();
}
Also be sure to get the highscore and update the highScoreText when you start the game
void Start()
{
highScore = PlayerPrefs.GetInt("HighScore");
highscoreText.text = "HighScore: " + highScore.ToString();
}
EDIT:
Updated answer
EDIT
After looking at your project, i notice the HighscoreText is not set in the inspector, see image
Simply drag HighScoreText (located under Canvas in your Hierarchy view) to the Highscore field there in the inspector.

Unity variable needs to work unfied in the same script on multiple gameobjects

I have a script attached to 4 gameobjects which has a trigger and adds score if the collider passes the trigger correctly. It does update the score correctly but updates 4 separate scores ( 4 instances of the score variable. I need to update the score unifiedly for all of the 4 gameobjects.
Here is my code
bool isDead;
private int score;
// Use this for initialization
void Start () {
isDead = false;
score =0;
}
void OnTriggerEnter2D (Collider2D other){
if (other.gameObject.name.ToLower () == this.name) {
Debug.Log ("you won");
score = score+1;
GameObject.Find("ScoreText").GetComponent<Text>().text = score.ToString();
}
else {
Debug.Log ("you lose");
isDead = true;
Application.LoadLevel(Application.loadedLevel);
}
Destroy (other.gameObject);
}
You have 2 options:
Make field score static.
Create new class for managing the score.

Counter to victory in Unity

have been having a problem while working in Unity. I simply want to increase a score every time a collision is made, but my code just isn't helping. I know it sounds basic but I've been looking around in the site for quite some time now and I haven't found an answer yet.
Here's the script:
I have already checked and the "VictoryScreen" is already made and built.
public class PaintScriptGreen : MonoBehaviour {
public GameObject CylGreen;
private int score = 0;
private Vector3 tempPos;
private Quaternion tempRot;
private GameObject tempCyl;
void Awake ()
{
}
public void AddScore (int scoreValue)
{
score += scoreValue;
}
void OnTriggerEnter(Collider col)
{
if (col.gameObject.tag == "Cylinder" && col.gameObject.tag != "TreeHolder")
{
tempPos = col.gameObject.transform.position;
tempRot = col.gameObject.transform.rotation;
Destroy (col.gameObject);
tempCyl = Instantiate(CylGreen, tempPos, tempRot) as GameObject;
AddScore (1);
if (score >= 4)
{
Application.LoadLevel ("VictoryScreen");
}
}
if ((col.gameObject.tag != "Player")&&(col.gameObject.tag != "PlayPart"))
{
// destroy self bullet
Destroy (this.gameObject);
}
}
if ((col.gameObject.tag != "Player")&&(col.gameObject.tag != "PlayPart"))
{
// destroy self bullet
Destroy (this.gameObject);
}
This is probably the culprit. You're destroying "this" anytime the above conditions aren't true. Is this script on the bullet? If so, you'll need to move the scoring mechanism to an object that isn't getting destroyed OR make it a static variable. I don't like static variables, but it is a possible solution.

Categories