Best way to read object from another class without code coupling - c#

for example we have class Foo
class Foo {
public class Physics {
float gravity = 9.8f;
float seperateDistance = 10f;
}
public Physics physics;
void Start(){
physics = new Physics();
Bar baz = AddComponent<Bar>();
}
}
Meanwhile, in Bar component, we are trying to get the gravity value inside Foo's physics.
Currently this is the only way I can think of. which i somehow feel not good about. If class Foo is removed then Bar will not working anymore, which i guess is not a good practice.
Inside the baz we created in Foo:
void Start(){
//...
float gravity = getComponent<Foo>().physics.gravity;
//...
}
Is there any better ways to do this?

If I'm reading you correctly, the issue that you're worried about is class coupling. As Georg's answer said, you should be using properties, not fields. But you can avoid class coupling by injecting an interface into Bar that Foo implements. This means that you don't need a Foo to code Bar:
public interface IGravitySource
{
double Gravity { get; }
}
public sealed class Foo : IGravitySource
{
private readonly Physics myPrivatePhysics = new Physics();
private sealed class Physics
{
public double Gravity { get; } = 9.81;
public double Smoothness { get; } = 0.05;
}
public double Gravity => myPrivatePhysics.Gravity;
}
public sealed class Bar
{
private readonly IGravitySource gravitySource;
public Bar(IGravitySource gravitySource)
{
this.gravitySource = gravitySource;
}
public void Start()
{
//...
var gravity = gravitySource.Gravity;
gravity += 1;
//...
}
}
EDIT:
Technically, you might be introducing debt by effectively re-implementing the properties of IGravitySource in multiple places. One solution to this is to have the IGravitySource only have a single member, IGravity. This way, if you decide to extend IGravity with direction, you don't need to change the implementation of Foo:
public interface IGravitySource
{
IGravity Gravity { get; }
}
internal interface IGravity
{
double AccelerationDueToGravity { get; }
}
public sealed class Foo : IGravitySource
{
private readonly Physics myPrivatePhysics = new Physics();
private sealed class Physics : IGravity
{
public double AccelerationDueToGravity { get; } = 9.81;
public double Smoothness { get; } = 0.05;
}
public IGravity Gravity => myPrivatePhysics;
}
public sealed class Bar
{
private readonly IGravitySource gravitySource;
public Bar(IGravitySource gravitySource)
{
this.gravitySource = gravitySource;
}
public void Start()
{
//...
var gravity = gravitySource.Gravity.AccelerationDueToGravity;
gravity += 1;
//...
}
}

This is usually done through properties which are basically pairs of two methods, a getter and setter method.
To use them, just exchange public Physics physics; by public Physics physics { get; set; }. There is no need to change the consuming code since properties are accessed like fields in C#. However, properties also allow you to customize the getter and setter. The good thing is that such a modification is transparent to client code, so you can change the access to that property without having to change code that consumes the property. Further, properties can be virtual or abstract and are allowed to be part of an interface.

You can check if there's a Foo component attached
void Start() {
//Check if there's Foo, if no then give them default to 3;
float gravity = GetComponent<Foo>() ? GetComponent<Foo>().physics.gravity : 3;
//...
}
Or you can also add RequireComponentAttribute to the class Bar, so that Foo will always tied to Bar RequireComponentAttribute
But if you mean 'what if Foo Class(not component) doesn't exist anymore.
I suggest you to do Method Injection like Adam Brown answers.
But there's another solution when class is no longer exist.
here's my thought.
Create a special Attribute to detemine which field is shareable. and then get the field wh use that Attribute.
Example :
of course this isn't tested yet, but by theory it will work.
//Some special attribute
[AttributeUsage(AttributeTargets.Field)]
public class ShareFieldAttribute : Attribute {
}
class Foo {
public class Physics {
float gravity = 9.8f;
float seperateDistance = 10f;
}
//mark ShareField attribute to this field
[ShareField]
public Physics physics;
void Start(){
physics = new Physics();
Bar baz = AddComponent<Bar>();
}
}
class Bar {
void Start() {
//Get the field 'public Physics physics' by name and Type
Physics physics = GetShareField<Physics>("physics", null);
float gravity = physics ? physics.gravity : 3;
//...
}
//Method Helper
public T GetShareField<T>(string fieldName, T defaultValue)
{
foreach(var c in GetComponents<MonoBehaviour>())
{
var fields = c.GetType().GetFields().Where(field => field.FieldType == T && field.Name == fieldName && field.IsDefined(typeof(ShareFieldAttribute), false));
return (T)fields[0].GetValue(c);
}
return defaultValue;
}
}

Related

How to wrap a function from an inherited class to add functionality, similarly to Python decorators

