Change GameObject Component on InitializeOnLoad - c#

I created script that i want to use as main script when my game launch. Now i want to access specific button text via that script and change it's text. I have problem because my text is not changing. Here is what i was trying:
static main()
{
Debug.Log("Up and running");
GameObject devButtonText = GameObject.Find("devButtonText");
Text text = devButtonText.GetComponent<Text>();
text.text = "Test";
}
Button is devButton and text is devButtonText
full script
using UnityEngine;
using UnityEditor;
using System.Collections;
using UnityEngine.UI;
[InitializeOnLoad]
public class main : MonoBehaviour {
static main()
{
Debug.Log("Up and running");
GameObject devButton = GameObject.Find("devButton");
Text text = devButton.GetComponentInChildren<Text>();
text.text = "Test";
}
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
}

I created script that i want to use as main script when my game launch.
The InitializeOnLoad attribute must be used to run a function when the Unity Editor starts, not the game. Every editor script won't run when you compile your game. Unity documentation
Sometimes, it is useful to be able to run some editor script code in a project as soon as Unity launches without requiring action from the user.
Instead, create an Empty GameObject and attach the following script :
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class ChangeText : MonoBehaviour
{
private void Awake()
{
GameObject devButton = GameObject.Find("devButton");
Text text = devButton.GetComponentInChildren<Text>();
text.text = "Test";
}
}
Even better :
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class ChangeText : MonoBehaviour
{
// Drag & Drop the desired Text component here
public Text TextToChange ;
// Write the new content of the Text component
public string NewText ;
private void Awake()
{
TextToChange.text = NewText;
}
}
The script will automatically be called when the scene starts.

When Initializing a MonoBehaviour
You should use Start, Awake or OnEnable.
You shouldn't use constructor, static constructor or field initialization (like public GameObject go = GameObject.Find("devButton");)
This should work:
using UnityEngine;
using UnityEditor;
using System.Collections;
using UnityEngine.UI;
public class main : MonoBehaviour {
void Awake () {
Debug.Log("Up and running");
GameObject devButton = GameObject.Find("devButton");
Text text = devButton.GetComponentInChildren<Text>();
text.text = "Test";
}
}
Edit
Given the name main I guess this is the starting point of your project so if your script is not attached to any game object then Start, Awake or OnEnable would not be called. In this case you should attach it to a game object and change the unity script execution order and bring the script to the earliest point.

Related

How to make a kills counter in Unity2D with C#?

I want to make a kill counter but for some reason it's not working.
Here is what i did
I create a new empty GameObject Game Manager And add a new component Score, Here is the code:
using UnityEngine;
using UnityEngine.UI;
public class Score : MonoBehaviour
{
public Text kills_UI;
private int Kills_Counts; //How many kills
public void Increase_score() //This will update the UI text to the current kills count
{
Kills_Counts++;
kills_UI.text = Kills_Counts.ToString();
}
}
After that i called this function in the enemy script BulletColision after he is killed :
using UnityEngine;
public class BulletColision : MonoBehaviour
{
Score kills_score;
void Start()
{
kills_score = GetComponent<Score>();
}
public void OnCollisionEnter2D(Collision2D others) //When a bullet collide with en enemy prefab
{
if (others.gameObject.CompareTag("Enemy"))
{
Destroy(gameObject); //Destroy the enemy
kills_score.Increase_score(); //Calling the function from 'GameManager'
Destroy(others.gameObject); //Destroy the bullet
}
}
}
The problem is with your kills_score reference, if you do:
kills_score = GetComponent<Score>();
You are searching for Score component on your BulletCollision, which I guess do not have Score component since it's a bullet.
Quick fix:
Attach to your GameManager a new TAG like "GameManager", then use
kills_score = GameObject.FindWithTag("GameManager").GetComponent<Score>();
instead of
kills_score = GetComponent<Score>();
To quickly validate this make your score variable public and see in your editor if the reference is correctly set.
Also and as a side note, try to maintain your variables with lowerCamelCame nomenclature, meaning that starts with lower case.

I decided to keep both scenes loaded in the hierarchy since it's easier to reference variables between them. How can I restart then a new game?

