I am learning C# as Godot Engine require it. How should I call an object (class) that is created by other function?
Here is my code structure:
public class ExampleClass //A random class()
{ //I heard that I need to set a field for
float data; //other function, How should i do it?
public void SetData(float setData){ //Method in the class
data = setData;
}
... // other syntax in class
}
public void main (){
float dataStorage;
ExampleClass Class = new ExampleClass (); //Create new object
Class.setData(1.0f);
dataStorage = returnData(); // Call function that return the class
// which is called by main
}
public float returnData (){
float getData;
//How should I the call object that is created by main??
return getData;
}
In short, I would like to know what should I do in order to call the class that is created by other function, thank you!!
You may need below code.
using System;
namespace ExplicitInterface
{
public class ExampleClass //A random class()
{
//You can define property to get or set the value
public float SetData { get; set; }
}
class Program
{
ExampleClass objClass = new ExampleClass(); //Instantiate class level variable to be used anywhere in the class
public void Main(string[] args)
{
float dataStorage;
ExampleClass Class = new ExampleClass(); //Create new object
Class.SetData = 1.0f;
dataStorage = returnData();
}
public float returnData()
{
float getData = objClass.SetData;
return getData;
}
}
}
Related
I am writing c# script in Unity
public class something1 : MonoBehaviour
{
public void Dosomething(){
}
}
public class something2 : MonoBehaviour
{
public void Dosomething(){
}
}
public class callingDoSometing
{
public void callALLDosomething(){
something1 s1 = new something1();
something2 s2 = new something2();
something3 s3 = new something3();
something4 s4 = new something4();
.
.
.
s1.Dosomething();
s2.Dosomething();
s3.Dosomething();
s4.Dosomething();
.
.
.
}
}
I need to call methods with same names (here Dosomething()) from different classes.
Actually I need something like multiple inheritance in other OOP languages and I don't want to create additional languages.
Typically the way you'd do this in C# is to declare an interface; you can implement arbitrarily many interfaces, but only extend one base type.
interface IDoSomething
{
void DoSomething();
}
public class Thing1 : SomeBaseClass, IDoSomething
{
public void DoSomething(){ }
}
public class Thing2 : SomeBaseClass, IDoSomething
{
public void DoSomething() { }
}
And now you can use IDoSomething as a type:
IDoSomething i1 = new Thing1();
IDoSomething i2 = new Thing2();
i1.DoSomething();
i2.DoSomething();
Usually this is accomplished with interfaces.
public interface IDoSomething
{
void Dosomething();
}
public class something1 : MonoBehaviour, IDoSomething
{
public void Dosomething() { }
}
public class something2 : MonoBehaviour, IDoSomething
{
public void Dosomething() { }
}
If you are trying to dynamically discover these classes, you would do something like this:
public class CallingDoSomething
{
private Type[] Get_IDoSomethingTypes()
{
var allTypes = typeof(CallingDoSomething).Assembly.GetTypes();
var searchFor = typeof(IDoSomething);
return allTypes.Where(x => searchFor.IsAssignableFrom(x))
.Where(x => x.IsClass)
.ToArray();
}
public void CallAllSomethings()
{
var types = Get_IDoSomethingTypes();
foreach (var type in types)
{
var instance = (IDoSomething)Activator.CreateInstance(type);
instance.Dosomething();
}
}
}
If you already have a collection these classes instantiated, you would just always treat them like they are IDoSomething objects:
public class CallingDoSomething
{
private List<IDoSomething> m_somethingDoers = new List<IDoSomething>();
public void OtherCodeThatPopulatedSomethingDoers()
{
// ...
}
public void CallAllSomethings()
{
foreach (var s in m_somethingDoers)
s.Dosomething();
}
}
The fact that you want to do this to two MonoBehaviours that don't otherwise have a common parent might indicate some questionable engineering, but it is possible to do exactly this using GameObject.SendMessage.
public class something1 : MonoBehaviour
{
public void Dosomething(){
}
}
public class something2 : MonoBehaviour
{
public void Dosomething(){
}
}
public class callingDoSometing
{
public void callALLDosomething(){
GameObject g1 = new GameObject();
g1.AddComponent<something1>();
GameObject g2 = new GameObject();
g2.AddComponent<something1>();
GameObject g3 = new GameObject();
g3.AddComponent<something2>();
GameObject g4 = new GameObject();
g4.AddComponent<something2>();
...
g1.SendMessage("Dosomething");
g2.SendMessage("Dosomething");
g3.SendMessage("Dosomething");
g4.SendMessage("Dosomething");
}
}
Just be aware that doing this will call Dosomething on every MonoBehaviour on that gameobject.
If you want to be specific about which MonoBehaviour to call on and/or have the references to the MonoBehaviours specifically, you can use MonoBehaviour.Invoke:
public class something1 : MonoBehaviour
{
public void Dosomething(){
}
}
public class something2 : MonoBehaviour
{
public void Dosomething(){
}
}
public class callingDoSometing
{
public void callALLDosomething(){
GameObject g1 = new GameObject();
MonoBehaviour m1 = g1.AddComponent<something1>();
GameObject g2 = new GameObject();
MonoBehaviour m2 = g2.AddComponent<something1>();
GameObject g3 = new GameObject();
MonoBehaviour m3 = g3.AddComponent<something2>();
GameObject g4 = new GameObject();
MonoBehaviour m4 = g4.AddComponent<something2>();
...
m1.Invoke("Dosomething",0f);
m2.Invoke("Dosomething",0f);
m3.Invoke("Dosomething",0f);
m4.Invoke("Dosomething",0f);
}
}
I have void Start() with string snapshotJson declared inside of it, and I have private void LoadGameData() that needs to call the value of snapshotJson. Declaring snapshotJson public doesn't work, I assume because of void. From what I read I should be using getters and setters, but I have no idea how they work and every guide I've read explaining it makes it seem very simple, but they explain it so simply I don't understand how exactly I'm supposed to use it, or how I can call the value after using the get/set functions.
Could anyone explain how I can get the variable from one class to another? In my code, LoadGameData isn't able to call the value of snapshotJson, I'm not sure what I'm missing.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using System.IO;
using Firebase;
using Firebase.Unity.Editor;
using Firebase.Database;
using System;
public class DataController : MonoBehaviour
{
private RoundData[] allRoundData;
private PlayerProgress playerProgress;
[Serializable]
public class FirebaseStart : MonoBehaviour
{
public string snapshotJson { get; set; }
void Start()
{
// Set up the Editor before calling into the realtime database.
FirebaseApp.DefaultInstance.SetEditorDatabaseUrl("https://FIREBASEDATABASE");
// Get the root reference location of the database.
DatabaseReference reference =
FirebaseDatabase.DefaultInstance.RootReference;
FirebaseDatabase.DefaultInstance
.GetReference("allRoundData")
.GetValueAsync().ContinueWith(task => {
if (task.IsFaulted)
{
// Handle the error...
}
else if (task.IsCompleted)
{
// DataSnapshot snapshot = task.Result;
snapshotJson = JsonUtility.ToJson(task.Result);
}
});
}
}
// Use this for initialization
void Start ()
{
DontDestroyOnLoad(gameObject);
LoadGameData();
LoadPlayerProgress();
SceneManager.LoadScene("MenuScreen");
}
public RoundData GetCurrentRoundData()
{
return allRoundData [0];
}
public void SubmitNewPlayerScore(int newScore)
{
if (newScore > playerProgress.highestScore)
{
playerProgress.highestScore = newScore;
SavePlayerProgress();
}
}
public int GetHighestPlayerScore()
{
return playerProgress.highestScore;
}
// Update is called once per frame
void Update () {
}
private void LoadPlayerProgress()
{
playerProgress = new PlayerProgress();
if (PlayerPrefs.HasKey("highestScore"))
{
playerProgress.highestScore = PlayerPrefs.GetInt("highestScore");
}
}
private void SavePlayerProgress()
{
PlayerPrefs.SetInt("highestScore", playerProgress.highestScore);
}
public void LoadGameData()
{
GameData loadedData = JsonUtility.FromJson<GameData>(snapshotJson);
Console.WriteLine(snapshotJson);
allRoundData = loadedData.allRoundData;
}
The LoadGameData() method cannot access it from the Main() method because it is local to that function scope. However, you can pass the value from the Main() method to the LoadGameData() using the code below:
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
private static void LoadGameData(String input) {
// Do something inside your input here.
}
public static void Main() {
Start();
}
public static void Start()
{
string snapshotJson = "Sample data";
// Same Class Call
LoadGameData(snapshotJson);
// Other Class Call
var otherClassInstance = new TestClass();
otherClassInstance.LoadGameData(snapshotJson);
}
}
public class TestClass {
public void LoadGameData(String input) {
// Do something inside your input here.
}
}
Assuming you refer to methods instead of classes (or rather: sharing data between objects), this is what you could do. Here's an example of a dedicated class for your Game objects, with SnaphopJson being a public property that can be accessed and changed from any other object. Changing the setter to private would ensure only it can only be read from anything but objects of this class.
public class Game
{
public string SnapshotJson { get; set; }
private void LoadGameData()
{
// load the json, e.g. by deserialization
SnapshotJson = "{}";
}
public void Start()
{
// access the content of your snapshot
var s = SnapshotJson;
}
}
If the variable snapshotJson is declared inside the body of the Start method, it will only be accessible within that method. If you want the variable to be accessible in other methods of your class, you may want to declare it as a member variable. This is how it looks like. You would need to declare it as a public property only if you need to access the value of snapshotJson outside of your class instance.
public class MyClass
{
string snapshotJson;
private void Start()
{
// Assign value to snapshotJson here
snapshotJson = "foo";
}
private void LoadGameData
{
// Use value of snapshotJson here
string s = snapshotJson;
}
}
I am trying to make a few objects and classes interact.
I have two classes. Code is similar. But in class Building_main after object is initialized in Start() I can reuse it in functions and in class House_main I can not (object is null).class Building_main is a child of class House_main.
What am I doing wrong?
First class :
public class Building_main : MonoBehaviour {
public string owner;
public string producedGoodName;
private Building_goods goods;
private House_main house;
void Start () {
goods = this.transform.Find("Building_goods").GetComponent<Building_goods>();
house = this.transform.parent.gameObject.GetComponent<House_main> ();
UpdateHouseInfo ();
}
void UpdateHouseInfo () {
// reusing objs (house, goods) no error
house.UpdateGoodInfo (goods.GetGoodByName("sword"), "sword");
}
Second class :
public class House_main : MonoBehaviour {
public string owner;
private House_goods goods;
void Start () {
// obj (goods) is not null
goods = this.transform.Find("House_goods").GetComponent<House_goods>();
// i can use
// goods.AddAmountToGoodByName (value, name);
}
public void UpdateGoodInfo (int value, string name) {
// obj (goods) is null
goods.AddAmountToGoodByName (value, name);
}
}
Looks like my child class ( class Building_main ) Start() function is executing before parent class ( class House_main ) Start() function.
So in class House_main object goods is not yet assigned when I am calling function UpdateGoodInfo, because I am calling it using class Building_main Start()
`class Building_main {
Start() {
UpdateHouseInfo ();
}
}`
Didn't know this.
Is using a switch on object types really the main way of calling a common function of stored references to class objects? It doesn't have to be a 'object' value type.
using System;
public class MainClass { public void Main() { print "hello world"; } }
public class SubClassOne : MainClass { }
public class SubClassTwo : MainClass { }
public class Storer
{
public void Main() {
object[] objects = new object[2];
objects[0] = new SubClassOne();
objects[1] = new SubClassTwo();
for(i=0;i<2;i++)
{
switch(objects[i].GetType().ToString())
{
case: "SubClassOne":
SubClassOne subclass = objects[i];
subclass.Main();
break;
case: "SubClassTwo":
SubClassTwo subclass = objects[i];
subclass.Main(); //Could probably call after the switch
break;
}
}
}
}
Note: Code not parsed, so there may be serious errors.
"Stringly" typed object oriented code is such a bad idea. You (almost) never need to know the type of an object via a string.
Changing your "print" to Console.WriteLine and main to this works fine
MainClass[] stuff = new MainClass[2];
stuff[0] = new SubClassOne();
stuff[1] = new SubClassTwo();
foreach(var item in stuff)
{
item.Main();
}
If the problem is you are determined to use an array of object, AlexH has answered.
In that case, I suggest to use as keyword to perform a safe cast operation :
using System;
public class MainClass { public void Main() { print "hello world"; } }
public class SubClassOne : MainClass { }
public class SubClassTwo : MainClass { }
public class Storer
{
public void Main() {
object[] objects = new object[2];
objects[0] = new SubClassOne();
objects[1] = new SubClassTwo();
for(i=0;i<2;i++)
{
var myMainClass = objects[i] as MainClass;
if (myMainClass != null)
{
myMainClass.Main();
}
}
}
}
As wudzik said it should be even better to declare objects as a MainClass array
There are many ways of solving this in a nice way, depends on:
If you know types and there are not too much of them:
Use LINQ OfType<>(). For more details see MSDN
foreach (var item in objects.OfType<SubClassOne>())
{
item.Main();
}
foreach (var item in objects.OfType<SubClassTwo>())
{
item.Main();
}
If there are many types, just introduce common interface
interface ISharedApi
{
void Main();
}
class SubClassOne : ISharedApi
class SubClassTwo : ISharedApi
And implement this/mark each type by it, then you just need single loop:
var objects = new List<ISharedApi>();
objects.Add(new SubClassOne());
objects.Add(new SubClassTwo());
foreach (var item in objects)
{
item.Main();
}
You should implement a more object oriented solution. Instead of creating an array consisting of objects you should make MainClass abstract and define an abstract method Main. After that you should implement Main in you sublclasses.
In this way you can exchange your code to:
using System;
public abstract class MainClass { public abstract void Main(); }
public class SubClassOne : MainClass {
public override void Main() { print "SubClassOne, hello world"; }
}
public class SubClassTwo : MainClass {
public override void Main() { print "SubClassTwo, hello world"; }
}
public class Storer
{
public void Main() {
MainClass[] objects = new MainClass[2];
objects[0] = new SubClassOne();
objects[1] = new SubClassTwo();
foreach(MainClass mc in objects)
{
mc.Main();
}
}
}
I have something like this:
public class Ship
{
public void PositionX_pixels_set1(float _position_x){position_x = _position_x;}
public class Engine : Ship
{
public int engines() { return 5; }
public class Piston
{
public int pistons(){return 5;}
}
}
}
void Main
{
Ship ship = new Ship()
int a = ship.Engine.Piston.pistons;//why this not working?
}
I don't know what I'm doing wrong. Why isn't "ship.Engine.Piston.pistons" working?
Because Engine is type inside the Ship class, and its member.
To fix this can do something like:
public class Ship
{
public void PositionX_pixels_set1(float _position_x){position_x = _position_x;}
private void Engine _myEngine = new Engine(); //DEFINE ENGINE MEMBER
public Engine MyEngine { //DEFINE A PROPERTY TO ACCESS THAT MEMBER
get {
return _myEngine;
}
}
public class Engine : Ship
{
public int engines() { return 5; }
private Piston _myPiston = new Piston();//DEFINE PISTON MEMBER
public Piston MyPiston {//DEFINE A PROPERTY TO ACCESS THAT
get {
return _myPiston ;
}
}
public class Piston
{
public int pistons(){return 5;}
}
MEMBER
}
}
and after use it like:
int a = ship.MyEngine.MyPiston.pistons
You must initiate an object of your sub type (Nested type) in order to access its method, in your case you are not creating any object of your nested types so you can not access its methode.
While you create a new Ship() you are not creating any Engine or Piston, so you can not access the methode Pistons() of the non existing object.