Why use a constructor over protected variables? - c#

I'm building some classes within unity to define the mechanics individually, and transition between each for easier and cleaner code.
What I wanna know, is when should I be using a constructor to pass variables around, and when to use protected variables. What are the pros and cons of each, and what should I know about them? Also what should I lean towards, like what's practical?
Previously I'd pass these variables into the PlayerState constructor, then in my classes that extend from my PlayerState would follow suit. But if they're protected variables I don't need to pass them into the constructor to access them, and I was wondering what should I do?
using UnityEngine;
The new way I'm doing it:
public class PlayerState
{
//protected Core Core;
protected Player player;
protected PlayerStateMachine StateMachine;
protected PlayerData playerData;
private string currentAnimation;
protected float StartTime; // Start time gets set everytime we're in a state, that way we have a reference for how long we've been in any state (good for mechanics)
protected bool isAnimationFinished;
protected bool isExitingState; // Very useful, if you run through if/else conditionals in a superState, the substate may still run, and both end up calling a change state. This will stop this from happening
public PlayerState(string currentAnimation)
{
this.currentAnimation = currentAnimation;
}
public virtual void Enter() { }
public virtual void Exit() { }
public virtual void LogicUpdate() { }
public virtual void PhysicsUpdate() { }
public virtual void DoChecks() { }
}
The Old Way:
public class PlayerState
{
protected Core Core;
protected Player player; // protected means private but shared between components that inherit the class
protected PlayerStateMachine StateMachine;
protected PlayerData playerData;
private string currentAnimation;
protected float StartTime; // Start time gets set everytime we're in a state, that way we have a reference for how long we've been in any state (good for mechanics)
protected bool isAnimationFinished;
protected bool isExitingState; // Very useful, if you run through if/else conditionals in a superState, the substate may still run, and both end up calling a change state. This will stop this from happening
public PlayerState(Player player, PlayerStateMachine stateMachine, PlayerData playerData, string currentAnimation)
{
this.player = player;
this.StateMachine = stateMachine;
this.playerData = playerData;
this.currentAnimation = currentAnimation;
Core = player.Core;
}
// So now we code out the functions for each state
// Every state must have an enter and exit function, as well as an update and fixedUpdate function
// We're naming the update function as "LogicUpdate", and fixedUpate as "PhysicsUpdate"
public virtual void Enter() // virtual means this function may be overriden from classes that inherit this class
{
DoChecks();
player.Anim.SetBool(currentAnimation, true);
StartTime = Time.time;
isAnimationFinished = false;
isExitingState = false;
//Debug.Log("Current Animation: " + currentAnimation);
}
public virtual void Exit()
{
player.Anim.SetBool(currentAnimation, false);
isExitingState = true;
}
The way I applied it to other classes the old way:
public class PlayerGroundedState : PlayerState
{
protected Vector2 input;
protected bool jumpInput;
private bool grabInput;
private bool dashInput;
private bool isTouchingGround;
private bool isTouchingWall;
protected bool willCollideWithCeiling;
public PlayerGroundedState(Player player, PlayerStateMachine stateMachine, PlayerData playerData, string currentAnimation) : base(player, stateMachine, playerData, currentAnimation)
{
}
public override void Enter()
{
base.Enter();
player.JumpState.ResetAmountOfJumpsLeft();
player.DashState.ResetCanDash();
}
public override void Exit()
{
base.Exit();
}
I don't have to pass player into the constructor of PlayerState and PlayerGroundedState to access it if it's protected. What should I do though, which method is the proper way to handle the variables, also which is better for my cpu?

This is just a question related to OOP. Unity is not needed to be considered.
A constructor let you create an object instance and initialize the members of the object at the same time. If there are some immutable members (i.e. they will never be changed after construction), you may need to initialize them in constructors, and you may add the keyword readonly to the members. If you don't need to initialize any member with passing parameter(s) when the instance is created, there is no need to have a custom constructor (unless you want to hide the default constructor).
The access modifier protected makes the member accessible only in code in the same class, or in a class that is derived from that class. If you need to access the member in other places, you still need do it via public/internal methods such as setters and getters, or make it public/internal.
In your case, I think a constructor is needed to initialize the members such as player when a PlayerState instance is created.

Related

Unity OnDisable - can I virtual override the built in unity methods?

Is it possible to use virtual void OnDisable() ? Its a built in Unity method, just like Start() or OnEnable(). I couldnt find any resources online where its explained if we can use virtual on these built in methods.
public abstract class ShipComponent : MonoBehaviour
{
[HideInInspector] public ShipControl shipControl;
public virtual void Init(ShipControl control)
{
this.shipControl = control;
StartCommonCoroutines();
}
public virtual void IsPlayer()
{
SetListeners();
StartPlayerOnlyCoroutines();
}
public virtual void OnEnable()
{
StartCommonCoroutines();
if (!shipControl.shipWrapper.ship.IsPlayer) return;
SetListeners();
StartPlayerOnlyCoroutines();
}
public virtual void OnDisable()
{
RemoveListeners();
StopAllCoroutines();
}
public abstract void SetListeners();
public abstract void RemoveListeners();
public abstract void StartCommonCoroutines();
public abstract void StartPlayerOnlyCoroutines();
public abstract void StopPlayerOnlyCoroutines();
}
I want to Inherit from ShipComponent in subclasses and whenever a subclass that inherits from ShipComponent calls OnDisable() (Unity built in version) then I want it to call the baseClass' ShipComponent.OnDisable() as initialized above.
I realize OnDisable() is a built in method, so should I instead be doing:
public override void OnDisable()
{
base.OnDisable();
RemoveListeners();
StopAllCoroutines();
}
Because we are overidding the original built in Unity method this way?
Thanks.
Unity does a little bit of reflection magic on user scripts, and it creates internal list of MonoBehaviours that have OnEnable/OnDisable methods - it calls them even if they are private, and you don't need to explicitly implement any interface for this to work.
This also means that it does not care if the method is virtual or not, it will call a correct override if you override it in your inheriting classes.
Do not mark it as override in your base class as there is no base implementation in MonoBehaviour itself. I would assume this decision was made for performance reasons - if all objects had those methods, even if they were empty, they would have to be called. If there are no methods, its a few calls less.

Don't use Interfaces in Unity?

in Unity I make use of interfaces. I set a logic for components which are totally different to each other.
Examples:
A car, a dog and a aircraft would implement IMovable. I can call Move() from each component but these components execute different code.
Same for ISavable, each component, that has to save data to the database could save the stuff when looping through all savables.
The problem:
Some people in forums say that interfaces are bad for Unity.
When destroying a gameobject and call its interface method this still gets executed.
No error would come up because Destroy() does not destroy objects. Unity as a C++ driven Engine would setup a C# wrapper for the objects. These objects just get a flag destroyed which is a bool.
Destroyed gameobjects will not get destroyed immediately, they will be destroyed later on at the end of the frame.
Until this end of the frame is not reached the method can still get called from the destroyed object.
The best way would be using abstract classes only and never use interfaces because of the bad behaviour coming up when destroying objects.
I tested this with a small example, I created the following scripts:
public interface IIntfacable
{
void DoSomething();
void DestroyComponent();
}
public class bar : MonoBehaviour
{
private IIntfacable i;
private void Start()
{
i = FindObjectOfType<foo>().GetComponent<IIntfacable>();
}
private void Update()
{
i.DoSomething();
i.DestroyComponent();
i.DoSomething();
}
}
public class foo : MonoBehaviour, IIntfacable
{
public void DoSomething()
{
Debug.Log("=> DoSomething");
}
public void DestroyComponent()
{
Debug.Log("=> DestroyComponent");
Destroy(gameObject);
}
}
When executing this code I get the following result
Workaround:
I could create an abstract base class and choose between
public abstract void Foo();
and
public virtual void Bar()
{
return;
}
but this might lead to overengineering. Because all Scripts would need this base class whether they need this method or not.
Conclusion:
Should I prevent using interfaces?
I am confident in saying there is no harm in using interfaces.
The underlying fear is about keeping track of unmanaged references, a problem which will still be there weather you are using interfaces, abstract classes or whatever. You simply have to make sure that your game code will not try to access any objects which have been Destroy()ed.
Basically, I just construct a collection of objects that I know are not destroyed in my scene, and remove them after destruction.
With risk of answering an xy-problem, If you are scared to miss out on your reference count anyway or there is something in particular which wont allow creating such a list, there is not really any magic wand here, but there are a few precedent patterns in the .net framework with the IDisposable interface/pattern that may lead the way.
Many implementations of these patterns checks a flag in a few public-facing methods of the object. IDisposable.Dispose() would set the flag to true and throw an ObjectDisposedException on some public method if this is set to true, analog to MissingReferenceException in this case. Some patterns will then expose the flag IsDisposed, so that other objects that use the implementation can check instead of doing a try-catch on any access to the object. Your analog could be IsDestroyed, and you should set it in the override of OnDestroy.
You could change your method update like this (well it's not really a use case, why would you try to use it after destroying it, but to show my point):
private void Update()
{
i.DoSomething();
i.DestroyComponent();
if (!i.IsDestroyed) {
// This will not be called
i.DoSomething();
}
}
and implementation could be
public interface IIntfacable : IDestroyable
{
void DoSomething();
}
public interface IDestroyable
{
void DestroyComponent();
bool IsDestroyed { get; }
}
public class foo : MonoBehaviour, IIntfacable
{
bool IsDestroyed { get; private set; }
public void DoSomething()
{
Debug.Log("=> DoSomething");
}
public void DestroyComponent()
{
Debug.Log("=> DestroyComponent");
Destroy(gameObject);
}
public override OnDestroy() {
base.OnDestroy();
IsDestroyed = true;
}
}

Proper way to create a static virtual factory method in C#

I'm implementing classes for Effects (something with a duration that applies a behavior in the FixedUpdate loop while it is active) in Unity3D.
I have a base abstract Effect class which has the behavior for keeping track of the duration, removing itself when the duration is up, and calling a protected abstract _doEffect function while its duration is up. In my derived classes, I override _doEffect to create Effects with different behaviors.
public abstract class Effect : MonoBehaviour
{
public virtual float kDuration { get { return 1.0f; }}
public static bool IsStackable { get { return false; }}
private float _elapsed = 0.0f;
protected virtual void Start()
{
_elapsed = kDuration;
}
protected virtual void FixedUpdate()
{
_elapsed -= Time.fixedDeltaTime;
if(_elapsed <= 0) {
Destroy(this);
}
_doEffect();
}
protected abstract void _doEffect();
}
Now, because you can't use constructors with Unity3D, I need a way to do the following for each derived Effect class when I'm applying a new Effect of that type to a game object:
1) If this type of effect is not stackable, then remove all other instances of this monobehaviour from the game object.
2) Create a new component of the effect type to the game object.
3) Do some initialization specific to that effect type.
For these requirements, I was imagining doing something like
public class DerivedEffect : Effect
{
public override float kDuration { get {return 1.0f; }}
public static bool IsStackable { get { return true; }}
private int _derivedData;
public static void Create(GameObject obj, int data)
{
DerivedEffect effect = DerivedEffect.CreateEffect(obj);
effect._data = data;
}
protected override void _doEffect()
{
//Do some stuff
}
}
and then in the base class putting
public static virtual Effect CreateEffect(GameObject obj)
{
//T is somehow magically the type of the class you called this function on
if(!T.IsStackable()) {
//delete all components of type T on obj
}
T effect = obj.AddComponent<T>();
return effect;
}
Obviously this isn't possible unless I do some weird stuff with generics and reflection that seems a bit extreme and probably not that right way to do things.
The crux is that I want a static function that does 1), 2), 3), and I want to share the code that does 1) and 2), and 1) depends on a bool which is different for every derived class.
What is a proper, working design for these desiderata?
What is a proper, working design for these desiderata?
Unity is component based and gets things complicated when you want to use it the way you in a normal C# application.
The simplest way is to use Composition. Make the Effect class it's own class that is not abstract. Just a normal class that inherits from MonoBehaviour. You can easily create new instance of it with AddComponent and get it with GetComponent. This script can also destroy itself directly after the timer is done counting without any problems.
Create a global variable in the DerivedEffect class to hold the instance of the Effect script that is created and this can be re-used over and over again until it becomes null which means that the script is destroyed. Note that there is no inheritance involved here and DerivedEffect script is only used as an example of the script that manages the Effect script.

