I have problem because I can't read a static value added to Uptade() and use it.
Rock
[Header("Points")]
public TextMeshProUGUI points;
public static int point;
private void Start()
{
points = GetComponent<TextMeshProUGUI>();
}
void Update()
{
Move();
}
void Move()
{
point += 1;
Debug.Log(point);
}
Points
[Header("Points")]
public TextMeshProUGUI points;
public Rock countPoint;
void Start()
{
}
void Update()
{
Debug.Log("points" + countPoint.point);
}
I want to see this point in class points. If i will delete static then debug showing just 0.
Can you show me how to do it in correct way in full example ? or reedit my code.
You're trying to access a static member by using an object reference.
Instead of using an instance of the object:
Debug.Log("points" + countPoint.point);
You should be using using the class to call the field:
Debug.Log("points" + Rock.point);
Static variables/functions can directly be accessed by class name.
So, Rock.point would do.
Related
I'm trying to make a save level system and I keep on getting this error.
UnityException: GetActiveScene is not allowed to be called from a MonoBehaviour constructor
I've tried searching this up, but there were no results. Here is the code I used:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class EndLevel : MonoBehaviour
{
public PlayerMovement pm;
public GameObject completeLevelUI;
// Start is called before the first frame update
void Start() {
}
// Update is called once per frame
void Update() {
}
void OnCollisionEnter (Collision collisionInfo) {
if(collisionInfo.collider.tag == "Finish") {
Debug.Log("You beat the level!");
pm.enabled = false;
completeLevelUI.SetActive(true);
Level = Level + 1;
PlayerPrefs.SetFloat("Level", Level);
Debug.Log("Saved");
Invoke("NextLevel", 3);
}
}
public void NextLevel() {
SceneManager.LoadScene (SceneManager
.GetActiveScene().buildIndex + 1);
}
}
Any Ideas about the error?
You have to get the current active Scene in the Start() or Awake() methods.
Example with Start():
private int sceneNumber;
private void Start() {
sceneNumber = SceneManager.GetActiveScene().buildIndex;
}
As an alternative solution you could also use a Lazzy Getter. Which means that the value won't get stale between when the scene loads and when you use it, which might matter with other pieces of data.
Example with Lazzy Getter:
private int sceneNumber {
get {
return SceneManager.GetActiveScene().buildIndex;
}
}
When you use either of those solutions, you can now simply call scenenumber + 1 in your SceneManager.Load() function call instead.
Additionally you need to ensure that you are calling an IEnumerator, instead of Invoking the Function call. If you want to delay the scene loading.
Function Call:
private void OnCollisionEnter (Collision collisionInfo) {
...
StartCoroutine(NextLevel(3f));
...
}
private IEnumerator NextLevel(float seconds) {
yield return new WaitForSeconds(seconds);
SceneManager.LoadScene(sceneNumber + 1);
}
Here's the first script which is just for the gems to be "collected".
using UnityEngine;
public class GemDestructionScript : MonoBehaviour
{
public int gemsCollected = 0;
void Awake()
{
}
void Update()
{
}
void OnCollisionEnter2D(Collision2D col)
{
if (col.gameObject.tag.Equals("Player1"))
{
gemsCollected++;
GetComponent<SpriteRenderer>().enabled = false;
GetComponent<CircleCollider2D>().enabled = false;
}
}
}
This is the 2nd script which is for the gemsCollected to be displayed on the canvas.
using UnityEngine;
using UnityEngine.UI;
using System;
public class GemCounter : GemDestructionScript
{
private Canvas canvas;
void Start()
{
}
void Update()
{
Transform child = transform.Find("Text");
Text t = child.GetComponent<Text>();
t.text = Convert.ToString(gemsCollected);
}
}
The problem is that the gemsCollected variable doesn't update on the canvas, it just stays at 0 the whole time.
Thanks in advance.
I fail to see the need for GemCounter to inherit from GemDestruction. Inheritance is more commonly used when having different Categories build upon each other.
A good, simple example of this is the Fruit example from Unity
In your case I would recommend using 2 separate Classes that are not linked via Inheritance. This will save you the headache of properly accessing whatever Data you need, unless it's really important for you to use Inheritance.
When you've split the classes and moved your gemsCollected to the Counter, instead of on the Gems themselves, you can just have the Gems "report in" when they are collected. This way the Counter can keep track of how many Gems have been collected and displays them on the UI. Every Object should have their job, and only use things that are relevant for that Job.
Example:
public class GemDestructionScript : MonoBehaviour
{
GemCounter counter;
private void Start()
{
// Find where-ever you keep the GemCounter Script (the Canvas in your case)
counter = GameObject.Find("Canvas").GetComponent<GemCounter>();
}
void OnCollisionEnter2D(Collision2D col)
{
if (col.gameObject.tag.Equals("Player1"))
{
counter.AddGem();
GetComponent<SpriteRenderer>().enabled = false;
GetComponent<CircleCollider2D>().enabled = false;
}
}
}
public class GemCounter : MonoBehaviour
{
public int gemsCollected = 0;
Text GemCounterText;
private void Start()
{
// Finding the Text Object in every Frame would be inefficient, so unless that object is constantly changing, just get it once during Start/Awake/before using it
GemCounterText = GameObject.Find("Text").GetComponent<Text>();
}
public void UpdateGemCount()
{
GemCounterText.text = gemsCollected.ToString();
}
public void AddGem()
{
gemsCollected++;
UpdateGemCount();
}
}
I have a number of Prefabs stored in an array and instantiate one at a time by clicking a button. The object appears but is always inactive.
I've searched for hours for an answer and tried a lot but the problem stays the same. I hope it's ok to ask, even though there are several similar questions but none of the answers solves my problem.
Like I've already described, I want to instantiate a GameObject from an array per button click and the object indeed appears but when I try to start a coroutine on it(if that's helpful, it's an IEnumerator that shall let the Object fade out by handling it's colours alpha channel), I always get an error that says the GameObject is inactive. I'm not able to set it active by writing myPrefab.gameObject.SetActive(true) and I've tried to call it at several places in my code. It always stays inactive. Has anybody any idea what might be the problem?
public class Class1 : MonoBehaviour
{
[SerializeField]
private MyClass[] myPrefabs;
private MyClass myCurrentPrefab;
private int myIndex;
public void ButtonEffect()
{
InstantiatePrefab();
myCurrentPrefab.OnButtonEffect();
}
private void InstantiatePrefab()
{
myIndex = Random.Range(0, myPrefabs.Length);
myCurrentPrefab = myPrefabs[myIndex];
Instantiate(myCurrentPrefab);
}
}
public class MyClass : MonoBehaviour
{
private SpriteRenderer mySprite;
private void Start()
{
mySprite = GetComponent<SpriteRenderer>();
}
private void Awake()
{
this.gameObject.SetActive(true)
}
private void OnButtonEffect()
{
StartCoroutine(FadeOut(mySprite, 3));
}
public IEnumerator FadeOut(SpriteRenderer spriteToFade, float duration)
{
//DoFadeOutStuff
}
}
Here I've tried to set the object active in the Awake function of its own code but I've also tried it in the both functions of Class1 and its Start function. I've also tried to handle it for the whole array in an foreach loop. Always the same result. All I want to do is to set it active, right now I don't even care if my fade out stuff works correctly. First I thought it was because my instantiated object is a clone but I can't find anything about it, so even if the solution is pretty obvious, please help!
The problem is that you're referencing the actual prefab itself, which isn't actually active in the scene. You need to create a gameobject and set its value to the instantiated prefab. The following should work
using UnityEngine;
public class Class1 : MonoBehaviour
{
[SerializeField]
private GameObject[] myPrefabs;
public void ButtonEffect()
{
var go = InstantiatedPrefab();
go.GetComponent<MyClass>().OnButtonEffect();
}
private GameObject InstantiatedPrefab()
{
var index = Random.Range(0, myPrefabs.Length);
return Instantiate(myPrefabs[index]);
}
}
using System.Collections;
using UnityEngine;
public class MyClass : MonoBehaviour
{
private SpriteRenderer mySprite;
private void Start()
{
mySprite = GetComponent<SpriteRenderer>();
}
public void OnButtonEffect()
{
StartCoroutine(FadeOut(mySprite, 3));
}
private IEnumerator FadeOut(SpriteRenderer spriteToFade, float duration)
{
print("FadeOut");
yield return 0;
}
}
I have made a method (changePaddleSize) in the class"Paddle", and trying to call it from another class "paddleMinimizer". When doing this, I get the following error:
An object reference is required to access non-static member `UnityEngine.Component.transform'
Here are my classes:
public class Paddle : MonoBehaviour {
public static void changePaddleSize(){
transform.localScale = new Vector3(2f, 0.5f, 1);
}
}
and
public class paddleMinimizer : MonoBehaviour {
public GameObject triggerText;
void OnCollisionEnter () {
Paddle.changePaddleSize ();
}
}
I have obviously done something wrong, but how can I fix this? If there is another way of doing this, please tell me. It will be appreciated.
Assuming there is only ever going to be one Paddle, one option might be to declare a static var that is the Paddle, and reference as such from within your code.
public class Paddle : MonoBehaviour {
public static Paddle global;
void Awake () {
Paddle.global = GetComponent<Paddle>();
}
public static void changePaddleSize(){
Paddle.global.transform.localScale = new Vector3(2f, 0.5f, 1);
}
}
This way you can still call Paddle.changePaddleSize (); from anywhere and have it work.
Alternatively, you could have changePaddleSize not be a static method, and call Paddle.global.changePaddleSize() instead:
public class Paddle : MonoBehaviour {
public static Paddle global;
void Awake () {
Paddle.global = GetComponent<Paddle>();
}
public void changePaddleSize(){
transform.localScale = new Vector3(2f, 0.5f, 1);
}
}
You need to get the Component you want to work on the transform from. You will get this from the GameObject you are working with. You can use
GameObject.Find("name")
Or
GameObject.FindWithTag("tagName")
Then as long as the game object is not null you can:
myGameObject.GetComponent<T>()
Where T is your component type. Again this could return null so you must check for this.
I am trying to pass on a value from OnTriggerEnter function for a class to another class.I already set the value that I want to pass to global variable.This is how I do :
public GameObject go;
public bool isSomething;
public static AClass instance;
public void Start()
{
instance=this;
}
public void OnTriggerEnter(Collision other)
{
if(go.tag=="Something")
{
isSomething=true;
}
}
The problem is at another class,I call isSomething from AClass and I run the Unity,it give me NullExceptionReference when I pass through a game object.This is the another class code :
private AClass aclass;
public void Start()
{
aclass=AClass.instance;
}
public void Update()
{
Debug.Log(aclass.isSomething); //<-----------------This give Null Exception Reference
}
I want to get a value just after I pass a collider trigger and not before passing a collider trigger.I don't know is this a dumb question but I hope someone can give me some idea.Thanks. :)
Try assigning the instance in the Awake function:
public void Awake()
{
instance = this;
}
There's no guarantee that the Start() function of one object happens before or after that of another object unless you explicitly set the execution order.
This code is wrong.
public void OnTriggerEnter(Collision other)
{
if(go.tag=="Something")
{
isSomething=true;
}
}
Solution
public void OnTriggerEnter(Collision other)
{
if(other.tag == "Something")
isSomething=true;
}