In the Hierarchy I have two scenes when running the game first time.
The scene that contains all the gameplay objects all the objects are disabled.
The main menu scene objects are enabled.
Now this script is attached to the main menu and the function PlayGame is being called from a Play button On Click event :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class MainMenu : MonoBehaviour
{
public static bool sceneLoaded = false;
public void PlayGame()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1);
SceneManager.LoadScene(0, LoadSceneMode.Additive);
SceneManager.sceneLoaded += SceneManager_sceneLoaded;
}
private void SceneManager_sceneLoaded(Scene arg0, LoadSceneMode arg1)
{
sceneLoaded = true;
}
public void QuitGame()
{
Application.Quit();
}
}
And this script is attached to one active gameobject on the gameplay scene and all it does is to check if I'm in the main menu or not and then to decide if to setactive or not all the gameplay objects :
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
public class ActiveScene : MonoBehaviour
{
public GameObject gameData;
// Update is called once per frame
void Update()
{
if(MainMenu.sceneLoaded == true)
{
gameData.SetActive(true);
MainMenu.sceneLoaded = false;
}
if(BackToMainMenu.loadedMainMenuScene == true)
{
gameData.SetActive(false);
BackToMainMenu.loadedMainMenuScene = false;
}
}
}
This is a screenshot of the Hierarchy :
You can see that the GameObject name Active Scene in the top scene is enabled gameobject while all the other gameobjects are disabled. On this Active Scene I attached the script ActiveScene.
This way when I click the Play button a new game start and when I hit the escape key it's getting back to the main menu.
The problem is when I hit the escape key and then click the Play button again it will keep load to the Hierarchy the main menu scene over and over again.
And this is after few times I hit the escape key and then started a new game over again by clicking the Play button :
This is the script to return to the main menu using the escape key. The script is attached to the Game Manager object in the game scene :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class BackToMainMenu : MonoBehaviour
{
public static bool loadedMainMenuScene = false;
private void Update()
{
if (Input.GetKeyDown(KeyCode.Escape))
{
loadedMainMenuScene = true;
}
}
}
I want to keep both scenes in the Hierarchy all the time since it's easier then to reference between variables in both scenes.
When both scenes in the Hierarchy it's also easier to restart a new game by re loading the gameplay scene.
The problem is when restarting a new game I have to set the flag bool sceneLoaded to false but then next time since it's false it will load the main menu scene to the Hierarchy over and over again.

TextMeshPro Text not changing, console is giving rapid errors

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
public class Num : MonoBehaviour
{
private int score;
public TextMeshPro TMP;
void Start()
{
TMP = GetComponent<TextMeshPro>();
score = 0;
}
void Update()
{
TMP.text = score.ToString();
score++;
}
}
The text is not changing, and I dont know why. The error in the console is "NullReferenceException: Object reference not set to an instance of an object
Num.Update () (at Assets/Scripts/Num.cs:19)"
The error is that your script isn't finding a TextMeshPro sibling component. If you're using the UI version, what you actually want is to find a TextMeshProUGUI
I'm guessing it's a text ui from what you said. If it is a text UI and Textmeshpro, then use TMPro.TextMeshProUGUI varName;

How can I link my C# scripts so that item count influences score in my Unity game?

I am trying to make it so that collecting an item will cause the score to increase. After perusing the documentation for Unity, I have written the following C# scripts. CollectableItem.cs is attached to the items in the game. ScoreBoard.cs is attached to the UI display. I'm getting the error message, "'ScoreBoard.score' is inaccessible due to its protection level." If I make the variables in ScoreBoard.cs public, I get a different error message: "An object reference is required for the non-static field, method, or property 'ScoreBoard.score'."
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CollectibleItem : MonoBehaviour {
[SerializeField] private string itemName;
[SerializeField] private int pointsValue;
void OnTriggerEnter(Collider other) {
Managers.Inventory.AddItem(itemName);
Destroy(this.gameObject);
ScoreBoard.score += pointsValue;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class ScoreBoard : MonoBehaviour {
[SerializeField] private Text scoreLabel;
private int score;
void Start () {
score = 0;
}
void Update () {
scoreLabel.text = "Score: " + score.ToString();
}
}
UPDATE: Here is Take 2 on CollectibleItem.cs. Now I'm being informed that "board" does not exist in the current context...
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CollectibleItem : MonoBehaviour {
[SerializeField] private string itemName;
[SerializeField] private int pointsValue;
void Start() {
var uiObject = GameObject.Find("Timer");
ScoreBoard board = uiObject.GetComponent<ScoreBoard>();
}
void OnTriggerEnter(Collider other) {
Managers.Inventory.AddItem(itemName);
Destroy(this.gameObject);
board.score += pointsValue;
}
}
This is not able to work because you make a so-called static access to the ScoreBoard class. That means you try to change the variable of the ScoreBoard class. What you want to do is to change the variable on one of the instances. When the UI Object is created, an instance of the class of your ScoreBoard-Script is created. Like every item has its own instance of CollectibleItem.
You can get the instance in this way:
var uiObject = GameObject.Find("Name of UI Object");
ScoreBoard board = uiObject.GetComponent<ScoreBoard>();
You can do this in Start() and save the ScoreBoard variable in the script where your other private variables reside and use it later in the trigger, or you can do this directly in your Trigger function and directly set the score:
board.score += pointsValue;
EDIT: You have to place the declaration of Scoreboard inside the class:
ScoreBoard board;
void Start ()
...
Or put the code from start to OnTriggerEnter.

scoreText.text not working in unity

"Score:" is not being displayed on unity ide.i have tried a lot and nothing seems to be working and not getting output as expected.Thankyou.Sorry for bad English.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class uiManager : MonoBehaviour {
public Text scoreText;
int score;
// Use this for initialization
void Start () {
score = 0;
}
void score_view()
{
score = move.score;
Debug.Log("uiManager Score:"+score);
scoreText.text = "Score:"+score;
}
// Update is called once per frame
void Update ()
{
score_view();
}
}
Update is called once per frame, if your GameObject is active, and your script is Enabled.
Moreover, your game should be running.
https://docs.unity3d.com/ScriptReference/MonoBehaviour.Update.html
You can check this states with these variables:
this.gameObject.activeSelf
this.enabled

Categories