I have no clue how to write a title correctly but what I mean is to make something like this:
public static MusicPlayer _Player = new MusicPlayer();
_Player.Play.Song(TestPath);
where MusicPlayer is a class and in that class I want to make something like property or another class I don't know how to call it, which will have two methods. My code for now:
public class MusicPlayer
{
//Variables, Methods and Properties in MusicPlayer
//And then Play which can have two tipes of play.
public static class Play
{
//This one should be called if I want to play one song
public static void Song(String _path)[...]
//And this one when I want to play from list, defined in MusicPlayer class
public static void List()[...]
}
}
You should do this:
public class MusicPlayer
{
public class Player
{
public static void Song(String _path)[...]
public static void List()[...]
}
private Player m_player = new Player();
public Player Play
{
get { return m_player; }
}
}
This defines a Player class in MusicPlayer. Also it creates a member variable of type Player and a property that allows you to access the Player instance from the outside using an instance of MusicPlayer:
var mplayer = new MusicPlayer();
mplayer.Play.Song(...);
If you do not want to create an instance of MusicPlayer, you could also make this static:
public class MusicPlayer
{
public class Player
{
public static void Song(String _path)[...]
public static void List()[...]
}
private static Player m_player = new Player();
public static Player Play
{
get { return m_player; }
}
}
You can now use MusicPlayer.Play.Song(...) without having to create an instance.
You can do something like that
public class MusicPlayer
{
public MusicPlayer()
{
Play = new Play();
}
public Play Play { get; private set; }
}
public class Play
{
//This one should be called if I want to play one song
public void Song(String _path){}
//And this one when I want to play from list, defined in MusicPlayer class
public void List() { }
}
And then using like
new MusicPlayer().Play.Song("");
Related
For example, there's two classes here.
Class One:
using UnityEngine;
using System.Collections.Generic;
public class One:MonoBehavior
{
private List<string> _assetBundleList;
private void Start()
{
InitializeList();
}
private void InitializeList()
{
//Add assetBundleList field some value.
}
public IEnumerator<string> GetEnumerator()
{
return _assetBundleList.GetEnumerator();
}
}
Class two:
public class Two:MonoBehavior
{
public GameObject gameObjectWithScriptOne;
private One _scriptOne;
private void Start()
{
scriptOne = gameObjectWithScriptOne.GetComponent<One>();
DoSomething();
}
private void DoSomething()
{
foreach(var assetBundle in scriptOne)
{
//Load asset
}
}
}
Script one is just like a manager things, I use this for storing asset bundle data, perhaps the list value will change. Script two must wait for initializing done. Is there any way to wait for it except adjusting script order?
It can be handled with easily creating a context that initialize things sequentially. In short you need to block the main thread.
Let's say you have a root or persistent scene that do must things like loading assets etc.
//The only object in the Root Scene.
public class RootContext : MonoBehaviour
{
private const string _playerAddress = "Player";
public void Awake()
{
//Load assets
//wait for assets loading
//instantiate things.
//new instantiated things can also initalize with this way.
var handle = Addressables.LoadAssetAsync<GameObject>(_playerAddress);
var asset = handle.WaitForCompletion();
var go = Instantiate(bla bla bla);
}
}
I think the what you want is a framework that organize things. You can look at Strange. It is MVCS + IoC framework. Addionality what you said about "when field or property initialization is done" with [PostConstruct] attribute with Strange.
[Inject(ContextKeys.CONTEXT)]
public IContext Context { get; set; }
/*Initialization of injections are guaranteed at here. Their initialization
is also quaranteed like this class.
*/
[PostConstruct]
public void Initalize()
{
}
I'd go with refactoring, but if this is not the case C# events might be the solution.
Class One
public class One:MonoBehavior
{
private List<string> _assetBundleList;
public event Func Initialized;
private void Start()
{
InitializeList();
}
private void InitializeList()
{
//Add assetBundleList field some value.
Initialized?.Invoke();
}
public IEnumerator<string> GetEnumerator()
{
return _assetBundleList.GetEnumerator();
}
}
Class Two:
public class Two:MonoBehavior
{
public GameObject gameObjectWithScriptOne;
private One _scriptOne;
private void Start()
{
scriptOne = gameObjectWithScriptOne.GetComponent<One>();
scriptOne.Initialized += DoSomething;
}
private void DoSomething()
{
foreach(var assetBundle in scriptOne)
{
//Load asset
}
}
}
Also, you should unsubscribe from events when disabling an object, but you'll figure it out by yourself.
I am making a basic shop system includes car name, price and buyable. I am saving data to a text file. When I replay, I can't get the last variables I've changed. But, if I refresh at Editor by CTRL+R and start the game, variables are loading correct. What am I doing wrong? I am new at storage and JSON issues. Thanks for answers...
Here is the code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using System;
public class GameHandler : MonoBehaviour
{
[Serializable]
public class Car
{
public string name;
public int price;
public bool unlocked;
}
[Serializable]
public class CarList{
public Car[] cars;
}
private Car cars = new Car();
public CarList myCars = new CarList();
//-------
public int chosenCar;
//-------
public TextAsset CARS;
//-------
private void Start() {
GetFromJSON();
}
private void Update() {
if(Input.GetKeyDown(KeyCode.L))
GetFromJSON();
if(Input.GetKeyDown(KeyCode.S))
SaveToJSON();
}
public void ChangeCarIndex(int a){
chosenCar = a;
}
//This is a button func.
public void ChangePrice(int a){
myCars.cars[chosenCar].price = a;
SaveToJSON();
}
public void GetCarName(){
Debug.Log(myCars.cars[chosenCar].name);
}
public void GetCarPrice(){
Debug.Log(myCars.cars[chosenCar].price);
}
public void SaveToJSON(){
string jsOutput = JsonUtility.ToJson(myCars);
File.WriteAllText(Application.dataPath + "/CARS.txt", jsOutput);
Debug.Log("SaveToJSON() called");
}
public void GetFromJSON(){
myCars = JsonUtility.FromJson<CarList>(CARS.text);
Debug.Log("GetFromJSON() called");
}
}
When running this in the editor try to add
public void SaveToJSON()
{
string jsOutput = JsonUtility.ToJson(myCars);
File.WriteAllText(Application.dataPath + "/CARS.txt", jsOutput);
Debug.Log("SaveToJSON() called");
#if UNITY_EDITOR
UnityEditor.AssetDatabase.Refresh();
#endif
}
Though actually this isn't really necessary! Afaik you could also simply set the text of the textasset:
public void SaveToJSON()
{
string jsOutput = JsonUtility.ToJson(myCars);
CARS.text = jsOutput;
Debug.Log("SaveToJSON() called");
}
BUT NOTE:
in general note that this makes only sense in the editor itself.
If you target to do this in an actually later built application you would rather go via a file in Application.persistentDataPath. Problem with that though: The data can easily be seen and edited by the user. So if this is anything sensitive you will need to go for a central database server with user login.
I have a class with a PictureBox created as followed:
public class Tile
{
public PictureBox tilePB = new PictureBox(); //properties don't matter in this case
}
I also have a class GameManager. This is like a referee.
I want to make it so the BackColor of Tile.tilePB can only be edited by Gamemanager and nothing else, and no other class.
I currently have a public PictureBox for Gamemanager (to edit) and a public get function for other classes, but I want to actually make this a valid system instead of what I have right now.
Is this even possible? Please include explenation for the required code.
EDIT: I ran into an issue that I hadn't thought off: class Gamemanager is a static class. I do everything in that class via public static functions. Is this still possible? Since this doesn't work.
You can't do this at compile time, but it can be done at runtime:
public class PictureBox
{
private Color _backColor;
public void SetBackColor(Color color)
{
//getting class type that called this method
var stackTrace = new StackTrace();
var stackFrames = stackTrace.GetFrames();
var callingFrame = stackFrames[1];
var method = callingFrame.GetMethod();
//checking if the class type is GameManager
if (!method.DeclaringType.IsAssignableFrom(typeof(GameManager)))
{
throw new FieldAccessException("Only GameManager can set the background color of a PictureBox!");
}
_backColor = color;
}
public Color BackColor => _backColor;
}
public class Tile
{
public PictureBox tilePB { get; set; }
}
//example GameManager class
public class GameManager
{
public void SetBackground()
{
var someTile = new Tile()
{
tilePB = new PictureBox()
};
var someColor = new Color();
someTile.tilePB.SetBackColor(someColor);
}
}
//example class that may want to set picturebox background color
public class MaliciousClass
{
public void SetBackground()
{
var someTile = new Tile()
{
tilePB = new PictureBox()
};
var someColor = new Color();
someTile.tilePB.SetBackColor(someColor);
}
}
Then somewhere:
var gm = new GameManager();
var mc = new MaliciousClass();
gm.SetBackground(); //this is fine
mc.SetBackground(); //this will throw an exception
If you don't want to throw an exception or you want to do something different when "not authorized" class is trying to access the SetBackColor method then just replace throw new FieldAccessException() with return or whatever you want.
Bare in mind the approach presented here is inefficent and it just presents that in can be done at runtime and nothing more than that.
Not sure if this is exactly what you are looking for, but I made this quick test and it seems to be able to differentiate the calling class:
class Program
{
static void Main(string[] args)
{
Type1 something1 = new Type1();
Type2 something2 = new Type2();
something1.runTest();
something2.runTest();
Console.ReadKey();
}
public class Type1
{
public void runTest()
{
Testing.edit(this);
}
}
public class Type2
{
public void runTest()
{
Testing.edit(this);
}
}
public static class Testing
{
public static void edit(object obj)
{
// This is where you test the calling class to make sure
// it is allowed to edit.
Console.WriteLine(obj.GetType().ToString());
}
}
}
The only way I can think of where you enforce this at compile time, end up being a bit complicated. I don't think you'll want to do this.
You can create an interface with properties/methods for everything that only the GameManager is allowed to do. You can implement this interface in a private inner class below Tile, and make sure the only way this object is created is by passing in a GameManager that receives it. Now, the only way the access can 'leak' is if the GameManager 'gives away' the object.
public class GameManager {
public void AddTile(Tile t, Tile.IManagerHook m) {
m.SomeProperty = "set from manager";
}
}
public class Tile
{
public object SomeProperty { get; private set; }
public Tile(GameManager manager) {
manager.AddTile(this, new ManagerHook(this));
}
public interface IManagerHook {
object SomeProperty {get; set;}
}
private class ManagerHook : IManagerHook {
private Tile _tile;
public ManagerHook(Tile t) {
_tile = t;
}
public object SomeProperty {
get{ return _tile.SomeProperty;}
set { _tile.SomeProperty = value; }
}
}
}
(seems) Simply not possible
After asking several programmers, the way I have coded everything and what I want seems to be simply impossible without immensely complicated code - to the point you are better off refacturing everything. Since class Gamemanager is a static class, there will be no instances of it so you can not check if the 'object' that called it is of class Gamemanager. this also doesn't work since Gamemanager is, agian, static.
This is a really simple structure question, but i don't know what is the best way to do this in C#.
I need a "base" class or something to allow me load diferent "levels" in the "level" object, and changing the name I can swith the class what I want to use.
Now i'm using a abstract class and instance of the childrens in this way:
using UnityEngine;
using System;
public class Level : MonoBehaviour {
public levelClass level;
public void initLevel(string className) {
Type t = Type.GetType(className);
level = (levelClass)Activator.CreateInstance(t, new object[] { });
level.Start();
}
void Start () {
Debug.Log("Levels: Start");
initLevel("worldTwo");
}
void Update () {
level.Update();
}
}
public abstract class levelClass {
public abstract void Start();
public abstract void Update();
}
public class worldOne : levelClass {
public override void Start() {
Debug.Log("worldOne: Start");
}
public override void Update() {
Debug.Log("worldOne: Update");
}
}
public class worldTwo : levelClass
{
public override void Start()
{
Debug.Log("worldTwo: Start!");
}
public override void Update()
{
Debug.Log("worldTwo: Update!");
}
}
But I think exists better ways to do, like store all classes in a list and call it or something similar. The part i don't like nothing is have some classes public in this file (I know i can split in other files, i'm trying to think only in a way to do this better)
I'm fairly new to object oriented programming and I still have trouble organizing my programs.
I'm making a simulation of a factory in c#. I have one instance of a Simulation class. When initialized, the constructor creates several instances of a Machine class.
The Simulation class has an event list. The Machine class has methods that need to add events to this list. Right now, the only way I see how to do this is to pass a reference of the simulation to the Machine constructor. However, these seems messy to me and I feel like there has got to be a better way of organizing this.
public class Simulation
{
public LinkedList<Event> event_list = new LinkedList<Event>();
public Simulation()
{
Machine m1 = new Machine(this);
Machine m2 = new Machine(this);
}
static void Main(string args[])
{
Simulation sim = new Simulation();
}
}
public class Machine
{
public Simulation sim;
public Machine(Simulation sim)
{
this.sim = sim;
}
public void Schedule_Event()
{
sim.event_list.AddLast(new Event(etc etc));
}
}
public class Event
{
}
Is there a way to add events to Simulation.event_list without having to pass the this reference? In a sense each Machine "belongs" to the Simulation class, and I want to show this somehow.
You can have a method in Machine that returns Event objects, then Simulation can take care of adding it to event_list:
public class Simulation
{
public LinkedList<Event> event_list = new LinkedList<Event>();
public Simulation()
{
Machine m1 = new Machine();
Machine m2 = new Machine();
event_list.AddLast(m1.GetEvent());
event_list.AddLast(m2.GetEvent());
}
static void Main(string args[])
{
Simulation sim = new Simulation();
}
}
public class Machine
{
public Machine() {}
public Event GetEvent()
{
return new Event(etc etc);
}
}
seems pretty much ok to me, I'd just hide the event_list implementation in the Simulation class:
public class Simulation
{
private LinkedList<Event> event_list = new LinkedList<Event>();
public void addEven(Event x) {event_list.Add(x); }
}
passing this in constructor is ok, if you really want to you can put a factory method in simulation:
public class Simulation
{
public Machine CreateNewMachine() { return new Machine(this); }
}
to just allow Machine m1 = Simulation.CreateNewMachine()
You could use a more Observer-pattern type approach, using Action<T>
Add a public action to Machine:
public class Machine
{
public Action<Event> EventAdded;
private void Schedule_Event()
{
if(EventAdded != null)
EventAdded(new Event());
}
}
And Subscribe to the action upon creation:
public class Simulation
{
public LinkedList<Event> event_list = new LinkedList<Event>();
public Simulation()
{
Machine m1 = new Machine() { EventAdded = AddEvent };
}
static void Main(string[] args)
{
Simulation sim = new Simulation();
}
public void AddEvent(Event e)
{
event_list.AddLast(new Event(etc etc));
}
}
Then, the only contract you have between your two objects is the Event type.