- Home /
How to set different classes at runtime
I am making a game where the character will have different characteristics and movement functions in each scene. So I am trying to have different script for player in different scenes, while all of them inheriting from same base class. The definition will be something like below
public class PlayerScript1 : PlayerBase{ /* for scene 1*/
public void Move(){
/* my movement code*/
}
}
Similarly, I have a separate class for Scene2 as
public class PlayerScript2 : PlayerBase{ /* for scene 2*/
public void Move(){
/* my movement code*/
}
}
Now the problem is, my other scripts, like HealthScript,ScoreScript etc they do not change with scene. But they do access PlayerScene1 script. And thats why, I have the PlayerScene1 declaration in them. Like below:
public class HealthScript :MonoBehaviour{
PlayerScript1 playerScript;
void Start(){
/*accessing the script attached to game object*/
}
}
So how do I manage different scenes to have different PlayerScripts?
Answer by FM-Productions · May 02, 2017 at 06:52 PM
Hi, In my opinion, there are 2 easy solutions to this.
Define an interface and make PlayerScript2 and PlayerScript1 implement it. The interface has to have all functions of the PlayerScript defined that you want to use in your general scripts like HealthScript, ScoreScript etc. Then, in your general scripts instead of using a specific instance of PlayerScript1 or PlayerScript2 you work with the interface.
This will be easier to implement in your case: Instead of defining
PlayerScript1 playerScript;
in scripts like HealthScript, you writePlayerBase playerScript;
- in short you use your base class in scripts that do not change in different scenes. Then in the PlayerBase class you define the functions where you want to use the specific implementations of PlayerScript1 and PlayerScript2 as virtual, like that:
public class PlayerBase{ public virtual void Move(){ /* my movement code*/ } }
In the derived classes, you override functions like Move() like so:
public class PlayerScript1: PlayerBase{ public override void Move(){ /* my movement code*/ } }
So when you are using the type PlayerBase in one of your scripts like HealthScript and assign an instance of PlayerScript1 to it, you can call the function Move() - because it is also defined in the base class - and it will execute the function like implemented in PlayerScript1, since you have overridden the method.
Then you could simply place a gameObject in you scene that has either the script PlayerScript1 or PlayerScript2 and access it in your general scripts like this:
public class HealthScript :MonoBehaviour{ PlayerBase playerScript; void Start(){ /*finding the player object in your scene*/ PlayerBase player = (PlayerBase)FindObjectOfType(typeof(PlayerBase)); } void Update(){ /*moving the character*/ player.Move(); } }
Thank you so much. Exactly what i needed. God bless you :D
Answer by Bunny83 · May 02, 2017 at 07:04 PM
You haven't mentioned the most important thing: Why are those other scripts referencing your "PlayerScript". The name "PlayerScript" does tell us anything about what that script actually does. PlayerScript1 and PlayerScript2 are fundamentally two completely different scripts. One can't be treated as the other. However both can be treated like a "PlayerBase" instance, just like every class can be treated as a System.Object.
Your other scripts might want to declare a variable of PlayerBase instead. However that of course limits the access to things defined inside PlayerBase. You can't access anything that is defined inside PlayerScript1 or 2.
Keep in mind when using inheritance and you want to override a method in a derived class, you have to declare that method in the base class either as virtual or abstract. If you declare it as abstract, the whole class has to be abstract as well.
public class PlayerBase : MonoBehaviour
{
public int someCommonVariable;
protected virtual void Move()
{
Debug.Log("PlayerBase-->Move");
}
protected virtual void Update()
{
Move();
}
public virtual int GetValue()
{
return 0;
}
}
public class PlayerScript1 : PlayerBase
{
public int anotherVariable = 5;
protected override void Move()
{
Debug.Log("PlayerScript1-->Move");
// Specific implementation here
}
public override int GetValue()
{
return anotherVariable;
}
}
public class PlayerScript2 : PlayerBase
{
public int anotherVariable = 345;
protected override void Move()
{
Debug.Log("PlayerScript2-->Move");
// Specific implementation here
}
public override int GetValue()
{
return anotherVariable;
}
}
Have a look at my example. The base class devines an Update method and calls the virtual Move method. Move inside the base class does nothing. However each derived class implement their own behaviour. Move will automatically be called from Update.
Note that each class PlayerScript1 and 2 define a variable names "anotherVariable". However even both a named the same, they have nothing in common and can't be accessed in an abstract way. They are two completely different variables. However each class also overrides the virtual GetValue method that returns an int value. Each script returns the value of it's "anotherVariable". Since GetValue is defined inside the base class you can call it on a base class reference.
So other scripts might have a variable like this;
public PlayerBase player;
And can simply do:
Debug.Log("Value is: " + player.GetValue());
If the actual player script is PlayerScript1 GetValue will return "5" (unless the value has changed of course). If the script is a PlayerScript2 instance GetValue will return "345".
Your answer
Follow this Question
Related Questions
An OS design issue: File types associated with their appropriate programs 1 Answer
Inherited member variables not set to base value c# 1 Answer
Loading component by superclass. 1 Answer
How to make a custom class inherited from Unity's GUI? 0 Answers
Can I/Should I call Awake() in parent class manually? 1 Answer