C
C#•7mo ago
AdiZ

Absolute Beginner - Accessing Variables From Other Classes

Hi. DecodeButton.cs:
using UnityEngine;

public class DecodeButton : MonoBehaviour
{
void Start()
{
Decoders decoder = new Decoders();
}

void OnClick()
{
Decoders.CaesarCipher(ReadStringInput.input);
}
}
using UnityEngine;

public class DecodeButton : MonoBehaviour
{
void Start()
{
Decoders decoder = new Decoders();
}

void OnClick()
{
Decoders.CaesarCipher(ReadStringInput.input);
}
}
ReadStringInput.cs:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ReadStringInput : MonoBehaviour
{
public string input;

// Start is called before the first frame update
void Start()
{

}

// Update is called once per frame
void Update()
{

}

public void ReadInput(string s)
{
input = s;
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ReadStringInput : MonoBehaviour
{
public string input;

// Start is called before the first frame update
void Start()
{

}

// Update is called once per frame
void Update()
{

}

public void ReadInput(string s)
{
input = s;
}
}
In DecodeButton.cs, I'm getting the error CS0120 about Object references but frankly I'm not understanding it. Can someone help me out?
53 Replies
AdiZ
AdiZ•7mo ago
The exact error text is:
An object reference is required for the non-static field, method, or property 'ReadStringInput.input'
An object reference is required for the non-static field, method, or property 'ReadStringInput.input'
Thinker
Thinker•7mo ago
The error is telling you that you need an instance to access the input field
AdiZ
AdiZ•7mo ago
Oh right The word reference was confusing me Thank you! I'll try it really quickly I changed DecodeButton.cs to this:
using UnityEngine;

public class DecodeButton : MonoBehaviour
{
void Start()
{
Decoders decoder = new Decoders();
ReadStringInput readStringInput = new ReadStringInput();
}

void OnClick()
{
string output = Decoders.CaesarCipher(readStringInput.input);
}
}
using UnityEngine;

public class DecodeButton : MonoBehaviour
{
void Start()
{
Decoders decoder = new Decoders();
ReadStringInput readStringInput = new ReadStringInput();
}

void OnClick()
{
string output = Decoders.CaesarCipher(readStringInput.input);
}
}
@🌈 Thinker 🌈 but i get a different error now Just that readStringInput doesn't exist I'm guessing that this is because the IDE doesn't know whether Start() will be called before OnClick()? But Unity still doesn't let me run the app
Thinker
Thinker•7mo ago
You're creating a variable readStringInput which is local to Start, it's destroyed immediately after the method stops.
AdiZ
AdiZ•7mo ago
But I can't really define it outside of the method, right?
Thinker
Thinker•7mo ago
yes you can You did that with input
AdiZ
AdiZ•7mo ago
Well isn't that a good point So just
ReadStringInput readStringInput;
ReadStringInput readStringInput;
? Or do I include the new() bit as well And then actually create the instance just before using it
Thinker
Thinker•7mo ago
yep Also about this, this is something called scope which determines where and how variables are accessible. It's a pretty fundamental concept, so it's quite important to know about
AdiZ
AdiZ•7mo ago
Yeah I understand it from Python, just kinda forgot it here haha - still getting into the frame of mind needed for coding Would it also work if I instantiated it within the scope of the entire class?
Thinker
Thinker•7mo ago
Yeah, and C# is quite different from Python
AdiZ
AdiZ•7mo ago
Oh yeah Definitely Quite cool though
Thinker
Thinker•7mo ago
Well yes, but that works a bit differently
AdiZ
AdiZ•7mo ago
How so?
Thinker
Thinker•7mo ago
Fields (variables in a class) cannot depend on each other, and you wouldn't be able to call any Unity methods from a field initializer.
AdiZ
AdiZ•7mo ago
So what could I use that for?
Thinker
Thinker•7mo ago
class Foo : MonoBehavior
{
private int x = GetComponent<Bar>().Value;
}
class Foo : MonoBehavior
{
private int x = GetComponent<Bar>().Value;
}
This wouldn't work
AdiZ
AdiZ•7mo ago
Ok
Thinker
Thinker•7mo ago
You set the value in Start or similar
AdiZ
AdiZ•7mo ago
And that is because it cannot change? So that value must always be the same so it can't depend on what GetComponent<Bar>().Value actually is?
Thinker
Thinker•7mo ago
not exactly In field initializers, Unity methods do not work
AdiZ
AdiZ•7mo ago
Got it
Thinker
Thinker•7mo ago
You have to set the value of fields in Start or some other method Though of course this is just in Unity
AdiZ
AdiZ•7mo ago
Yes I understand Not exactly why Unity methods don't work, though
Thinker
Thinker•7mo ago
Do you know what a constructor is?
AdiZ
AdiZ•7mo ago
Somewhat, yes Called when the class is instantiated
Thinker
Thinker•7mo ago
yep
AdiZ
AdiZ•7mo ago
Sets some intial fields' values depending on parameters That's about the extent of my knowledge on them
Thinker
Thinker•7mo ago
So field initializers are actually just put inside the class's constructor. Unity doesn't let you use constructors for MonoBehavior classes, for various reasons including multithreading (I believe). Constructors are called before the object has any information about its place in the scene, eg. what components it has, its transform, etc., and this prevents you from calling Unity methods in said constructor.
AdiZ
AdiZ•7mo ago
That makes a lot of sense Pretty logical to be fair
Thinker
Thinker•7mo ago
However Start is called after this initialization is complete, therefore you have to initialize fields from there.
AdiZ
AdiZ•7mo ago
Got it So Start() is effectively your constructor when using Unity
Thinker
Thinker•7mo ago
yep
AdiZ
AdiZ•7mo ago
Okay Thank you, that's actually quite useful to know
Thinker
Thinker•7mo ago
np catsip
AdiZ
AdiZ•7mo ago
Really quick, I saw this thing in codecademy at school that's like if ? myBool x : y Something vaguely resembling that Like a really short if/else statement to set the value of a variable And I've completely forgotten it
Thinker
Thinker•7mo ago
int x = c ? a : b;

// same as

int x;
if (c)
{
x = a;
}
else
{
x = b;
}
int x = c ? a : b;

// same as

int x;
if (c)
{
x = a;
}
else
{
x = b;
}
AdiZ
AdiZ•7mo ago
That's the one Brilliant Thank you
Thinker
Thinker•7mo ago
yeah, it's quite useful
AdiZ
AdiZ•7mo ago
Now I've just got to figure out how to restrict the contents of an Input Field in Unity to digits Shouldn't be too hard But knowing me I'll make some super complicated method for doing it when there's already a built-in function or something 😢
Thinker
Thinker•7mo ago
Hint: use int.TryParse
AdiZ
AdiZ•7mo ago
Yep I'm using that rn Just don't want to run that over every char every time the field is edited I feel like Unity will have something in there that does it for me @🌈 Thinker 🌈
AdiZ
AdiZ•7mo ago
No description
AdiZ
AdiZ•7mo ago
I'm now just getting a bunch of these errors This is the script that is supposedly causing issues:
using UnityEngine;

public class DecodeButton : MonoBehaviour
{
ReadStringInput plaintextStringInput;
ReadStringInput shuffleStringInput;

void Start()
{
plaintextStringInput = new ReadStringInput();
shuffleStringInput = new ReadStringInput();
}

void OnClick()
{
int shuffle = 0;
// string output = Decoders.CaesarCipher(plaintextStringInput.input);
}
}
using UnityEngine;

public class DecodeButton : MonoBehaviour
{
ReadStringInput plaintextStringInput;
ReadStringInput shuffleStringInput;

void Start()
{
plaintextStringInput = new ReadStringInput();
shuffleStringInput = new ReadStringInput();
}

void OnClick()
{
int shuffle = 0;
// string output = Decoders.CaesarCipher(plaintextStringInput.input);
}
}
AdiZ
AdiZ•7mo ago
Unity Discussions
You are trying to create a MonoBehaviour using the 'new' keyword. ...
You are trying to create a MonoBehaviour using the ‘new’ keyword. This is not allowed. MonoBehaviours can only be added using AddComponent(). Alternatively, your script can inherit from ScriptableObject or no base class at all I am trying to connect these two scripts and I don’t know which one this error is for. The full error is: You...
AdiZ
AdiZ•7mo ago
Looking at this link, it suggests MyScript script = obj.AddComponent<MyScript>(); However I don't understand the syntax We're creating a script - where does it go? Is it a temporary file? Why are we adding a component? Also isn't MonoBehaviour.Awake() Unity's version of a constructor?
AdiZ
AdiZ•7mo ago
AdiZ
AdiZ•7mo ago
Found the fix for this.
AdiZ
AdiZ•7mo ago
GitHub
CipherDecoderApp/Assets/Scripts at main · AdiZ-1579887/CipherDecode...
Adi, Karter, Kavya. Contribute to AdiZ-1579887/CipherDecoderApp development by creating an account on GitHub.
AdiZ
AdiZ•7mo ago
You can find it here if you're curious 🙂
Thinker
Thinker•7mo ago
Read what it says
Dharmang
Dharmang•7mo ago
Altho a bit late, I suggest watching tarodev's videos. Excellent resource and he also has a discord. https://www.youtube.com/watch?v=tE1qH8OxO2Y
Tarodev
YouTube
Unity Architecture for Noobs - Game Structure
Unity Architecture is one of those things which can completely overwhelm new devs. This video will introduce you to a handful of architectural design patterns, which shy away from over-engineering, allowing you to learn the basics and get on with developing your game. Simple patterns are perfectly fine for most projects solo devs and small teams...
Dharmang
Dharmang•7mo ago
it covers basically everything for beginners. I am also learning from it
AdiZ
AdiZ•7mo ago
@Dharmang thank you, definitely needed something like this, I'll go check it out.