Inheriting from abstract class, using methods with private variables

In a simplified version, I have the following:
abstract class Days
{
private readonly int _amount;
protected virtual void UpdateAmount()
{
Proccess();
}
protected virtual void Process()
{
_amount += 1;
}
}
The problem is I need to create a class which inherits from Days, in which I need to change the functionality of UpdateAmounts() but still use the same functionality from Process(). Since Process uses a private field, is there anyway to do this without just copying and pasting the code from Process() into my child class? It wont let me use base.Process() because the method references a private field.
You will be able to use base.Process() because it is protected, it doesn't matter if it uses private fields
class MyClass : Days
{
protected override void UpdateAmount()
{
base.Process();
}
}
This code works

designing virtual methods

I wonder under what circumstances you would choose the first or the second design :
First design : the child method have to call the base method
public abstract class Base
{
public virtual void Enable() { IsEnable = true; }
public virtual void Disable() { IsEnable = false; }
public bool IsEnable { get; private set; }
}
public class Child : Base
{
public override void Enable() { /* do stuffs */ base.Enable(); }
public override void Disable() { /* do stuffs */ base.Disable(); }
}
Second design : a virtual method is used to be sure the child do not forget to call the base
public abstract class Base
{
public void Enable()
{
IsEnable = true;
OnEnable();
}
public void Disable()
{
IsEnable = false;
OnDisable();
}
public bool IsEnable { get; private set; }
public virtual void OnEnable() {}
public virtual void OnDisable() {}
}
public class Child : Base
{
override void OnEnable() { /* do stuffs */ }
override void OnDisable() { /* do stuffs */ }
}
Thanks
It depends if you really want to make sure IsEnable gets set or not. If you can imagine scenarios in which the user doesn't want to set it, then I suppose you leave it up to them to call the base method. Otherwise, do it for them.
The second, template-based approach is better in my opinion. It allows you to ensure that some base functionality is always called, and gives you room to add some if none is present at first without the risk of breaking any subclass.
As soon as you make a method virtual, you are giving a derived class a chance to break your class. A responsible deriver will always ask himself "should I call the base implementation?" Guidance for this should always come from documentation. MSDN uses standard verbiage:
Notes to Inheritors:
When overriding Xxxxx in a derived
class, be sure to call the base
class's Xxxx method so that blablah
happens.
The C# language makes that easy with the "base" keyword. Working from the assumption that this documentation is not available or unclear, your second example would strongly discourage a deriver to call the other base class method. After all, s/he wouldn't use the standard pattern. Use this pattern only if you want to discourage the inheritor from calling a base class method.
In the first one, where the overring class could prevent Enable from being set, I reckon Enable and Disable could potentially be misleading method names.
Something like TryEnable and TryDisable would probably be more accurate implying that there are situations where you cannot enable.
A third possible situation could be catered for if you took example 2 and changed it so the base class calls OnEnable before setting the flag:
public void Enable()
{
OnEnable(); // Exceptions raised from here prevent the flag being set.
IsEnable = true;
}
Then overriding classes could prevent the setting of the flag by raising an exception if an error were to occur. Thus error situations would prevent the flag from being changed.
Just food for thought.

Categories

Resources