I'm experiencing a sort of bug in Unity, probably due to the fact I'm almost new to it:
I have a MonoBehaviour object that correctly lives in memory.
For sake of code organization, this object have two members of standard System.Object classes which needs to be created by a new call.
class A
{
// ...
}
class B
{
// ...
}
class Status : MonoBehaviour
{
A m_AVar;
B m_BVar;
public A AVar
{
get {return m_AVar;}
protected set { m_AVar = value; }
}
public B BVar
{
get { return m_BVar; }
protected set { m_BVar = value; }
}
void Awake()
{
// SingletonImplementation
}
void Start()
{
m_AVar = new A();
m_BVar = new B();
}
At some point in the game someone decides to call my Status.ExecuteSomeAction():
public void ExecuteSomeAction()
{
AVar.DoSome();
BVar.DoSomethingElse();
}
and everything go fine. While at the end by a UIButton.OnClickEvent:
public void ExecuteOnClickAction()
{
AVar.Foo();
}
But no matter what AVar result null. Reading left and right I have the feeling that there's something under the hood with those System.Object which I still don't get.
Where am I doing wrong?
I had a similar problem myself some time ago.
When the singleton pattern creates a new instance of this class (Status) then the links to the UI-Objects won't be created.
To solve this problem create a class which is responsible for handling the UI. This class will then call your Status class.
Another way is to change the singleton pattern to your needs. In my case I simply wrote this:
public static Status Instance { get; set; }
public Awake()
{
Instance = this;
}
This may be a bit sloppy because I will get problems if there is more than one instance of this class but it does the job.
Related
I recently decided to make a command console for my game, and then proceeded to make some groundwork. My issue is I cannot use it to change any relevant variables, as I have gotten stuck trying to get references to the classes where said variables are stored.
I have an abstract class for my command:
public abstract class Command
{
public abstract void Execute(string[] args);
}
Then I have a class deriving from above class for my command
public class RunesAdd : Command
{
public override void Execute(string[] args)
{
int number;
if(args.Length == 1 && int.TryParse(args[0], out number))
{
Debug.Log(number);
RunCtr.runes += number;
}
else
{
ConCtr.addLogEntry("Incorrect syntax, correct syntax is: runes.add <runes>");
}
}
}
and finally my registry of commands
public class CommandRegistry
{
private Dictionary<string, Command> _commands;
public CommandRegistry()
{
_commands = new Dictionary<string, Command>();
}
public void RegisterCommand(string name, Command command)
{
if (_commands.ContainsKey(name))
{
Debug.Log("Created command already exists");
}
_commands[name] = command;
}
public void RegisterAllCommands()
{
RegisterCommand("testcommand", new TestCommand());
RegisterCommand("runes.add", new RunesAdd());
}
public bool ExecuteCommand(string commandName, string[] args)
{
if (_commands.ContainsKey(commandName) == false)
return false;
_commands[commandName].Execute(args);
return true;
}
}
My problem is that I am unable to get a reference to my class with the variable for runes. I first tried to get a reference to the class in the Command class, so that those variables would be available in all children, but in order to do that I must make a method to actually assign those references, which would look like this:
public void GetReferences()
{
controllerObject = GameObject.FindGameObjectWithTag("Controller Object");
RunCtr = controllerObject.GetComponent<Runes_Controller>();
ConCtr = controllerObject.GetComponent<Console_Controller>();
}
The issue here is that since I cannot get a reference the Command class (due to it being abstract) in any of my monobehavior scripts which have the void Start() method, I cannot actually execute this method to assign the references. I then tried to make another class called GetReferences, which looks like this:
public class GetReferences
{
public GameObject controllerObject;
public Runes_Controller RunCtr;
public Console_Controller ConCtr;
public void GetReferencesMethod()
{
controllerObject = GameObject.FindGameObjectWithTag("Controller Object");
RunCtr = controllerObject.GetComponent<Runes_Controller>();
ConCtr = controllerObject.GetComponent<Console_Controller>();
}
}
Then I made the Command class derive from my GetReferences class, called the GetReferencesMethod() from a monobehavior script on start. Doing this I no longer get an error for not having assigned my classes to references, but whenever I try to edit the values it just does nothing. I have been searching the web for 2 hours now, but no dice. If I explained myself poorly please let me know. Any help is much appreciated, and thanks in advance!
Ok from what I understand is that you are trying to get your Command class using the GetComponent<> method. I might be wrong on this, so correct me if I am wrong.
If it is, then the issue is GetComponent<> only works with MonoBehaviour derived classes. Meaning you have to implement your class as a MonoBehaviour, which should be as simple as this:
public abstract class Command : MonoBehaviour {...}
EDIT
After reading your comments I believe you can use of the a Singleton pattern.
If you place your RuneController & CommandController on the same object and add another class called GameManager or InGameManager.
Then you can use a singleton pattern to access it.
public class GameManager
{
public GameManager Instance { get; private set; }
public RuneController RuneController { get; private set; }
public CommandController CommandController { get; private set; }
void Awake ()
{
// If there is an instance, and it's not me, delete myself.
if (Instance != null && Instance != this)
{
Destroy(this);
}
else
{
Instance = this;
}
}
void Start()
{
this.RuneController = GetComponent<RuneController>();
this.CommandController = GetComponent<CommandController>()
}
}
So the usage will look as follow:
GameManager.Instance.RuneController.Execute(command);
I have classes as follow one is SuperClass which is inherited by ChildClass and Child1Class
public class SuperClass
{
public new int Superclassprop = 2;
public virtual void play()
{
Console.WriteLine("SuperClass");
}
}
public class ChildClass : SuperClass
{
public new int Childclassprop = 2;
public override void play()
{
Console.WriteLine("ChildClass");
}
}
public class Child1Class : SuperClass
{
public new int Childclassprop = 3;
public override void play()
{
Console.WriteLine("Child1Class");
}
}
Now when i create an object something like below i don't understand what is the difference between these. i had read a huge bunch of blogs related to this but i didn't find any justifiable answer please help me to understand what actually is happening here or suggest me a good blog or article including on SO where i can understand a whole concept behind this why we need this where the actual real time use of these concept?
SuperClass obj = new SuperClass();
SuperClass obj1 = new ChildClass();
I have attached screenshot of watch which is generating on Run-Time why there is a obj1 consisting all properties but i can access only SuperClassprop?
Thanks in advance any help will be really appreciated.
Here is the more practical example of your topic:
using System;
public class Music
{
public virtual string play()
{
return "Play Music";
}
}
public class Drum : Music
{
public override string play()
{
return "Play Drums";
}
}
public class Piano : Music
{
public override string play()
{
return "Play Piano";
}
}
public class PlayMusicService
{
private readonly Music _musicContext;
public PlayMusicService(Music musicContext)
{
this._musicContext = musicContext;
}
public string PlayAlbum()
{
return _musicContext.play();
}
}
public class Program
{
public static void Main()
{
string whatPlayed = "";
Drum drums = new Drum();
PlayMusicService music1 = new PlayMusicService(new Drum());
whatPlayed = music1.PlayAlbum();
Console.WriteLine(whatPlayed);
Piano piano = new Piano();
PlayMusicService music2 = new PlayMusicService(new Piano());
whatPlayed = music2.PlayAlbum();
Console.WriteLine(whatPlayed);
}
}
Output:
Play Drums
Play Piano
i don't understand what is the difference between these.
One of the main differences is the constructor call
SuperClass obj = new SuperClass();
SuperClass obj1 = new ChildClass();
In the case of obj1 the ChildClass constructor is called after the SuperClass constructor and the field and property initialisation is done also for the property Childclassprop
consisting all properties but i can access only SuperClassprop?
The variable obj1 is still of type SuperClassprop so at compile time you are only allowed to see and use those variables that belong to this class. If you want to actually access the variables of ChildClass you will have to cast it to the proper type:
var r = (obj1 as ChildClass).Childclassproput;
why we need this where the actual real time use of these concept?
One scenario that comes to my mind is : it might be that at compile time it is not clear which class has to be instantiated. But this is decided at runtime. But you need already a variable to write the call of the specific play() method. At runtime it will be decided which method is called in the end.
SuperClass obj = new SuperClass();
bool condition = false;
if (condition)
{
obj = new ChildClass();
}
else
{
obj = new ChildClass1();
}
// now just call the method and the proper method will be called
obj.play();
At the moment I have the following class.
class BaseClass : IDisposable
{
private static List<BaseClass> instances = new List<BaseClass>();
protected BaseClass()
{
instances.Add(this);
}
~BaseClass()
{
Dispose();
}
public void Dispose()
{
instances.Remove(this);
}
}
So the lifetime of every class that inherit the BaseClass is infinitely until I close the program or I will call Dispose explicity.
Can I prevent this behaviour, so that lifetime is back to normal? (of course without removing the possibility to access the derived objects, otherwise my question make no sense)
I add the static List, to handle various actions to all classes that inherit BaseClass.
Edit
class DerivedClass : BaseClass
{
}
//This case works
using (DerivedClass _dc = new DerivedClass())
{
//Do something with object
}
//This object will live forever, because it is internally in the static list
//That behaviour is not desired
DerivedClass dc = new DerivedClass();
How I can get the bahaviour that DerivedClass dc calls his destructor after the normal lifetime (as it would not be in the list)?
Background
I want to fill the Properties of the derived classes with values from a config file and do it in base class. But if the config file changed, I have to change all properties of alll derived classes. So if you know a way to get all objects that implements the base class and needs to be changed, let me know it.
Update
Solution 1: Based on my question
With help from Steve Mitcham (Go to post) I found out how I can make a weak reference with few lines of code:
class BaseClass : IDisposable
{
private static List<GCHandle> handles = new List<GCHandle>();
protected BaseClass()
{
this.handle = GCHandle.Alloc(this, GCHandleType.Weak);
handles.Add(this.handle);
}
~BaseClass()
{
Dispose();
}
public void Dispose()
{
if (handle.IsAllocated)
{
//Do Something more to Dispose the Object
//...
handle.Free();
handles.Remove(handle);
}
}
public void DoSomethingWithTheList()
{
foreach (GCHandle handle in handles)
{
BaseClass bc = (BaseClass)handle.Target;
//Do something
}
}
}
Now If I call GC.Collect(); it will collect my unused derived classes (so I think the garbage collector will collect my objects normally as well) because the object itself has no reference in a list.
Thank you!
Solution 2: Subsrciber / Broadcaster Pattern
With this pattern it is simple too. Additionally the derived class can get the info if the values are changed.
Thank you Alireza (Goto post) and Thangadurai.
class ConfigurationBroadcaster
{
string path = "";
public string Path
{
get { return path; }
set
{
bool changed = path != value;
path = value;
if(changed)
if (ChangedConfigurationValues != null)
{
Delegate[] invocationList = ChangedConfigurationValues.GetInvocationList();
foreach (var item in invocationList)
{
Type t = item.Target.GetType();
PropertyInfo[] pInfos = t.GetProperties();
foreach (PropertyInfo pInfo in pInfos)
{
//new object() have to be the value from config file
//5 is used to set Width and Height from BroadcastSubscriber for this example
pInfo.SetValue(item.Target, 5/* new object()*/, null);
}
}
ChangedConfigurationValues(this, new EventArgs());
}
}
}
public event EventHandler ChangedConfigurationValues;
}
class BaseBroadcastSubscriber
{
ConfigurationBroadcaster broadcaster;
protected BaseBroadcastSubscriber(ConfigurationBroadcaster broadcaster)
{
this.broadcaster = broadcaster;
this.broadcaster.ChangedConfigurationValues += new EventHandler(broadcaster_ChangedConfigurationValues);
}
void broadcaster_ChangedConfigurationValues(object sender, EventArgs e)
{
Console.WriteLine("Configuration values changed");
}
}
class BroadcastSubscriber : BaseBroadcastSubscriber
{
int width,height;
public int Width
{
get { return width; }
set { width = value; }
}
public int Height
{
get { return height; }
set { height = value; }
}
public BroadcastSubscriber(ConfigurationBroadcaster broadcaster)
: base(broadcaster)
{
}
}
Without seeing more of your program it would be difficult to determine whether your approach could be improved. However, without fundamentally changing your design I would use WeakReferences to track your objects. The UpdateClasses method is to simulate your reconfigure action.
class BaseClass : IDisposable
{
private WeakReference<BaseClass> myReference;
private static List<WeakReference<BaseClass>> instances = new List<WeakReference>();
public static UpdateClasses(MyData stuff)
{
foreach(var ref in instances)
{
BaseClass target;
if (ref.TryGetTarget(out target))
{
// code to update target here
}
}
}
protected BaseClass()
{
myReference = new WeakReference<BaseClass>(this,true);
instances.Add(myReference);
}
~BaseClass()
{
Dispose();
}
public void Dispose()
{
instances.Remove(myReference);
}
}
The weak references will not keep your objects alive. When they get garbage collected they will remove their references from the instance list. Note, however, that this implementation will cause your objects to stay alive in the garbage collector longer than normal due to the requirement for the finalizer, and this may decrease the performance of the application over time.
Despite Steve Mitchman's answer, you could design a broadcaster class providing an event which gets fired whenever a change in config file is detected. Derived classes (objects) could subscribe to this event and unsubscribe upon being get GC collected or finalized. This approach follows open/closed principle very well.
When your BaseClass instance is off, that is both when you call the Dispose and when the instance itself is destroyed. These cases are normal.
I'm working on very simple Roguelike game (just for myself) and get a question:
As it is not possible to create a cross-class struct-object (entity in the game case) that could be accessible from any class of my program, what to use to create a cross-class object? I was thinking of something like storing all newly created object (enities) in a static object array, but I guess there is more simple solution on this problem.
Question itself: How to create a cross-class accessible object(s) with your own properties?
Thanks everybody, I found what I was searching for.
It seems like you tried passing around a value type (a struct) between different classes and you noticed that when you update the value in one place it doesn't change the value in another place.
That's the basic difference between value types and reference types.
If you are creating the struct yourself you may want to instead define it as a class.
If not, you could wrap all your structs in a class and pass the class around as your state object.
If all you have is simply a list of the same type of struct (like Points), just pass the List itself around. C# collections are implemented as classes.
public class GameState
{
public Point PlayerLocation { get; set; }
public List<Point> BulletPoints { get; set; }
public double Health { get; set; }
}
Now you can create a GameState and pass it around to different classes:
public class Game
{
private GameState _state = new GameState();
private BulletUpdater _bulletUpdater = new BulletUpdater();
public void Update()
{
_bulletUpdater.UpdatePoints(_state);
// Points have now been modified by another class, even though a Point is a struct.
}
}
public class BulletUpdater
{
public void UpdatePoints(GameState state)
{
for (int i = 0; i < state.BulletPoints.Count; i++)
{
Point p = state.BulletPoints[i];
state.BulletPoints[i] = new Point(p.X + 1, p.Y + 1);
}
}
}
Just remember in the above code if I were to write:
Point p = state.BulletPoints[i];
p.X += 1;
p.Y += 1;
That wouldn't affect the original point! When you read a value type from a list or from a class into only copies the value into a local variable. So in order to reflect your changes in the original object stored inside the reference type you need to overwrite it like so:
state.BulletPoints[i] = p;
This same principal is why the following also will not work:
state.PlayerLocation.X += 5; // Doesn't do anything
state.PlayerLocation.Y += 5; // Also doesn't do anything
The compiler would tell you in this case that you are doing something wrong. You are only modifying the returned value of the property, not the backing field itself. You have to write it like so:
state.PlayerLocation = new Point(state.PlayerLocation.X + 5, state.PlayerLocation.Y + 5); // This works!
You can do the following:
Using IoC Framework, like Ninject. You can setup Ninject to create single instance for all usages.
The other option is to use Singleton pattern design pattern
And the third one is to use static property
It sounds like you want to use the Singleton pattern:
http://en.wikipedia.org/wiki/Singleton_pattern
Here is an example of what this would look like in C#:
public class Singleton
{
static Singleton()
{
Instance = new Singleton();
}
public static Singleton Instance { get; private set; }
}
It's possible. What about public and static class?
public static class CrossClassObject
{
public static object MyProperty { get; set; }
public static void MyMethod() {}
}
Of course this class should be placed in the same namespace that other ones.
How to use it?
class OtherClassInTheSameNamespace
{
private void SomeMethod()
{
var localVariable = CrossClassObject.MyProperty; // get 'cross-class' property MyProperty
CrossClassObject.MyMethod(); // execute 'cross-class' method MyMethod()
}
}
No idea what you are trying to achieve... but if you want a list of objects accessible 'cross-class', just make a static class with a list of objects and then when you reference your class from any other class, you will have access to its list of objects. Here is something like that:
public static class ObjectController
{
private static IList<object> existingObjects;
public static IList<object> ExistingObjects
{
get
{
if (existingObjects == null)
{
existingObjects = new List<object>();
}
}
}
}
public class MyObject
{
public MyObject()
{
ObjectController.ExistingObjects.Add(this);
}
public void Delete()
{
ObjectController.ExistingObjects.Remove(this);
}
}
Then you can add stuff like
MyObject newObj = new MyObject();
//// other stuff... This object should now be visible to whatever other class references ObjectController
newObj.Delete();
I have a method which should return a snapshot of the current state, and another method which restores that state.
public class MachineModel
{
public Snapshot CurrentSnapshot { get; }
public void RestoreSnapshot (Snapshot saved) { /* etc */ };
}
The state Snapshot class should be completely opaque to the caller--no visible methods or properties--but its properties have to be visible within the MachineModel class. I could obviously do this by downcasting, i.e. have CurrentSnapshot return an object, and have RestoreSnapshot accept an object argument which it casts back to a Snapshot.
But forced casting like that makes me feel dirty. What's the best alternate design that allows me to be both type-safe and opaque?
Update with solution:
I wound up doing a combination of the accepted answer and the suggestion about interfaces. The Snapshot class was made a public abstract class, with a private implementation inside MachineModel:
public class MachineModel
{
public abstract class Snapshot
{
protected internal Snapshot() {}
abstract internal void Restore(MachineModel model);
}
private class SnapshotImpl : Snapshot
{
/* etc */
}
public void Restore(Snapshot state)
{
state.Restore(this);
}
}
Because the constructor and methods of Snapshot are internal, callers from outside the assembly see it as a completely opaque and cannot inherit from it. Callers within the assembly could call Snapshot.Restore rather than MachineModel.Restore, but that's not a big problem. Furthermore, in practice you could never implement Snapshot.Restore without access to MachineModel's private members, which should dissuade people from trying to do so.
Can MachineModel and Snapshot be in the same assembly, and callers in a different assembly? If so, Snapshot could be a public class but with entirely internal members.
I could obviously do this by
downcasting, i.e. have CurrentSnapshot
return an object, and have
RestoreSnapshot accept an object
argument which it casts back to a
Snapshot.
The problem is that somebody could then pass an instance of an object which is not Snapshot.
If you introduce an interface ISnapshot which exposes no methods, and only one implementation exists, you can almost ensure type-safety at the price of a downcast.
I say almost, because you can not completely prevent somebody from creating another implementation of ISnapshot and pass it, which would break. But I feel like that should provide the desired level of information hiding.
You could reverse the dependency and make Snapshot a child (nested class) of MachineModel. Then Snapshot only has a public (or internal) Restore() method which takes as a parameter an instance of MachineModel. Because Snapshot is defined as a child of MachineModel, it can see MachineModel's private fields.
To restore the state, you have two options in the example below. You can call Snapshot.RestoreState(MachineModel) or MachineModel.Restore(Snapshot)*.
public class MachineModel
{
public class Snapshot
{
int _mmPrivateField;
public Snapshot(MachineModel mm)
{
// get mm's state
_mmPrivateField = mm._privateField;
}
public void RestoreState(MachineModel mm)
{
// restore mm's state
mm._privateField = _mmPrivateField;
}
}
int _privateField;
public Snapshot CurrentSnapshot
{
get { return new Snapshot(this); }
}
public void RestoreState(Snapshot ss)
{
ss.Restore(this);
}
}
Example:
MachineModel mm1 = new MachineModel();
MachineModel.Snapshot ss = mm1.CurrentSnapshot;
MachineModel mm2 = new MachineModel();
mm2.RestoreState(ss);
* It would be neater to have Snapshot.RestoreState() as internal and put all callers outside the assembly, so the only way to do a restore is via MachineModel.RestoreState(). But you mentioned on Jon's answer that there will be callers inside the same assembly, so there isn't much point.
This is an old question, but i was looking for something very similar and I ended up here and between the information reported here and some other I came up with this solution, maybe is a little overkill, but this way the state object is fully opaque, even at the assembly level
class Program
{
static void Main(string[] args)
{
DoSomething l_Class = new DoSomething();
Console.WriteLine("Seed: {0}", l_Class.Seed);
Console.WriteLine("Saving State");
DoSomething.SomeState l_State = l_Class.Save_State();
l_Class.Regen_Seed();
Console.WriteLine("Regenerated Seed: {0}", l_Class.Seed);
Console.WriteLine("Restoring State");
l_Class.Restore_State(l_State);
Console.WriteLine("Restored Seed: {0}", l_Class.Seed);
Console.ReadKey();
}
}
class DoSomething
{
static Func<DoSomething, SomeState> g_SomeState_Ctor;
static DoSomething()
{
Type type = typeof(SomeState);
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(type.TypeHandle);
}
Random c_Rand = new Random();
public DoSomething()
{
Seed = c_Rand.Next();
}
public SomeState Save_State()
{
return g_SomeState_Ctor(this);
}
public void Restore_State(SomeState f_State)
{
((ISomeState)f_State).Restore_State(this);
}
public void Regen_Seed()
{
Seed = c_Rand.Next();
}
public int Seed { get; private set; }
public class SomeState : ISomeState
{
static SomeState()
{
g_SomeState_Ctor = (DoSomething f_Source) => { return new SomeState(f_Source); };
}
private SomeState(DoSomething f_Source) { Seed = f_Source.Seed; }
void ISomeState.Restore_State(DoSomething f_Source)
{
f_Source.Seed = Seed;
}
int Seed { get; set; }
}
private interface ISomeState
{
void Restore_State(DoSomething f_Source);
}
}