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.
Related
I'm looking to implement a certain behavior but I'm not sure how to implement it.
Given a base class :
public class Base
{
void Start() { }
void Update() { }
}
And these two classes which inherit it.
public class Behavior1 : Base
{
private int member;
void Start() { member = 0; }
void Update() { member++; }
}
public class Behavior2 : Base
{
private string name;
void Start() { name = "some string"; }
void Update() { if(name) { Console.WriteLine(name) } }
}
And then a final class which I wish to inherit the logic of the two sub classes.
public class Child : Base // ? Behavior1, Behavior2
{
void Start() { } // logic and members implemented but don't need to be referenced
void Update() { }
}
How would I go about having the Child class implement the two Behavior classes? I don't think you can inherit more than one class at a time so I can't do that. Is there another construct which can accomplish this?
Wihtout enter to valorate the inheritance, that probably need some think as you can read in the comments, you can do something like this if you want use both behaviors ni a class that doesn't inherith them:
public class Child : Base
{
private readonly Behavior1 _behavior1;
private readonly Behavior2 _behavior2;
public Child()
{
this._behavior1 = new Behavior1();
this._behavior2 = new Behavior2();
}
public override void Start()
{
this._behavior1.Start();
}
public override void Update()
{
this._behavior2.Update();
}
}
You can also inherith from Behavior1 and only add Behavior2 as a field:
public class Child : Behavior1
{
private readonly Behavior2 _behavior2;
public Child()
{
this._behavior2 = new Behavior2();
}
public override void Update()
{
this._behavior2.Update();
}
}
But, as I said, is probably that you find a better solution thinking about your models and their composition/inheritance.
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;
}
}
}
I'm new in Unity. I have started developing a basic game while learning but the following errors arise when trying to chain the states(it's for doing a menu system).
The errors seems to be the same:
Argument 1: cannot convert from 'UIManager' to 'GameStateAbstract'
Argument 1: cannot convert from 'UIManager' to 'GameStateAbstract' //Happends same file in another line
Argument 1: cannot convert from 'GameManager' to 'GameStateAbstract'
context(UIManager):
public class UIManager : MonoBehaviour
{
#UIManager Singletons
private static UIManager _instance;
public static UIManager Instance
{
get
{
if (_instance == null)
{
Debug.LogError("UIManager is NULL");
}
return _instance;
}
}
#Fields
public GameObject gameOverPanel;
public GameObject onPlayOverlays;
public GameObject startMenuPanel;
public GameStateAbstract _currentState;
public readonly PlayStates onPlayStates = new PlayStates();
public readonly DeadStates onDeadStates = new DeadStates();
public readonly MenuStates onMenuStates= new MenuStates();
public void TransitionToState(GameStateAbstract state)
{
_currentState = state;
_currentState.EnterState(this);
}
public void Context(GameStateAbstract state)
{
_currentState.Conditions(this);
}
void Awake()
{
_instance = this;
TransitionToState(onMenuStates);
}
}
Abstract State:
public abstract class GameStateAbstract
{
public abstract void EnterState(GameStateAbstract layer);
public abstract void Update(GameStateAbstract layer);
public abstract void Conditions(GameStateAbstract layer);
}
Concrete State:
public class MenuStates : GameStateAbstract
{
public override void Update(GameStateAbstract layer)
{
}
public override void EnterState(GameStateAbstract layer)
{
}
public override void Conditions(GameStateAbstract layer)
{
}
}
GameManager:
public class GameManager : MonoBehaviour
{
void Update()
{
UIManager.Instance.CurrentState.Update(this);
}
}
Thanks for answering!
public abstract void Update(GameStateAbstract layer);
Your parameter is a ‘GameStateAbstract’ object but you are passing a ‘GameManager’ object:
UIManager.Instance.CurrentState.Update(this);
(this) in this instance is called from GameManager
Make sure you are passing valid parameters or else you will have compile errors.
Also abstract class should be extended with a child class and the child class should be used to create objects.
I'm having difficulty inheriting from a generic class that is itself inherited from a generic singleton.
I am trying to make an inventory base class that is a singleton and derive different inventory types from this with different derived items.
Code has been simplified for brevity.
public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
private static bool m_ShuttingDown = false;
private static object m_Lock = new object();
private static T m_Instance;
public static T Instance
{
get
{
if (m_ShuttingDown)
return null;
lock (m_Lock)
{
if (m_Instance == null)
{
m_Instance = (T)FindObjectOfType(typeof(T));
if (m_Instance == null)
{
var singletonObject = new GameObject();
m_Instance = singletonObject.AddComponent<T>();
singletonObject.name = typeof(T).ToString() + " (Singleton)";
DontDestroyOnLoad(singletonObject);
}
}
return m_Instance;
}
}
}
private void OnApplicationQuit()
{
m_ShuttingDown = true;
}
private void OnDestroy()
{
m_ShuttingDown = true;
}
}
public class Inventory<T> : Singleton<Inventory<T>> where T : Item
{
...
}
public class EquipmentInventory : Inventory<Equipment>
{
...
}
public class Item : ScriptableObject
{
public string Name = "Item";
}
public class Equipment : Item
{
public string Name = "Equipment";
}
I can't access the Instance;
private EquipmentInventory equipmentInventory;
private Inventory<Item> inventory;
public void Run()
{
var cachedInventory = Inventory<Item>.Instance; //returns null
var cachedEquipmentInventory = EquipmentInventory.Instance as EquipmentInventory; //returns null
}
Both statements return null.
The purpose of this, is that each inventory type will be a singleton and each type of inventory will be implent different item types, so that the base inventory will use the Item type, while the Equipment inventory will be implemented using the Equipment item type.
Here is an alternate method, which seems to solve this
public abstract class Inventory<T, TClass>
: Singleton<TClass> where TClass
: MonoBehaviour where T : Item
{
}
public class EquipmentInventory : Inventory<Equipment, EquipmentInventory>
{
}
I haven't fully tested this yet with actual code, but will update when I have tested it more thoroughly
Please assist.
The main issue is caused by
public class Inventory<T> : Singleton<Inventory<T>> : where T : Item { }
Here you "pass in" the generic type Iventory<T> into the Singleton even though later you explicitly inherit from that Inventory<T> class.
Here is one possible solution though it might seem like a bit strange workaround at first:
Make your Inventory take a second generic type, use the first one inside the class as needed and "forward" the second one to the Singleton<T> like e.g.
// Note how for the limitation via where you still can use the generic type
// which makes sure no other MonoBehaviour can be passed to TSelf by accident
public class Inventory<TItem, TSelf> : Singleton<TSelf> where TItem : Item where TSelf : Inventory<TItem,TSelf>
{
public TItem reference;
private void Awake()
{
if (!reference) reference = ScriptableObject.CreateInstance<TItem>();
}
}
Then in the implementation your pass additionally in your own final (non-generic) type so it can be properly "forwarded" to the Singleton<T> like e.g.
public class EquipmentInventory : Inventory<Equipment, EquipmentInventory> { }
Note that anyway this class has to be in a separated file called EquipmentInventory.cs otherwise it won't work as component in Unity.
This works now since now you explicitly pass in the type EquipmentInventory for TSelf which is then forwarded to the Signleton<T> so the return type of Instance is explicitly EquipmentInventory.
In general get used to rather have one script file for each individual class/type.
Additionally I would slightly alter your fields in Item and Equipment like e.g.
[CreateAssetMenu]
public class Item : ScriptableObject
{
[SerializeField] private string _name;
public string Name => _name;
private void Awake()
{
_name = GetName();
}
protected virtual string GetName()
{
return nameof(Item);
}
}
and
[CreateAssetMenu]
public class Equipment : Item
{
protected override string GetName()
{
return nameof(Equipment);
}
}
And this is how it looks like e.g.
public class Example : MonoBehaviour
{
public EquipmentInventory equipmentInventory;
[ContextMenu("Run")]
public void Run()
{
equipmentInventory = EquipmentInventory.Instance;
}
}
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);
}
}