I'm working on a hobby project in Unity. I have MonoBehaviour scripts for my characters that use component objects for each behavior the character has. When I create new characters, I inherit a new class from the base class for whichever component behaves differently.
When certain triggers occur, I send characters back to their initial state by calling a Reset() method exposed by the base class that sets fields back to their initial values. I'm wondering how to send that call down through the inheritance chain. Right now, the base class has a protected virtual ChildReset() that gets called in Reset() and does nothing by default. If child classes have fields to reset, they override this method. It feels like a really awkward way of doing it.
I like the idea of implementing something similar to the messaging system Unity uses. If a monobehavior doesn't use the Update() message, then the class just doesn't define an update. It eliminates unnecessary calls. I have no idea how I would do something like that.
Any thought invested in this is much appreciated! I've written out the way my project is structured below just in case these details are useful for answers.
public class Character : MonoBehaviour
{
private Motion motionController;
private Interaction characterInteractionController;
//etc
private void Update()
{
motionController.DoStuff();
characterInteractionController.DoStuff();
}
private void Reset()
{
motionController.Reset();
characterInteractionController.Reset();
}
private void OnEnable() => ResetTrigger.OnReset += Reset;
private void OnDisable() => ResetTrigger.OnReset -= Reset;
}
public class Motion : Component {}
public class Interaction : Component {}
public abstract class Component
{
public void Reset()
{
/* set fields to default values */
ChildReset();
}
protected virtual void ChildReset() { }
public abstract void DoStuff();
}
There is no need to send a call down through the inheritance chain. You do not have two different objects. An object of the child class contains everything declared in the base class. Why not directly make Reset() virtual?
public abstract class Character : MonoBehaviour
{
public virtual void Reset()
{
...
}
}
public class ChildCharacter : Character
{
// If ChildCharacter has stuff to reset, override this method, otherwise don't!
public override void Reset()
{
base.Reset(); // Call this to reset stuff from the base class.
//TODO: reset child stuff.
}
}
If Reset is overridden in the child class, then calling Reset will call ChildCharacter.Reset() even if called on a variable statically typed as Character.
Character c = new ChildCharacter();
c.Reset(); // calls ChildCharacter.Reset() when overridden
If Reset is not overridden in the child class, then calling Reset will call Character.Reset() even if called on a ChildCharacter.
ChildCharacter child = new ChildCharacter();
child.Reset(); // calls Character.Reset() when not overridden.
Related
I have a pretty basic understanding of inheritance and so when using it there are a few moments like this where I find it difficult to understand what's fully happening and it probably doesn't help that I'm most likely not using it properly.
Anyways though I have these 3 classes
public abstract class EffectBase
{
public enum EffectType
{
harm,
help,
self
}
public EffectType type;
public float duration;
public void Activate()
{
Debug.Log("Activating effect");
ApplyEffect();
}
public abstract void ApplyEffect();
public abstract void End();
}
public class Player : MonoBehaviour
{
public List<EffectBase> effects = new List<EffectBase>();
void Update()
{
if (Input.GetKeyDown("q"))
{
Debug.Log("Q pressed");
AddEffect(new SpeedEffect());
}
}
public void AddEffect(EffectBase effect)
{
Debug.Log("Adding effect");
effects.Add(effect);
effect.Activate();
}
}
public class SpeedEffect : EffectBase
{
public override void ApplyEffect()
{
Debug.Log("Speed effect applied");
}
public override void End()
{
Debug.Log("Speed effect ended");
}
}
When I call the AddEffect method I pass a new instance of SpeedEffect (I think it's an instance) as the parameter and then in the AddEffect method I call the Activate method from it, however, in the SpeedEffect class, it doesn't have or override that method so I'm assuming it goes to the base class which does have it and continues and now here's where I get confused in the Activate method it calls the ApplyEffect method, but how does it know to call the one in the SpeedEffect class?
Despite not having an override for Activate() that method still exists in the SpeedEffect class, you just didn't need to write any code for it since its the same code so theres no need to duplicate it.
The code for Activate() calls the ApplyEffect() method for whatever class its being called from. In this case: EffectBase.Activate() and SpeedEffect.Activate() have the same code in terms of reading it, but they are not the same; EffectBase.ApplyEffect() and SpeedEffect.ApplyEffect() are two different methods and each are called from their respective classes.
So I've been working on a state machine for a player character in a Unity game, and thought a hierarchical system would work well. However, I'm having some trouble getting methods to traverse the inheritance chain. If someone could point out my mistake for me, I'd greatly appreciate it.
Here's my PlayerScript : Monobehavior script:
public PlayerState State;
public void Start() {
State = new StoppedState();
State.Enter(this);
}
public void Update() {
State.Update(this);
}
And here are the PlayerStates:
public class PlayerState {
public virtual PlayerState Update(PlayerScript player) {
Debug.Log("Blorp");
return null;
}
public virtual void Enter(PlayerScript player) {}
}
public class LowPriorityState : PlayerState {
public new virtual PlayerState Update(PlayerScript player) {
Debug.Log("Blop");
PlayerState newState = base.Update(player);
//Do state stuff, determine if state should change
return newState;
}
}
public class StoppedState : LowPriorityState {
public override PlayerState Update(PlayerScript player) {
Debug.Log("Blip");
PlayerState newState = base.Update(player);
//Do state stuff, determine if state should change
return newState;
}
public override void Enter(PlayerScript player) {
Debug.Log("Entered Stopped State");
}
}
The expected output after 1 frame is:
Entered Stopped State
Blip
Blop
Blorp
but instead I'm getting:
Entered Stopped State
Blorp
...which is completely baffling, because it's clearly using the overridden "Enter" method but not using the overridden "Update" method. Does anyone know what I'm doing wrong and how to fix it?
The "new" modifier is used to hide a method of the base class and create a completely new method. This way, if the variable is of type BaseClass, it will call the method in the base class, and if the variable is of type DerivedClass, it will call the method in the derived class.
So in the LowPriorityState you are creating a new method, not overriding the one from PlayerState. So your field State of type PlayerState will continue to call the method from the base class.
And then you override this new method in StoppedState, but as your field State is of type PlayerState, it continues to call the method from the base class.
So just replace the new keyword with override.
I'm making my rpg game in unity. As I need a lot of different weapons, I tried to make a script for each weapons. Then instead of enacting the Attack function in each weapon's object, I wanted to controll them in other class such as WeaponManager for some reason.
However, I got no idea how to manage variety of classes. It doesn't seem efficient to write all the codes for each classes, such as
if((gameObject).name=="Wand")
gameObject.Getcomponent<Wand>().Attack();
else if((gameObject).name=="Sword")
gameObject.Getcomponent<Sword>().Attack();
... and so on.
In other way, I also thought of SendMessage function, but it doesn't seem like efficient as well.
I'm wodering how can I solve this problem. Which method can I use?
Classical example use case for object oriented programming:
Inheritance!
Use a shared parent class both inherit from and either implement the method virtual with a shared default behavior the inheriting classes can overwrite/extend or make it abstract so inheriting classes have to implement it.
public abstract class Weapon : MonoBehaviour
{
public abstract void Attack();
// alternatively implement some default behavior
// in this case the child classes can but don't have to override this
//public virtual void Attack()
//{
// Debug.Log("Harr Harr .. but I'll do nothing else!", this);
//}
}
and then
public class Wand : Weapon
{
public override void Attack()
{
...
}
}
and
public class Sword : Weapon
{
public override void Attack()
{
...
}
}
then simply go
gameObject.GetComponent<Weapon>().Attack();
I don't think I explained my question very well in the title, so I'll do my best to do it here.
I have an abstract class called Song, a class that extends it MidiSongand then I have a SongCreator interface and a MidiSongCreatorclass that implements it. I would like to have a way to store lots of SongCreators so I can call their Create method but the problem is, since the SongCreators will each be a MidiSongCreator I am wondering how I should initialize each MidiSongCreator since it takes a MIDIPlayer and other things to help initialize it which doesn't have a static reference to it. Should I create a static class that holds lots of SongCreators? Should I not make the SongList class static?
What is looks like:
public abstract class Song{
public IList<Playable> notes { get; private set; }
public SongPlayData Start(){
// calls onStartEvent
return CreateSongData();
}
protected abstract SongPlayData CreateSongData();
public bool Update(SongPlayData songData, float songTime,List<SongPlayer> players) { // note that the players list is a list of people who are playing this game (this is a rhythm game) (doesn't have anything to do with MIDIPlayer
}
public void End(){
//calls end event
}
}
public class MidiSong : Song { // this is the class that needs the MIDIPlayer parameter
public MIDIPlayer midiPlayer;
protected MidiSong(MIDIPlayer player){
this.midiPlayer = player;
}
protected override SongPlayData CreateSongData() {
return new MidiSongData(midiPlayer);
}
}
public interface SongCreator<out T> where T : Song {
T Create();
}
public class MidiSongCreator : SongCreator<MidiSong>, IListenerObject { // this is the class that I need to store lots of instances of. the midiPlayer will probably be the same every time
private MIDIPlayer player;
public MidiSongCreator(MIDIPlayer player) {
this.player = player;
Init();
}
private void Init() {
player.midiListener.listener = this;
//
}
private void Clear() { // resets all the data so we can create another Song if we need to (even without entering stuff in)
if(player.midiListener.listener == this) {
player.midiListener.listener = null;
}
}
public MidiSong Create() {
MidiSong r = new MidiSong(player);
// I'm still going to implement calls to other methods from midiPlayer
Clear();
return r;
}
public void OnLoad(MidiFile file) {
// does stuff to load midi file (deals with individual events)
}
}
public class MasterSong : MonoBehaviour { // this should initialize last btw (It's in the Script Execution Order)
public MIDIPlayer midiPlayer;
public Song song;
public SongPlayData playData;
// Use this for initialization
void Start() {
// this is where I'd like to reference a SongCreator and call it's create method and Start the song
//for instance:
song = SongList.SONG_NAME.Create();
playData = song.Start();
}
void Update() {
}
}
It's a RhythmGame made with unity, but I didn't add the unity tag because I feel that this is more of a C#/design thing.
Also note, that I have my classes much more organized that just one file with all these.
I'm looking for ways to improve on the design that I have.
This is a design problem, domain design!
I suggest don't write code yet. Create a class diagram, with pen and paper, don't need to use tools in the beginning.
Try to determine entities - classes, interfaces etc - and the relationship among them. Just use boxes and arrow, don't need to put details yet. With boxes and arrows, you will be able to have a picture of your domain much more clearly. Keep refining and changing it, still at this high level, without details, until you are satisfied.
Then, step by step, refine it by adding details/properties such attributes and methods. This may cause to change the diagram from the first step.
I intentionally did not refer to specifics of you questions like the classes and interfaces you mentioned. Since, there is not enough information to comment on that. Secondly, and more importantly, you should start at high level of design and once that is done, then do coding based on your design.
I am trying to implement C# as a scripting language for my game engine. Everything works fine, only one major problem occurred in my design.
I have the class BaseEntity. And another class BossEntity that derives from BaseEntity. Then I want to be able to create a new entity via script. So I create a class in my script let's say Boss1, that derives from BossEntity.
BaseEntity has an virtual Update Method. BossEntity overrides it and calls also base.Update(). All fine in the design.
But now to my problem. In my script I also want to be able to override the Update Method. So I go ahead and override it again. All works as supposed, the BossEntity override gets lost, as I now override the BaseEntity Update again.
But for simplicity I do not want to have to call in my script base.Update() to have the same behavior as in BossEntity. That's a thing that can be forgotten, which would be for me as for a scripting language bad design.
When scripting you just add functionality not remove some in my opinion.
So my general question is, is there any way to accomplish a call to base.Update() without even calling it extra in my script?
I assume no, or maybe just with a trick, but you never know.
As far as I know, there is no way to automatically invoke the base class's virtual method when an overridden one is invoked. You must explicitly call it.
One of the things you can do is break the parent method up a bit more. Instead of having all of the code in a single overridable method like this:
public class Foo
{
public virtual void Update()
{
// Do stuff
}
}
public class Bar : Foo
{
public override void Update()
{
// Replaces the parents implementation of the
// Update method due to not calling base.Load();
}
}
Instead, you can use the Template Method Pattern to break it up in to multiple parts, so that the user can override the part that is meant explicitly for them.
public class Foo
{
public void Update()
{
this.OnUpdating();
this.PerformUpdate();
this.OnUpdated();
}
public virtual void PerformUpdate()
{
// Leave this empty. Let the subclass override it and
// do their own thing. Your parent code will still
// get called when Update() is called.
}
public void OnUpdating()
{
// Invoke code that you want to guarantee is always
// executed PRIOR the overridden PerformUpdate() method
// is finished.
}
public void OnUpdated()
{
// Invoke code that you want to guarantee is always
// executed AFTER the overridden PerformUpdate() method
// is finished.
}
}
public class Bar : Foo
{
public override void PerformUpdate()
{
// Do custom stuff, don't have to call base.PerformUpdate()
// because it already does it's code in OnUpdating()
// and OnUpdated().
}
}
Hope this makes sense. This is what I do in my game engine. I then document that a call to base.PerformUpdate() is not needed. Another option is to make the PerformUpdate() method abstract, forcing children to implement it. That makes it a bit more clearer that there is no need to invoke base.PerformUpdate().
public class Foo
{
public void Update()
{
this.OnUpdating();
this.PerformUpdate();
this.OnUpdated();
}
// Child class is required to implement this method.
// Only downside is you will no longer be able to instance
// the base class. If that is acceptable, then this is really
// the preferred way IMO for what you are wanting to do.
public abstract void PerformUpdate();
public void OnUpdating()
{
// Invoke code that you want to guarantee is always
// executed PRIOR the overridden PerformUpdate() method is finished.
}
public void OnUpdated()
{
// Invoke code that you want to guarantee is always
// executed AFTER the overridden PerformUpdate() method is finished.
}
}
In the end, this approach lets your base class handle its update code safely, by forcing children to implement their own update method that you do not depend on. Your base class can run through its update stuff before and after the child-class has run through its updates.
This basically lets you do this in your game code:
Bar myFoo = new Bar();
myFoo.Update();
And you can rest assured that your base class update methods get called, and the child update code will get called as well.