I'm inheriting a more generic health handling class to add functionality specific to the player. I wish to decorate functions inherited from the old class in a similar manner to Python decorators to add checks and functionality when they are called, hopefully without rewriting the existing functions.
For clarity I've included the two classes below:
public class HealthSystem
{
// Start is called before the first frame update
public int currentHealth;
public int maxHealth;
// Update is called once per frame
public HealthSystem(int maxHealth, int currentHealth = 0)
{
if (currentHealth == 0) this.currentHealth = maxHealth;
else this.currentHealth = currentHealth;
this.maxHealth = maxHealth;
}
public int Damage(int damageAmount)
{
currentHealth -= damageAmount;
if (currentHealth < 0) currentHealth = 0;
return currentHealth;
}
public int Heal(int healAmount)
{
currentHealth += healAmount;
if (currentHealth > maxHealth) currentHealth = maxHealth;
return currentHealth;
}
public void SetMaxHealth(int newMaxHealth)
{
maxHealth = newMaxHealth;
}
public void UpdateMaxHealth(int updateAmount)
{
maxHealth += updateAmount;
}
public void SetCurrentHealth(int newCurrentHealth)
{
currentHealth = newCurrentHealth;
}
}
Currently I'm inheriting this HealthSystem Class into a Player Health System Class, Which is functionally very similar except it also takes a reference to the gameObject that instantiates it.
public class PlayerHealthSystem : HealthSystem
{
private GameObject parent;
public PlayerHealthSystem(int maxHealth, GameObject parent, int currentHealth = 0) : base(maxHealth, currentHealth)
{
this.parent = parent;
}
}
public class MyAttribute : Attribute
{
}
The point of this is that I want certain function calls that modify the current health to be checked after they've run to see if the players current health is 0, which would make a call back to the player gameObject to run some kind of death script. I wanted to do this with python-like decorators like so:
[HealthCheck]
func()
decorator HealthCheck()
{
if (this.currentHealth == 0)
{
parent.GetComponent<PlayerControl>.DeathScript();
}
}
Can anyone provide an example of how to achieve it, I can see so many uses for this kind of pattern and it would be amazing to learn how to do it now so I can implement it later.
The way the decorator pattern is usually implemented in C# is by having an interface which both the decorator as well as the decorated class implement.
The decorator wraps an instance of the decorated class, and implements all members of the interface as pass-through calls to the wrapped object - along with some additional functionality on top.
public interface IHealthSystem
{
int Damage(int damageAmount);
int Heal(int healAmount);
void SetCurrentHealth(int newCurrentHealth);
}
public class HealthSystemDecorator : IHealthSystem
{
private readonly IHealthSystem wrappedHealthSystem;
private readonly PlayerControl playerControl;
public HealthSystemDecorator(IHealthSystem wrappedHealthSystem, PlayerControl playerControl)
{
this.wrappedHealthSystem = wrappedHealthSystem;
this.playerControl = playerControl;
}
public void Damage()
{
wrappedHealthSystem.Damage();
HandleInvokeDeathScript();
}
public void Heal()
{
wrappedHealthSystem.Heal();
}
public void SetCurrentHealth(int newCurrentHealth)
{
wrappedHealthSystem.SetCurrentHealth(newCurrentHealth);
HandleInvokeDeathScript();
}
private void HandleInvokeDeathScript()
{
if(currentHealth == 0)
{
playerControl.DeathScript();
}
}
}
To actually make use of the decorator, you also need to figure out a way to get all objects in the project to use the decorator object instead of the original HealthSystem. One way to achieve this is with the dependency injection pattern. This way the clients using the IHealthSystem object don't need to know if they're working with the original or the decorator variant.
public class PlayerBuilder
{
public static Player CreatePlayer()
{
Player player = new GameObject("Player").AddComponent<Player>();
PlayerControl playerControl = player.AddComponent<PlayerControl>();
IHealthSystem wrappedHealthSystem = new HealthSystem();
IHealthSystem healthSystemDecorator = new HealthSystemDecorator(wrappedHealthSystem, playerControl);
player.Init(healthSystemDecorator); // inject the decorator to the player object
}
}
If you actually want to be able to just add attributes to methods to decorate them with additional functionality, then you should look into code weaving.

What is an alternative to static derived classes which aren't allowed in c#

