Basically i'm asking how best to do this properly based on what I THINK I want.
I have a weapon class which is abstract because it contains methods like Fire() that are so general (lasers vs bullets) in how they'd fire they require the inheritor implement.
however once I get to an actual ballistic weapon class which inherits from weapon class.
well most of those fire the same. They spawn the projectile and lower the ammo count and wait for the reload timer to kick down to 0 before allowing fire again.
Whether it's a tank gun or a pistol or a turret or an artillery it will stay the same more than change.
That seems like a virtual class (a torpedo launcher might need a special implementation to raise and lower a hatch door to fire so it can't be non-virtual/abstract, it needs to be modifiable)
however basically I want to have
abstract weapon class Fire() method
virtual ballistic weapon inherits weapon Fire() method
But it doesnt seem that you can override an abstract method and make it a virtual one.
I don't think I want a whole new method though because i'd like to be able to do
weapon.fire
and it go into ballstic weapon and use the implementation there, unless the specific ballistic weapon has overridden that general method.
Abstract means it must be overridden in child class where virtual means it can be overridden. You can have virtual methods in an abstract class. You can solve your problem using Interfaces by binding in a form of contract like:
Ifireable
May be you can do like that:
abstract class Weapon
{
public abstract void Fire();
}
class BallisticWeapon
{
virtual public void Fire()
{
// Ballistic fire
}
}
// Weapon need ballistic fire
class WeaponA : BallisticWeapon
{
}
// Weapon don't need ballistic fire
class WeaponB : Weapon
{
// Implement fire
public void Fire()
{
}
}
Related
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.
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 have the following code about a wildlife park:
public class Bird
{
public void virtual Exercise()
{
some logic here
}
public void virtual Feed()
{
Exercise();
some logic here
}
}
public class Penguin : Bird
{
public void override Exercise()
{
base.Exercise();
some logic here
}
public void override Feed()
{
Exercise();
base.Feed();
some logic here
}
}
So everytime a bird is feed it must also be exercised. However a bird can be exercised without being fed.
A penguin is a special type of bird which requires bird exercise and some specific penguin exercise. Feeding the penguin requires bird feeding plus some additional penguin requirements.
The problem I have here with this code is when Feed is called it gets the bird exercise twice. The penguins will get really tired.
How could I improve the code so that when the penguins are fed they are only exercised for bird and penguin once per feed?
Just remove Exercise() from the Penguin.Feed() call. Since, as you note, Exercise() will get called when you call base.Feed(), so it's redundant to do so. And the base.Feed() call will call the Penguin version of Exercise(), so you'll get the right exercise for that bird.
(Removed reference to mammal since it was removed from the question)
Ok so I am making a game using XNA, I would like all of the enemies to extend from one base class called "baseEnemy.cs". For example, I would like a zombie to have a class called "zombie.cs" but make it entend the "baseEnemy.cs".
I think I remember being told its would be laid out like:
class zombie : baseEnemy
{
}
But I am assuming the use of get{} and set{} would help me to change values of current variables in zombies.cs that exist as part of baseEnemy.cs... If that makes sense? I don't understand the usage of get{} and set{} but I have seen it in other languages (such as the code for minecraft) which I would assume are similar in their working.
So, say I have a float for the speed of the enemy... I don't want all the enemies to move at the same speed (zombie's should have a low speed, etc). How could I get the speed from the baseEnemy.cs and set it as the speed in zombie.cs.
Or would I be better just making the variables public in baseEnemy.cs?
Sorry if the above doesn't make much sense, I am not too experienced with XNA or terminology used and therefore I probably sound like I am going round in circles :S
You are looking for so called abstract methods or abstract properties.
abstract class Enemy
{
public abstract float GetSpeed();
}
class Zombie : Enemy
{
public override float GetSpeed()
{
return 10;
}
}
Note the abstract keyword preceding the class name and the method name. The child class has to implement all abstract members, if it is not abstract itself. When an abstract member is implemented the override keyword must be used.
The get set syntax you are describing is called a property. It is a special C# construct that organizes the getter and/or setter of a field and puts them in a single block. The same example as above using properties:
abstract class Enemy
{
public abstract float Speed { get; }
}
class Zombie : Enemy
{
public override float Speed
{
get { return 10; }
}
}
I'm struggling with a design problem and I don't want my code to become a mess because of a bad solution. Rather than give a poor analogy I'll just explain my exact case.
I'm trying to write a clone of Wii Play Tanks, and I'm having trouble designing the Tank classes. Tank itself is the only such class, it uses dependency injection for its parts. The two parts right now are TankAI and TankWeapon. The AI handles decisions about movement and firing, the weapon describes how the weapon behaves - what projectiles it fires, and how often, etc. I have a factory class that builds tanks in different combinations.
My projectile classes are set up under an abstract Projectile class. Each subclass describes the projectile's model, number of bounces, speed, etc.
The problem I'm having is that each TankWeapon subclass is duplicating a lot of code around the area where they construct a new projectile, because they each construct a different class. I want to move this code into the base class, but I would have to somehow inject the projectile class itself that the weapon needs to construct. I know I could literally pass a Class to the base upon construction, but that feels like the wrong way to go.
And while we're at it I have another design problem: How can I make my AI classes aware of the projectile class as well? Their decisions will depend on properties of the projectile being fired, such as how many times they can bounce off walls. Both the AI and Weapon classes are being given a reference to the parent Tank upon injection.
Edit:
It seems like my original question was a bit confusing, so I'll post code. I already have the DI set up for my tank.
public class Tank : ISolidObject
{
public TankAI AISystem { get; private set; }
public TankWeapon Weapon { get; private set; }
public Tank(TankAI aiSystem, TankWeapon weapon)
{
this.AISystem = aiSystem;
this.AISystem.Tank = this;
this.Weapon = weapon;
this.Weapon.Tank = this;
}
}
public abstract class TankAI
{
public Tank Tank { get; set; }
public abstract void Think();
}
// TankAI implementations aren't important here
public abstract class TankWeapon
{
protected int maxShotsOnScreen, shotsOnScreen;
public Tank Tank { get; set; }
public virtual void Shoot()
{
shotsOnScreen++;
// I really want to put the projectile construction code in here
}
}
public class BulletWeapon : TankWeapon
{
public BulletWeapon()
{
this.maxShotsOnScreen = 5;
this.turnSpeed = 1;
}
public override void Shoot()
{
// here's my problem. Every weapon class duplicates this, because I can't put the projectile construction in the base weapon class.
if (shotsOnScreen >= maxShotsOnScreen) return;
base.Shoot();
// just create it, it will take care of the rest
double bx = Tank.X - Math.Sin(Tank.AngleTurret * Math.PI / 180.0);
double by = Tank.Y + Math.Cos(Tank.AngleTurret * Math.PI / 180.0);
// note that projectiles subscribe themselves to the game entity handler, so don't have to store it myself.
// this weapon creates bullets. A different weapon might create rockets. How would the base class know which? Is there any way I can prevent this code from being duplicated?
new Bullet(bx, by, Tank.AngleTurret).Death += ShotDeath;
}
private void ShotDeath(Projectile p)
{
p.Death -= ShotDeath;
shotsOnScreen--;
}
}
For the first question, it sounds like you need a ProjectileFactory
It would look something like
// somewhere in tank weapon's Fire method or whatever
Projectile p = projectileFactory.Create( myProjectile.GetType() );
For the second question, have the AI require injection of a Projectile or a Type
public Tank( TankAi ai, TankWeapon w) // ...
public TankWeapon( Tank t, Projectile p ) // ...
public TankAi( Tank t, Projectile p ) // ...
public TankAi( Tank t, Type projectileType ) // ...
A question for you...Why do the weapon and ai get references to the tank?
It sounds like you aren't using enough Interfaces. It helps to think about the distinction between behavior (implementation) and functionality (the exposed interface).
You want each projectile, AI, and weapon to function the same way (to have the same interface) but to implement unique behavior, with some shared behaviors. A typical model of such would be to have IWeapon, IProjectile, and IIntelligence interfaces which define the exposed public face of those objects. Then you'd have a base class of each (BaseProjectile, for example) that implements the interface, and provides some common behavior for all Projectiles to use.
Now in the constructor (or a setter, or whereever) on your classes, you take in an Interface to the type.
So AI_Tank_Boss class might look like
public class AI_Tank_Boss : BaseTank
public AI_Tank_Boss(IWeapon weapon, IInteligence ai)
{
this.Weapon = weapon;
this.AI = ai;
}
Now each of your tank methods that rely on an AI method (perhaps events that fire from the AI and the tank looks to those events to do something?) can be implemented to use the interface, and any weapon-specific code will call the IWeapon interface.
What actually happens is based on how the particular Weapon subclass implements the methods and how it uses the common code in the BaseWeapon. This is the basis of polymorphism and why injection works.
Passing a class to the base upon construction is indeed the wrong way to go. The base class should have no knowledge of its derived classes. If you "have to somehow inject the projectile class itself that the weapon needs to construct" it means you haven't designed your class hierarchy and methods properly.
Unless you post here and example of what you need to pass, it would be very difficult for me to provide a specific solution.