0

I'm making a Unity3D game. I want to implement a connection between the script Timer.cs and Collide.cs, by which they exchange the variable obji. And before you mark this question as a duplicate I want to mention that have already read this tutorial. As a result of the solution provided I get the error

A namespace cannot directly contain members such as fields or methods

Can you provide a solution for exchanging information between scripts that have no element in common. I want Timer.cs to get the variable obji from Collide.cs

Timer.cs

using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class Timer : MonoBehaviour { public ScoresManager ScoresManager; Text instruction; // Start is called before the first frame update void Start() { instruction = GetComponent<Text>(); InvokeRepeating("time", 0, 1); } void time() { if (timeLeft <= 0){ /* if(move.obji() <= 0){ instruction.text = "You win!"; }else{ instruction.text = "You lost!"; }*/ } else { timeLeft = timeLeft - 1; instruction.text = (timeLeft).ToString(); } } // Update is called once per frame int timeLeft = 30; void Update() { } } 

Collide.cs

using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class Collide : MonoBehaviour { public Text txt; public int obji = -1; //this is an example, I always try to initialize my variables. void Start() { //or Awake obji = GameObject.FindGameObjectsWithTag("Enemy").Length; } void OnCollisionEnter(Collision collision) { if (collision.collider.gameObject.tag == "Enemy") { transform.localScale -= new Vector3(0.03F, 0.03F, 0.03F); Destroy(collision.collider.gameObject); obji = obji - 1; Debug.Log(obji); if ((obji) > 0) { txt.text = (obji).ToString(); } else { txt.text = "You win!"; } } } } 

Editor view 1

Editor view 2

1

2 Answers 2

3

Communication between scripts like this (sharing properties of one class with another class) is a very common task in Unity. The script that needs the value of a property of another class should get a reference to that other class.

In your example, since Timer needs to access the obji property from the Collide class, you need to add a reference to the Collide class to the Timer class:

public class Timer : MonoBehaviour { public Collide _collide; // The rest of the script... } 

Then, in the Inspector in Unity, you need to drag a GameObject that has the Collide script attached to the _collide property of the GameObject with the Timer script attached.

Finally, you can access the obji property through your newly created reference:

if (_collide.obji > 0) 

See this tutorial from Unity which covers this topic in depth.

Sign up to request clarification or add additional context in comments.

Comments

0

The error you've once received:

A namespace cannot directly contain members such as fields or methods,

tells you that in a namespace cannot be placed any methods or fields (i.e. variables) directly. A namespace can only contain

  • classes,
  • interfaces,
  • enums,
  • delegates,
  • structs
  • namespaces.

Generally speaking, a namespace is used to provide certain scope and organize entities.


There are many ways you can get access to another class's member fields. The cleanest and simplest way is through a so-called Getter method (also through get properties). You should avoid using and referencing public fields. For example, in your Collide class

// You don't have to always initialize your fields: they have default values. // Initialize only when you need to. private int obji; ... public int GetObji() { return obji; } 

Now, to call that method you need a proper reference to it. For that you can simply add that as a parameter in your Timer class:

public Collide CollideRef; ... // Get the field CollideRef.GetObji(); 

And then just drag and drop the GameObject, having the Collide component onto it.

8 Comments

obji is a property already and has a getter method. The only part OP was missing was adding a reference to the Collide script.
@LewsTherin No, it doesn'T have a getter method. It is global and utilisation of global variables leads to poor code quality and harder maintenance.
Global variables don't exist in C#. My terminology was off. You are correct that it is not technically a property with a getter; But my point still stands that OP only needs a reference to Collide to be able to access the obji public field, as described in my answer.
@LewsTherin By global I meant global to a class. In your link, they speak of true global variables, which I believe are not part of many, if any, modern day languages. About your point, while true, it is just a bad practice and can lead to various code smells.
Well you taught me something! I didn't know that they open-sourced the engine (GitHub link). I don't have time to dig through it now, but I still think that there must be some reason the Unity devs recommend public variables so often (they must know about Encapsulation and that Microsoft recommends properties instead of public fields in C#). Fly-by downvoting and leaving no reason is one of the most annoying things on this site! Thanks for keeping this civil :)
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.