I have a Pokemon class which is an abstract class. I want to build a bunch of Pokemon which behave similarly. Currently it have the fields: speciesName and health. I have multiple derieved pokemon classes such as Bulbasaur, Venusaur, Charmeleon, etc. Each of these has a different static value for that particular type of Pokemon. I get creating instances of these Pokemon because not all instances of the same type of Pokemon will be exactly the same. They will have different moves, and I can add functionality on such as Nicknames or levels.
abstract class Pokemon
{
string speciesName;
int health;
bool Fainted
{
get
{
if (health == 0)
{
return true;
}
else
{
return false;
}
}
}
public Pokemon(string speciesName, int health)
{
}
public void TakeDamage(int damage)
{
health -= damage;
}
}
class Bublasaur :Pokemon
{
Move[] possibleMoves = {new Tackle() };
static int health = 60;
static string speciesName = "Bublasaur";
Bublasaur() :base(speciesName, health)
{
}
}
However, I also have a Move class is abstract and has derived classes which are moves such as Flamethrower and Watergun. They have only static fields.
abstract class Move
{
int damage;
string name;
public Move(int damage, string name)
{
this.damage = damage;
this.name = name;
}
}
class Tackle :Move
{
static int damage = 20;
static string name = "Tackle";
public Tackle():base(damage,name)
{
}
}
class Ember: Move
{
static int damage = 30;
static string name = "Ember";
public Ember() : base(damage, name)
{
}
}
Because I have a base class of Moves, I can't make the class static as static classes can only derive from the object class. However, creating an instance of each move to attach to each Pokemon I create does not seem very intuitive. Is there a way I can implement this better?
Tackle and Ember don't extend the behaviour of Move, so the inheritance hierarchy seems unneccesary.
You could have a single class Move that holds static references to the various instances:
class Move
{
int damage;
string name;
private Move(int damage, string name)
{
this.damage = damage;
this.name = name;
}
public static readonly Move Tackle = new Move(20, "Tackle");
public static readonly Move Ember = new Move(30, "Ember");
// Other moves..
}
Move is an action that can be performed by Pokemon. As such, I think it is better if it is defined as an Interface and that these don't need to be static.
You can then create moves such as Tackle, Ember etc.
public interface IMove
{
public int Damage { get; }
public string Name { get; }
}
public class Tackle : IMove
{
public Tackle()
{
}
//You can still set defaults per class
public int Damage { get; } = 30;
public string Name { get; } = "Tackle";
}
I don't use a setter, as I assume you don't actually want these values to change after initialisation. if you do, you can simply add it in.
I would also use an Enum for the Name of the Move (and Pokemon), so that you don't have problems with upper/lower case, spelling mistakes etc.
I would also look at using a Factory to create Pokemons, and maybe even the moves (if you don't already).
I admit to not knowing about the game and characters in Pokemon, so maybe I don';t understand correctly but I don't see why in your Pokemon that Health should be static, as it means all instances of that Pokemon will have the same health level. Maybe you mean for the Pokemon itself should be a Singleton?

Custom static variables for child classes

I have something like this :
class powerup {
public static int cooldown = 1;
}
class freeze : powerup {
//some unrelated code
}
class burn : powerup {
//unrelated
}
and i'd like to have a different value for the cooldown of the freeze and burn powerups, and in a static way since i can't instantiate them where i set the cooldown, and it also makes more sense to have them static since they are unique. So i feel like i'm needing to override the cooldown with "new" , but it doesnt feel right. Is there any solution i'm not aware of ?
Thanks in advance
There is no combination of overridability and staticness in C#; those are in a sense opposites.
The better technique would be to make instances; those instances could be singletons if that makes sense. I'd be inclined to do something like:
abstract class Powerup
{
public virtual int Cooldown => 1
}
sealed class Freeze : Powerup
{
}
sealed class Burn : Powerup
{
public override int Cooldown => 2;
}
But a technique I particularly like when these are singletons is:
abstract class Powerup
{
private Powerup() {} // Prevent instantiation
public virtual int Cooldown => 1
public static readonly Powerup Freeze = new FreezePower();
private sealed class FreezePower : Powerup
{
}
public static readonly Powerup Burn = new BurnPower();
private sealed class BurnPower : Powerup
{
public override int Cooldown => 2;
}
}
Now look at the use site:
Console.WriteLine(Powerup.Freeze.Cooldown); // 2
That looks really nice at the use site I think.
You can use the new modifier to hide the parent property on child classes, such as:
class powerup
{
public static int cooldown = 1;
}
class freeze : powerup
{
public new static int cooldown = 3;
//some unrelated code
}
class burn : powerup
{
public new static int cooldown = 2;
//unrelated
}
This provides the following results:
Console.WriteLine($"powerup: {powerup.cooldown}");
Console.WriteLine($"freeze: {freeze.cooldown}");
Console.WriteLine($"burn: {burn.cooldown}");
I believe you are wanting to update the cooldown value of all instances of a specific powerup. In that case, I would use something like this:
interface IPowerup {
int Cooldown { get; set; }
}
class Freeze : IPowerup {
private static int _cooldown;
public int Cooldown { get { return _cooldown } set { _cooldown = value; }
public Freeze() { Cooldown = 1; }
}
class Burn : IPowerup {
private static int _cooldown;
public int Cooldown { get { return _cooldown } set { _cooldown = value; }
public Burn() { Cooldown = 2; }
}
So now, if you set the cooldown for one powerup, you set the value for all.
You can also do away with the constructors and instantiate the powerups and set the cooldown period like this:
var burnPowerup = new Burn { Cooldown = 2 };

How can I force a child to call a parent method?

I have a base class with a method. I want to force all children of this class to call this base method somewhere in their code.
public class BaseClass
{
public void BaseMethod()
{
//Do something
}
}
public class ChildClass1 : BaseClass
{
public void ChildMethod()
{
BaseMethod();
}
}
public class ChildClass2 : BaseClass
{
public void ChildMethod()
{
//Doesn't call BaseMethod();
}
}
So I want ChildClass1 to be fine, but I want ChildClass2 to throw an error.
The reason I want to do this is because my base class has a value that I don't want to forget to implement in my child class. For example, if I am making a bunch of enemies for a game, and the Enemy class has a speed modifier, I don't want to forget to include that in all of the children methods:
public class Enemy
{
public float x;
public float y;
private float speed;
public float GetSpeed()
{
return speed;
}
public void SetSpeed(float speed)
{
this.speed = speed;
}
}
public class Goomba : Enemy
{
public void Move()
{
x += 5 * GetSpeed();
}
}
public class Turtle: Enemy
{
public void Jump()
{
y += 5; //This is wrong. I forgot to adjust for speed.
//y += 5 * GetSpeed(); This is what I want to force myself to do
}
}
Although it is not actually for movement. This is an oversimplification. The base class contains ability modifiers, where the children class are unique abilities that use the modifiers.
How can I structure my code such that a child is required to call a specific parent method somewhere in the code?
You can use the TemplateMethod design pattern
public class BaseClass
{
public void BaseMethod()
{
DoSomething();
TemplateMethod();
}
protected abstract void TemplateMethod();
}
So you make your derived classes implement the template method, but clients of that class call the BaseMethod method. This forces the DoSomething() bit to execute but allows the derived classes to include their own logic.
So a simple example in the case of enemy (obvs adapt so it meets your needs).
public abstract class Enemy
{
public float x;
public float y;
private float speed;
public float GetSpeed()
{
return speed;
}
public void SetSpeed(float speed)
{
this.speed = speed;
}
public void Move()
{
x += GetMovementAmount() * GetSpeed();
}
public abstract decimal GetMovementAmount();
}
public class Goomba : Enemy
{
public void GetMovementAmount()
{
return 5;
}
}
public class Turtle: Enemy
{
public void GetMovementAmount()
{
return 6;
}
}
You could rearrange the code so that changing the position is possible only in base class:
public class Enemy
{
public float x { get; private set; }
public float y { get; private set; }
private float speed;
public Move(float dx, float dy)
{
x += dx * speed;
y += dy * speed;
}
}
Create a new class ability. It will allow you to control what happens when it is run and the user gets to make the run do whatever they want.
public class Ability
{
Action myAct { get; set; }
public Ability(Action inAct)
{
myAct = inAct;
}
public Run()
{
DoStuffBefore();
myAct();
DoStuffAfter();
}
}

Generics in Unity C#

I am having a lot of trouble with the syntax and the rules for using Generics. I am trying to make a structure, where different classes, can use the WaitAction class to disable input while a couroutine is running, an re-enable it once the coroutine is finished.
This example is a simplified version, and in reality I will not be using a count float to define the length of the coroutine, but the length will based on animations and translation.
Is what I am trying to do at all possible?
"Somehow use "T _ready" to change the "bool ready" in "Main Class" back to "true""
public class Main : Monobehaviour {
WaitAction _waitAction = new WaitAction();
public bool ready;
float delay = 5f;
void Update()
{
if(Input.GetMouseButton(0) && ready)
{
ready = false;
StartCoroutine(_waitAction.SomeCoroutine((delay, this));
}
}
public class WaitAction {
public IEnumerator SomeCoroutine<T>(float count, T _ready)
{
float time = Time.time;
while(Time.time < time + count)
{
yield return null;
}
// Somehow use "T _ready" to change the "bool ready" in "Main Class" back to "true"
}
}
The solution is to constrain the generic type, such that the generic method knows how to set the ready flag. This is easily done using an interface:
public interface IReady
{
bool ready { get; set; }
}
public class Main : Monobehaviour, IReady {
...
public bool bool ready { get; set; }
...
}
public class WaitAction {
public IEnumerator SomeCoroutine<T>(float count, T _ready) where T : IReady
{
...
_ready.Ready = true;
}
}

Categories