Detecting variables outside method - c#

I was trying to make a 2d Unity Latin translator, but i got a problem. How could i make that it recognises the Text and Dropdown variables already inside the "Declinatio". I need to check for the last 2 characters of this string which is SGenTextStr, and the data should be taken from the SGenText InputField. I dont know if you got a fix for this, i didnt find anything that was helpful on the internet.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
public class LatinDecl : MonoBehaviour
{
public static void Declinatio()
{
string SGenTextStr;
string AnsTextStr;
int StrLength;
SGenTextStr = SGenText.text;
AnsTextStr = AnsText.text;
StrLength = SGenTextStr.Length();
switch (SGenTextStr.charAt(StrLength - 2) + SGenTextStr.charAt(StrLength - 1))
{
default:
break;
}
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
InputField SGenText;
Dropdown DeclDrop;
InputField AnsText;
}
}

One of the things you may use a lot in Unity games is the Gameobject.GetComponent<>() method. It allows you to access values and functions from other components or scripts in your Unity Scene.
There are also an issue with declaring your variables in Update() as it will cause them to be wiped clean every frame, instead you may want to move them outside all together.
Because of that you will also have trouble with Declinatio() as it is currently static, which wont allow it to reference any non-static variables outside of it.
The last issue is that C# doesn't actually have an implementation of String.charat() however you can use String[int] to achieve the same thing.
With all those changes it would look something like this:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
public class LatinDecl : MonoBehaviour
{
public InputField SGenText;
public Dropdown DeclDrop;
public InputField AnsText;
public void Declinatio()
{
string SGenTextStr;
string AnsTextStr;
int StrLength;
SGenTextStr = SGenText.GetComponent<InputField>().text;
AnsTextStr = AnsText.GetComponent<InputField>().text;
StrLength = SGenTextStr.Length;
switch (SGenTextStr[(StrLength - 2)] + SGenTextStr[(StrLength - 1)])
{
default:
break;
}
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}

Related

Unity Error [error CS0120: An object reference is required for the non-static field, method, or property 'Zoney.setMonney(int)'] [duplicate]

This question already has answers here:
CS0120: An object reference is required for the nonstatic field, method, or property 'foo'
(9 answers)
Closed 2 years ago.
I keep getting this error, but I don't even know what is or isn't static in this context? I have tried solutions like setting instances and checking capitalization but I just get the same error. I want the shop script to change the monney value, which is written into debug until I set up the right U.I.
The Zoney script:
using UnityEngine;
using UnityEngine.UI;
public class Zoney : MonoBehaviour
{
public Text Money;
public int Monney;
private string Mony;
// Start is called before the first frame update
void Start()
{
Money = GetComponent<Text>();
}
public void setMonney(int Change)
{
Monney = Change;
}
// Update is called once per frame
void Update()
{
Mony = Monney.ToString();
Money.text = Mony;
}
}
The Shop script:
using UnityEngine;
public class Shop : MonoBehaviour
{
public int Change;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
Change += 1;
Zoney.setMonney(Change);
Debug.Log(Change);
}
}
Because you're working with Unity, you need to follow the requirements of the engine.
In a case like this, where you need an instance of a component (MonoBehaviour), you really want to be referencing a Unity created instance, instead of creating a new one with the new keyword. Creating an instance of a component using the new keyword is going to leave you with an instance of the class that's not associated with any Unity GameObject.
The far more reliant way to get the component you want to reference, is to use the Inspector window, and drag into the object field, the right component on the desired object. In this case, I am going to assume you'll want to drag a Scene object (in your hierarchy) into the object field slot.
You would do that by first defining a variable. This can generally be done in one of two ways:
public Zoney zoney;
[SerializeField] private Zoney zoney;
In this example, once you've assigned your reference, use the variable zoney, instead of the class name Zoney. Note that your variable name could be anything else you feel is appropriate, e.g. _zoney, or myZoney.
Your new Shop script could then look like this:
public class Shop : MonoBehaviour
{
public int Change;
public Zoney zoney;
void Update()
{
Change += 1;
zoney.setMonney(Change);
Debug.Log(Change);
}
}
Zoney is a class, you need to create an instance of it first before using it.
Instantiate a class that derives from MonoBehaviour
Also very important, you need to update your shop object so it has the Zoney instance as a member object otherwise your updates to money wont be kept:
i.e.
public class Shop : MonoBehaviour
{
private Zoney;
public int Change;
// Start is called before the first frame update
void Start()
{
_HiddenZoney = gameObject.Addcomponent<Zoney>();
}
// Update is called once per frame
void Update()
{
Change += 1;
_HiddenZoney.setMoney(Change);
Debug.Log(Change);
}
}
Thanks #derHugo for the alert!
You need to create a object from Zoney class to access it's non static memebers. Try below:
public class Shop : MonoBehaviour
{
public int Change;
public Zoney myZoney; // Need to create the object
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
Change += 1;
myZoney.setMonney(Change); // Access members using created object
Debug.Log(Change);
}
}

