First of all I want to make clear the fact that I'm not using Unity or anything related to this .
I want to get values from a variable from a script to another , but inside the same .cs file.
My variable is named spellpos
Im setting it's values in this script
public class MyMissile: ISpellScript
etc etc
public void CastKeg(ISpellMissile missile)
{ etc
var spellpos = new Vector2(daspell.CastInfo.TargetPositionEnd.X, daspell.CastInfo.TargetPositionEnd.Z);
etc
} etc etc
Then I want to access that spellpos value in another script
public class GragasQToggle : ISpellScript
etc etc
public void OnSpellCast(ISpell spell)
{
var position = spellpos;
}
How can I achieve this ?
OR
You can make the first method return the value and use in the second method like below:
public Vector2 CastKeg(ISpellMissile missile)
{
var spellpos = new Vector2(daspell.CastInfo.TargetPositionEnd.X, daspell.CastInfo.TargetPositionEnd.Z);
return spellpos;
}
And then you call in the second method like below:
public void OnSpellCast(ISpell spell)
{
var position = CastKeg(spell);
}
Try making your variable public:
public class MyMissile: ISpellScript
{
public static Vector2 spellpos;
public void CastKeg(ISpellMissile missile)
{
spellpos = new Vector2(daspell.CastInfo.TargetPositionEnd.X, daspell.CastInfo.TargetPositionEnd.Z);
}
}
And now you can access the variable from the other class:
public class GragasQToggle : ISpellScript
{
public void OnSpellCast(ISpell spell)
{
var position = MyMissile.spellpos;
}
}
Another option is to make get and set functions for each class
and leave them as private.
If those are separated programs or even the same program a creative solution is to use TCP sockets.
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);
Hi I'm a completely new to coding and am trying to create a card game. I've watched some tutorials and tried to take things into my own hands but cant seem to figure out something. I currently have a BattleState set up;
public enum BattleState { START, PLAYERMAINPHASE, PLAYERBATTLEPHASE, PLAYERENCORESTEP, ENEMYTURN, WON, LOST }
and would like it so when i change the BattleState with a script, it changes it for every other script that references this BattleState. Sorry for the bad wording. Coding is rough :/
You can use interfaces, create an interface such as IBattleStateChanger and have a method on it
interface IBattleStateChanger{
void ChangeBattleState(YourClass.BattleState state);
}
Then on every script you want the value to change implement this interface as
ClassExample : IBattleStateChanger {}
This will then force you to create a method in the script to change the state
After that, whenever you want to change the value globally on the scripts where you implemented this interface, you can do a foreach loop finding each type of this interface such as
BattleState newState = BattleState.START;
foreach (var obj in FindObjectsOfType<IBattleStateChanger>){
obj.SetBattleState(newState);
}
You could use a static event and attach listeners/callbacks to it like e.g.
public enum BattleState
{
START, PLAYERMAINPHASE, PLAYERBATTLEPHASE, PLAYERENCORESTEP, ENEMYTURN, WON, LOST
}
public static class BattleStateMgr
{
private static BattleState _state;
public static BattleState State => _state;
public static event System.Action<BattleState> OnStateChange;
public static ChangeState(BattleState s)
{
_state = s;
OnStateChange?.Invoke(_state);
}
}
public class OtherScript : MonoBehaviour
{
private void Awake()
{
BattleStateMgr.OnStateChagne += OnBattleStateChange;
}
private void OnDestroy()
{
BattleStateMgr.OnStateChagne -= OnBattleStateChange;
}
private void OnBattleStateChange(BatlleState newState)
{
Debug.Log($"Changed Battle State to{newState}", this);
}
}
I believe you are confused about the scope of your variable. Each script you place an instance of the enum Battlestate, is a local version of that enum. If you want the reference to be global, you will need to have a central point where all scripts can grab this reference.
public class BattleManager : MonoBehaviour
{
private BattleState battleState;
// setter / getters
public BattleState GetBattleState(){return battleState; }
public void SetBattleState(BattleState state){ battleState = state; }
}
You are going to want to make a single script that holds the only reference to your enum Battlestate, then have your other scripts reference the variable.
public class OtherScript : MonoBehaviour
{
// assign this reference in the inspector
[SerializeField] private BattleManager bm = null;
private void YourFunction()
{
if(bm.GetBattleState() == BattleState.randomStateHere)
{
// run logic here
}
}
}
There are a number of ways to go about doing this, but the easiest would most likely be by declaring the variable static.
public class BattleManager : MonoBehaviour
{
private static BattleState battleState;
// setter / getters
public static BattleState GetBattleState(){return battleState; }
public static void SetBattleState(BattleState state){ battleState = state; }
}
public class OtherScript : MonoBehaviour
{
private void YourFunction()
{
if(BattleManager.GetBattleState() == BattleState.randomStateHere)
{
// run logic here
}
}
}
I do not know how many scripts you need to access this variable, but if it is only a handful, I would instead assign references to the script that holds the enum to each of the scripts that need it. I would avoid simply using static as it is the easy approach but creates what is called a code smell. The reason for this is OOP (object-oriented programming) by design should generally not have mutable global variables.
If you have a single instance of an object that manages all of your battle activity and a lot of scripts need to access it, you can look into the Singleton pattern. As you are new to programming, I would not implement this pattern until you understand the time and place to properly use it. You can also completely avoid using it by properly assigning the references you need in the inspector or by using a Object.FindObjectOfType in either Start or Awake.
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();
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 created a class that needs to alter a variable's value when it is instantiated.
Example:
In my LrgDialogBox class I might have:
public LrgDialogBox(ref oldResult)
{
// bunch of code
UserInput();
}
public UserInput()
{
newResult=false;
}
In my main class I create an object of my LrgDialogBox called lrgDia then I type:
lrgDia = new LrgDialogBox(ref result);
if (result==true) this.exit;
I basically need to know how to make the reference variable "oldResult" private in my LrgDialogBox class, so that any method can alter its value so it can be used in my main class. Hopefully without changing the parameters of my other methods. Please help.
Kris
There isn't any way for you to meaningfully store the reference parameter that is passed in and be able to modify its value later. What you need to do is add in another layer of indirection; create a reference type that holds onto the value that you really care about. Pass around references to that type, and then all of those references are indirectly pointing to a single value.
The implementation of such a wrapper is simple:
public class Wrapper<T>
{
public T Value { get; set; }
}
You can now create a class that accepts a Wrapper<bool> in the constructor, and then modifies the value within that wrapper at a later point in time.
public class Foo
{
private Wrapper<bool> flag;
public Foo(Wrapper<bool> flag)
{
this.flag = flag;
}
public void Bar()
{
flag.Value = false;
}
}
The other option available to you, since you are, in this case, only calling the method from within the constructor, is to simply have your other method return its value, rather than setting a private field. This would be the preferred design:
public class LrgDialogBox
{
public LrgDialogBox(ref bool oldResult)
{
// bunch of code
oldResult = UserInput();
}
public bool UserInput()
{
return false;
}
}
Just use a private variable to work with during the processing.
private bool _newResult;
public LrgDialogBox(ref bool oldResult)
{
// bunch of code
_newResult = oldResult;
UserInput();
oldResult = _newResult;
}
private void UserInput()
{
_newResult = false;
}