C# - Failed at calling another script - c#

I've created two scripts. One includes a variable and a method. Second script's task is to call the first script and access its component. However I'm getting the following error :
ThisScriptWillCallAnotherScript.Update () (at Assets/Scripts/ThisScriptWillCallAnotherScript.cs:21)
I tried removing the line it's referring to but the error persists.
Any idea what I may be doing wrong?
Script 1 :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ThisScriptWillBeCalledInAnotherScript : MonoBehaviour {
public string accessMe = "this variable has been accessed from another script";
public void AccessThisMethod () {
Debug.Log ("This method has been accessed from another script.");
}
}
Script 2 :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ThisScriptWillCallAnotherScript : MonoBehaviour {
// below we are calling a script and giving a name//
ThisScriptWillBeCalledInAnotherScript callingAScript;
void Start () {
//here we are using GetComponent to access the script//
callingAScript = GetComponent<ThisScriptWillBeCalledInAnotherScript> ();
Debug.Log ("Please press enter key...");
}
// Update is called once per frame
void Update () {
if (Input.GetKeyDown (KeyCode.Return)) {
Debug.Log ("this is the script we just called " + callingAScript);
Debug.Log (callingAScript.accessMe); // we are accessing a variable of the script we called
callingAScript.AccessThisMethod (); // we are calling a method of the script we called
}
}
}

It Unity GameObjects can have Components.
The method GetComponent<T>() gets a reference to the component T from the current GameObject.
So if your GameObject has both components (ScriptAand ScriptB)
then this will return a "not-null" reference to the instance of ScriptB:
public class ScriptA : MonoBehaviour {
ScriptB scriptB;
// Use this for initialization
void Start () {
scriptB = GetComponent<ScriptB>(); //Not null if GameObject has ScriptB component.
}
}
If you GameObject does not have the component ScriptB, then the Method GetComponent<T>() will return null.
If ScriptB is a component from another GameObject then you will need a reference to that other GameObject and call it via OtherGamoeObject.GetComponent<T>()
If ScriptB is not even a Script that changed the GameObject and simply (for example) contains some Math-Calculations or so, then I would suggest not making it inherit from Monobehaviourand simply creating an instance like so: var scriptB = new ScriptB();

Related

I have tried using a public void function from a different script and error message CS1061 pops up

I am making a game in Unity with dialogue boxes and have one script made for putting the dialogue box on the screen and another to have the actual text put on the dialogue box.There is one function in the first script I have to use in the second to make it work. The problem however is that when I try to reference the first script it always occur an error.
The error message is:
Assets\scripts\dialogueHolder.cs(29,18): error CS1061: 'dialogueManager' does not contain a definition for 'ShowBox' and no accessible extension method 'ShowBox' accepting a first argument of type 'dialogueManager' could be found (are you missing a using directive or an assembly reference?)
First code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class dialogueManager : MonoBehaviour
{
public GameObject dialogueBox;
public Text dialogueText;
public bool activeDialogue;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (activeDialogue == true && Input.GetKeyDown(KeyCode.Return))
{
dialogueBox.SetActive(false);
activeDialogue = false;
}
}
public void ShowBox(string lines)
{
activeDialogue = true
dialogueBox.SetActive(true);
dialogueText.text = lines;
}
}
Second code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class dialogueHolder : MonoBehaviour
{
public string dialogue;
private dialogueManager dMan;
public GameObject Manager;
// Start is called before the first frame update
void Start()
{
dMan = Manager.GetComponent<dialogueManager>();
}
// Update is called once per frame
void Update()
{
}
void OnTriggerStay2D(Collider2D other)
{
if(other.gameObject.name=="Shadow")
{
if(Input.GetKeyDown(KeyCode.Return))
dMan.ShowBox(dialogue);
}
}
}
I can clearly see that the function ShowBox I am trying to access from the first script is the problem. But I can't figure out what to do with the code to make it work. I have tried different methods to try and reference the Class dialogueManager. For an example I have tried refrencing the actual gameobject in the game or the script alone but I can't seem to get it to work. If I remove the function ShowBox the code will run but I need the ShowBox function to actually make the dialogue boxes in my game to work so that is not a solution.
"activeDialogue = true" maybe you should put a ";" after this

Unity communication between scripts

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!";
}
}
}
}
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.
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.