Unity can't acess prefab's script's variable

I am working on a 3D game on Unity but recently a problem occurred. I can't access a variable from another prefab's script. I tried it before when the object which has to be accessed wasn't a prefab and it worked correctly.
This is the script which tries to access the "slashtime" variable, but when I run it gives back 0 though in the other script the variable is changing continuously.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class collision : MonoBehaviour
{
public GameObject sword;
public float slashtime;
private void Update()
{
slashtime=sword.GetComponent<movement>().slashtime;
}
private void OnTriggerEnter(Collider collider)
{
if (collider.tag == "sword" && slashtime+1f > Time.time)
{
Destroy(gameObject);
}
}
}
You can use this. It is also working.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class collision : MonoBehaviour
{
public GameObject sword;
public float slashtime;
private void OnTriggerEnter(Collider collider)
{
sword = collider.gameObject;
slashtime=sword.GetComponent<movement>().slashtime;
if (collider.tag == "sword" && slashtime+1f > Time.time)
{
Destroy(gameObject);
}
}
}
Reason for your code is not working because when you write some code in update then it calls every frame. so when your object is destroyed, update call that code and it shown error.
Reworking your code a bit, with explanations below:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class collision : MonoBehaviour
{
[SerializeField]
private GameObject _sword;
private float _slashTime;
private void Start()
{
_slashTime = GameObject.Find("Movement").GetComponent<Movement>().GetSlashTime();
}
private void OnTriggerEnter(Collider collider)
{
if (collider.CompareTag("sword") && _slashTime + 1f > Time.time)
{
Destroy(gameObject); // What is gameObject in this context? the _sword? something else?
}
}
}
Use private properties. Why? Because it increases modularity and protects the object(s) you're working with from accidentally having their values overwritten.
In conjunction to this, use public methods to obtain/change the values in other objects. Public methods are your API.
It's convention to begin the names of private properties with an underscore.
Like I said in my comment above, you first need to Find() your desired object before you can attempt to GetComponent<T>().
Like others have said, attempting to GetComponent<T>() in Update() is computationally expensive. It's better to get that component at Start() and then talk to it as necessary (in this case, during collision).
CompareTag() is the more modern/accepted way to check a tag.
EDIT:
[SerializeField] will keep the property private while also making it available to the Unity editor. It's good for debugging and linking objects.

Unity TextMeshProUGUI.text is NullReferenceException ... not set to an instance [duplicate]

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 3 years ago.
I've been looking around for a possible solution but I don't solve It... This is the problem:
I have in a file with its class the various Ui, including the textmesh.
Another file, with its own class, retrieves and sets them via ".text"
result?
"NullReferenceException: Object reference not set to an instance of an
object Controller_RaceManager.Update () (at
Assets/[GameAssets]/Controller
[MobileCar]/Scripts.Code/Controller_RaceManager.cs:307)"
to better understand:
A) into Controller_UiManager.cs (attached to the canvas with all UIs)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI; using TMPro;
public class Controller_UiManager : MonoBehaviour
{
[System.Serializable]
public class UiSettings
{
public TextMeshProUGUI Label_Lap;
}
[SerializeField]
[HideLabel] public UiSettings UiElements;
void OnDrawGizmos()
{
var Canvas = this.gameObject;
UiElements.Label_Lap = getTheChild(Canvas, "Label.PilotLap").transform.GetComponent<TextMeshProUGUI>();
// note: getTheChild is a method that returns the child gameObject
}
}
B) Controller_RaceManager.cs, which of course handles all the values ​​of races (It's attached to his prefab for loops and bla bla bla)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI; using TMPro;
public class Controller_RaceManager : MonoBehaviour
{
[System.Serializable]
public class RaceManagerSettings
{
...
public Controller_UiManager UiManager;
}
[SerializeField]
[HideLabel] public RaceManagerSettings sets;
void OnDrawGizmos()
{
if(GameObject.Find("Ui-RaceLoop"))
{
sets.UiManager = GameObject.Find("Ui-RaceLoop").transform.GetComponent<Controller_UiManager>();
}
else
{
Debug.LogError("Controller Race Manage: Ui System not founded - Ui-Raceloop prefab is not in scene");
}
}
void Update()
{
string Label_Lap_Output = "";
if(...) { Label_Lap_Output = "FINISHED";}
else if(....) { Label_Lap_Output = "LAP XX/"+totalloopText; }
else { Label_Lap_Output = "LAP O"+pilotlapText+"/"+totalloopText; }
sets.UiManager.UiElements.Label_Lap.text = Label_Lap_Output;
}
}
here unity pauses and gives notice. If I take the break, it continues quietly ... but am I becoming stupid?
is there a reason?
note: Unity TextMeshProUGUI.text is NullReference not "why not all or some things" ... but textmeshpro.
Solved.
I didn't understand why the It was taken from other scripts but, with TextMesh, no.
So it was obvious that I was wondering about him (in part it was right! Because on the buttons it doesn't happen... the "ui controller" is taken via editor OnDrawGizmos function)
The solution:
TextMesh must be initialized in Start or Awake. If you try a taken it directly from the editor with OnDrawGizmo, even if you reset or empty the caches, will be null.
If instead, in start or awake:
void Start()
{
// find ui elements
sets.UiManager = GameObject.Find("Ui-RaceLoop").GetComponent<Controller_UiManager>();
}
The infamous works ... I have no idea why it happens, maybe they are different procedures between the two functions.

Unity GameOver Screen

I am just trying to activate game over screen when the Player's activate is 'false'. There is no animation, just the
There are 3 objects that need to be active and i added the script to those 3 objects but the screen does not appear.
How can i fix?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameOverManager : MonoBehaviour
{
public GameObject _player;
void Start()
{
_player = GameObject.FindGameObjectWithTag("Player");
}
void Update()
{
if (_player.activeInHierarchy == false)
{
gameObject.SetActive(true);
}
else
{
gameObject.SetActive(false);
}
}
}
My suspicion is the following. Whenever a Gameobject is not enabled, its code does not run. Test this by adding a Debug.Log("test") message.
If no message appears you can be certain that this check is never evaluated. To work around this simply add a script that is bound to an active gameObject. Creat a new empty gameobject in the scene. And add something like this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameOverManager : MonoBehaviour
{
public GameObject _player;
public GameObject _endscreen;
void Update()
{
if (_player.activeInHierarchy == false)
{
_endscreen.SetActive(true);
}
else
{
_endscreen.SetActive(false);
}
}
}
Assign the Variables in the Inspector by dragging the object to the empty fields. Never use GameObject.Find Methods.
If you need any further help tell me :)
What you're currently doing is to find a single GameObject and checking whether that is active or not.
It would make more sense, and be more optimized, if each player object adds himself to a list of all players when he spawns. You can then loop over that list instead to check all players.
An even better way would be if you only call that "GameOver" check after a player has died. So when you call whichever method kills him.
Based on Franz Answer, I did some modification in the code. You won't need any if else statement if you use a shortcut.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameOverManager : MonoBehaviour
{
public GameObject _player;
public GameObject _endscreen;
void Update()
{
_endscreen.SetActive(!_player.activeInHierarchy);
}
}

Set bool to different objects with 1 script Unity

I read many pages on google and everything else I could find but nothing helped me, so I have to ask here: I made a script attached to 100 cubes it says:
using UnityEngine;
using System.Collections;
public class IfClose:MonoBehaviour{
public bool Gravitronned=false;
// Use this for initialization
void Start(){
}
// Update is called once per frame
void Update(){
}
void OnTriggerEnter(Collider col)
{
if(col.gameObject.name =="IfInScreenGrv"){
Gravitronned=true;
}
else
{
Gravitronned=false;
}
}
}
and then I have another script that says:
using UnityEngine;
using System.Collections;
public class TimeFreeze:MonoBehaviour{
static bool GravitronedTwice;
// Use this for initialization
void Start(){
}
void Update()
{
GravitronedTwice= gameObject.GetComponent<IfClose>().Gravitronned;
if(GravitronedTwice=true){
if(Input.GetKeyDown(KeyCode.V)){
Physics.gravity =newVector3(0,3.0F,0);
}
}
}
}
so when I press V I want the cube only in this area to get Physics.gravity = new Vector3 (0, 3.0F, 0);
You're calling the value of the bool variable Gravitronned in the second script using GetComponent<>() which is not the right way of going about this.
How about instead of having two bool variables, Gravitronned and GravitronnedTwice, you only have 1 variable in the first script, make it public [even though make it public a bad idea - but that's another topic altogether] and have it access to both the scripts, instead of what you're doing. That way you can change the bool value, as well as access it in both scripts.
Alternatively, you can make the bool Gravitronned private in Script 1, and access it in any other script via C# property.
Script 1
private bool Gravitronned;
public BOOL GRAVITY
{
get Gravitronned;
set Gravitronned;
}

Categories

Resources