TextMesh Pro text will not change via script

I cannot seem to change my TextMeshPro value via script.
In my inspector I have a TextmeshPro object named Countdown. I have a script named GameController which is attached to this.
My script then sets the string value of Countdown to Hello but it does not work.
GameController
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
public class GameController : MonoBehaviour {
public TextMeshProUGUI Countdown;
// Use this for initialization
void Start () {
Countdown = GetComponent<TextMeshProUGUI> ();
Countdown.text = "Hello";
}
// Update is called once per frame
void Update () {
}
}
In the inspector there is a field for TextMesh but I cannot drag the CountDown object to this for some reason, could that be the issue?
the problem is that you are using a regular TextMeshPro object, and in your code your looking for a TextMeshProUGUI, simple mistake. change code to:
public class GameController : MonoBehaviour {
public TextMeshPro Countdown;
// Use this for initialization
void Start () {
//you shouldnt need to get component the editor should take care of this for you when
//you drop it since you have the object set to TextMeshPro and not just GameObject
Countdown = GetComponent<TextMeshPro> ();
Countdown.text = "Hello";
}
// Update is called once per frame
void Update () {
}
}
the only way to make a TextMeshProUGUI object is to add it through a canvas. in your scene when you just add a TMP it will be Regular TMP which your "countdown" is. you can tell because it uses the TMP script not the TMPUGUI script.

Enable/disable a GameObject component from a script [Unity3D]

I need to take the value of a boolean (put in a variable called "bouclier") set in one script to enable or disable a GameObject.
The variable is in game object Player (bottom right here):
And I need to enable of disable this game object ("Bouclier01"):
To do this, I attached a script to game object "Bouclier01". Here it is:
using UnityEngine;
using System.Collections;
public class ShowBouclier : MonoBehaviour {
public GameObject Bouclier01;
public bool bouclier;
// Use this for initialization
void Start () {
Bouclier01 = Bouclier01.GetComponent<GameObject>();
}
// Update is called once per frame
void Update () {
Bouclier01.enabled = false;
if (bouclier == true) {
Bouclier01.enabled = true;
}
}
}
I must be missing something, because this comes up with this error message:
Any idea how to properly accomplish this?
You can use GameObject.SetActive() function to activate or deactivate a GameObject (I think GameObject.enabled was in the old API):
Bouclier.SetActive(false);
By the way, if you want to know the current activation state of a GameObject, use GameObject.activeSelf, which is a read only variable:
Debug.Log(Bouclier.activeSelf);
it will works
public GameObject otherobj;//your other object
public string scr;// your secound script name
void Start () {
(otherobj. GetComponent(scr) as MonoBehaviour).enabled = false;
}

Character not attacking via Unity

So I have built an attack using SpriteFactory, and simply want to assign the keyboard letter A as a default attack. I have used GetKeyUp for the sole purpose of the character to attack once, and not multiple times like a loop (i.e. GetKeyDown). At this stage I have not included any enemies or anything, as i just want the the character to simply attack when I Press A. I have Included the game object and added the Attack.cs but no success. Maybe I am complete missing the point of what I am doing, but some help in the right direction would be appreciated.
using UnityEngine;
using System.Collections;
public class Attack : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if(Input.GetKeyUp(KeyCode.A)) {
}
}
}
Ok so i have tried the below method. Have adjusted the code as follows:
using UnityEngine;
using System.Collections;
using FactorySprite = SpriteFactory.Sprite;
public class Attack : MonoBehaviour {
// you forgot to set name of variable representing your sprite
private FactorySprite sprite;
// Use this for initialization
void Start () {
sprite = GetComponent<FactorySprite> (); // Edited
}
void Update ()
{
if(Input.GetKeyUp(KeyCode.A))
{
sprite.Play("Attack");
}
}
}
But now have a ''nullReferenceError'' Object reference not set to an instant object?
You have to add yourSprite.Play("AnimationName"); to your loop:
void Update ()
{
if(Input.GetKeyUp(KeyCode.A))
{
yourSprite.Play("AnimationName");
}
}
For this to work you have to add a reference to your sprite to the script, with GetComponent().
Btw, GetKeyDown only triggers once for each key-press, you can use this too. (GetKey() would fire every frame)

Categories