I'm working on a game for WP7 with XNA. Here is my structure:
public abstract class enemy
{}
Child elements:
public class genericEnemy : enemy{}
...
public class snake : enemy {}
etc...
In WP7, a lot of things have been moved around and/or removed (especially with Serialization) it seems. Despite much searching, I haven't been able to find a solution. I'm trying to duplicate the child elements.
For example: On loading a level, I pass an array of three different enemies into the loading phase. During loading, I need to duplicate each of those enemies so that 20 of each are flying around doing their own thing during gameplay.
All the solutions I've seen refer to things that are not present in the WP7 library.
There's no "library" way of doing this as far as I know. One solution would be:
1) Declare a Clone() method in enemy that returns a copy of that enemy.
abstract class Enemy {
public abstract Enemy Clone();
}
2) Implement it in every concrete type, so a Snake creates a new Snake, etc. Example:
class Snake : Enemy {
int speed;
public override void Enemy Clone() {
var clone = new Snake();
clone.speed = speed;
return clone;
}
}
3) Now any object of a concrete type knows how to clone itself, so if you have an array of Enemies, you can call Clone() on each and it will create the proper concrete type in the proper way.
Create an enemy factory that can create enemies from an id of some sorts. While loading your level, you can then call the factory when you need to create an enemy:
class EnemyFactory
{
Enemy CreateEnemy(int id)
{
if (id == 0)
return new Snake();
return new GenericEnemy();
}
}
void LoadLevel()
{
// bla bla
Level level = new Level();
int enemyId = LoadFromFile();
level.AddEnemy(EnemyFactory.CreateEnemy(enemyId));
}
This way you get rid of the nasty cloning code, and you can control all enemy instantiation in the factory class.
use an abstract method that calls a copy constructor:
public abstract class Enemy
{
private readonly int mEnemyData;
protected Enemy(Enemy pEnemy)
{
mEnemyData = pEnemy.mEnemyData;
}
public abstract Enemy Clone();
}
public sealed class GenericEnemy : Enemy
{
private readonly double mGenericEnemyData;
private GenericEnemy(GenericEnemy pGenericEnemy)
: base(pGenericEnemy)
{
mGenericEnemyData = pGenericEnemy.mGenericEnemyData;
}
public override Enemy Clone()
{
return new GenericEnemy(this);
}
}
Related
TLDR: How can I have a script that inherits from a public abstract class have access to an often changing Enemy gameObject variable (so it can't be static) without passing it through several other scripts first?
In my game, I have a battle system where a different "Battle Event" gets loaded for each battle. Each "Battle Event" gets its own script, and each of those events inherits from the same BattleEvent parent (which is public abstract).
The code structure basically goes:
BattleSystem (main brain of battles which holds the Enemy
gameObject) ->
BattleEventsManager (handles both which BattleEvent to load, and which methods to run on that BattleEvent) ->
a random BattleEvent (BattleEventOne or BattleEventTwo etc)
public class BattleSystem : MonoBehaviour
{
BattleEventsManager battleEventsManager;
public Enemy currentEnemy;
// the Enemy data is passed when the battle starts
public void Start(Enemy enemyToLoad)
{
battleEventsManager = GetComponent<BattleEventsManager>();
currentEnemy = enemyToLoad;
}
public void BeginPlayerTurn()
{
battleEventsManager.SetupEvent(currentEnemy);
}
}
public class BattleEventsManager : MonoBehaviour
{
BattleEvent currentBattleEvent;
private void Awake()
{
// define this battleEvent
currentBattleEvent = GetComponent<BattleEventOne>();
}
public void SetupEvent(Enemy currentEnemy)
{
// start the battleEvent with its Setup function
currentBattleEvent.Setup(currentEnemy);
}
}
// inherits from `BattleEvent` parent class, shown below
public class BattleEventOne : BattleEvent
{
// override the method from the parent
public override void Setup(Enemy currentEnemy) {
// we can now use the data we need in `currentEnemy`
// all I wanted was to get access to `BattleSystem.currentEnemy`
// but i had to pass it down all the way here. Is there a better way?
}
}
// parent of all `BattleEvents`
public abstract class BattleEvent : MonoBehaviour
{
public abstract void Setup(Enemy currentEnemy);
} // end BattleEvent class
As you can see, the the currentEnemy variable needs to be passed down through 2 classes in order to get to where it needs to be: BattleEventOne.Setup().
Furthermore, I needed to add the Enemy currentEnemy param to the parent BattleEvent, which is problematic because not all BattleEvents will need this information.
I originally wanted to just call BattleSystem.currentEnemy from BattleEventOne (using a property or something), but because the BattleSystem is abstract/static, it can't access it. And because currentEnemy contains new data each battle, I can't make that a static variable.
So, how can I have BattleEventOne here access BattleSystem.currentEnemy without having to pass it down as I've done above?
(I still struggle a lot with passing information between scripts, so any help here is really appreciated!)
So I'm experimenting with DI and am trying to create a GameObject Generator.
That GameObject Generator generates GameObjects inside the scene based on some internal logic.
There is variation to what kinds of GameObjects are generated and the logic can vary.
I thought that I could create a Interface and be able to create a class per "unique logic" (i.e. for every generator behaviour i create a class and can switch between generating a lot of small objects and a couple of big objects without having to use if statements, but instead the power of polymorphism).
So I've got something like
GameObjectGenerator : Monobehaviour
IGeneratorType
SmallGenerator : Monobehaviour, IGeneratorType
BigGenerator : Monobehaviour, IGeneratorType
from a logical standpoint this seems to be making sense.
The issue arrises, when transitioning from those generators.
I want to have some sort of condition, where i call a method "TransitionGenerator" from IGeneratorType
that returns a new IGeneratorType. Logically this is working aswell.
However, i want to keep track of my generated Objects (in a list for instance), because they need to be Destroyed later.
When transitioning, the List of generated Objects need to be passed to the new IGeneratorType.
This is where I find myself struggling.
The classes that implement from IGeneratorType need to extend Monobehaviour aswell because i need to make calls to Instantiate and Destroy.
But because they extend from Monobehaviour, I can't seem to create a constructor.
After a bit of research i found a lot of people pointing to either Awake/Start or to creating a Init method.
The problem is, with Awake/Start i cant pass anything and with Init, i would need to put that into the interface aswell, which doesnt make a lot of to me sense from a design standpoint.
Example code:
public class GameObjectGenerator : Monobehaviour{
private IGeneratorType generator;
public void Start(){
generator = new SmallGenerator();
}
public void Update(){
generator.Generate();
if(somecondition){
generator = generator.Transition();
}
}
}
public interface IGeneratorType{
void Generate();
IGeneratorType Transition();
}
public class SmallGenerator : Monobehaviour, IGeneratorType{
private List<GameObject> generatedObjects;
public SmallGenerator(/*List<GameObject> previousObjects*/){
//generatedObjects = previousObjects;
}
public void Generate(){
//...
if(somespecificcond){
generatedObjects.Add(Instantiate(...));
}
if(somecondition){
Destroy(generatedObjects[0])
}
}
public IGeneratorType Transition(){
return new BigGenerator(/*generatedObjects*/);
}
}
public class BigGenerator : Monobehaviour, IGeneratorType{
private List<GameObject> generatedObjects;
public BigGenerator(/*List<GameObject> previousObjects*/){
//generatedObjects = previousObjects;
}
public void Generate(){
//...
if(somespecificothercond){
generatedObjects.Add(Instantiate(...));
}
if(somecondition){
Destroy(generatedObjects[0])
}
}
public IGeneratorType Transition(){
return new SmallGenerator(/*generatedObjects*/);
}
}
I just found the simplest workaround to this specific case:
public class BigGenerator : IGeneratorType{
private List<GameObject> generatedObjects;
public BigGenerator(/*List<GameObject> previousObjects*/){
//generatedObjects = previousObjects;
}
public void Generate(){
//...
if(somespecificothercond){
generatedObjects.Add(Object.Instantiate(...));
}
if(somecondition){
Object.Destroy(generatedObjects[0])
}
}
public IGeneratorType Transition(){
return new SmallGenerator(/*generatedObjects*/);
}
}
This works because Instantiate and Destroy are static methods from "Object", of which "GameObject" inherits.
However this doesn't solve the problem in case one really HAS TO inherit from monobehaviour
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.
I want to create a class named Enemy, which should be used in a programmed rpg-themed-battlesystem. The problem is that I would want to create multiple monster types in the Enemy class, but then I would have to create a possibility for the battlesystem with every enemy class for example Enemy.Goblin or Enemy.Golem.
Question:
How could I achieve this by using only one parameter in the battlesystem function? I wanted to use
public static void InitiateBattle ( Player player, Enemy enemy )
but now I cannot use the Enemy.Goblin instance, because it cant implicitly convert Enemy.Goblin to Enemy. How could I most easily and with minimal code fix this?
You need to use inheritance.
public class Enemy
{
// put all properties and methods common to all here
}
public class Goblin: Enemy
{
// goblin specific stuff here
}
you will then be able to pass in a goblin as an enemy.
It sounds like you want to use inheritance?
public class Enemy {}
public class Goblin : Enemy {}
public class Golem : Enemy {}
You can then pass in an instance of Goblin or Golem to your method and the statement will be valid because the compiler will 'box' your object into an instance of the parent type.
Then, if you want to use a member from the Goblin or Golem subclasses, you would need to 'cast' the enemy parameter variable back into the appropriate type using as:
public static void InitiateBattle (Player player, Enemy enemy)
{
var golem = enemy as Golem;
var goblin = enemy as Goblin;
}
Make sure you check for null after the cast!
Bear in mind that C# does not allow multiple-inheritance; each class can inherit from only one parent.
I think it would be best to use interface.
public interface IEnemy
{
//e.g.
public void Attack();
}
public class Goblin : IEnemy
{
public void Attack()
{
throw new System.NotImplementedException();
}
}
public class Battle
{
public static void InitiateBattle(Player player, IEnemy enemy);
}
I'm stuck in this situation where:
I have an abstract class called Ammo, with AmmoBox and Clip as children.
I have an abstract class called Weapon, with Firearm and Melee as children.
Firearm is abstract, with ClipWeapon and ShellWeapon as children.
Inside Firearm, there's a void Reload(Ammo ammo);
The problem is that, a ClipWeapon could use both a Clip and an AmmoBox to reload:
public override void Reload(Ammo ammo)
{
if (ammo is Clip)
{
SwapClips(ammo as Clip);
}
else if (ammo is AmmoBox)
{
var ammoBox = ammo as AmmoBox;
// AddBullets returns how many bullets has left from its parameter
ammoBox.Set(clip.AddBullets(ammoBox.nBullets));
}
}
But a ShellWeapon, could only use an AmmoBox to reload. I could do this:
public override void Reload(Ammo ammo)
{
if (ammo is AmmoBox)
{
// reload...
}
}
But this is bad because, even though I'm checking to make sure it's of type AmmoBox, from the outside, it appears like a ShellWeapon could take a Clip as well, since a Clip is Ammo as well.
Or, I could remove Reload from Firearm, and put it both ClipWeapon and ShellWeapon with the specific params I need, but doing so I will lose the benefits of Polymorphism, which is not what I want to.
Wouldn't it be optimal, if I could override Reload inside ShellWeapon like this:
public override void Reload(AmmoBox ammoBox)
{
// reload ...
}
Of course I tried it, and it didn't work, I got an error saying the signature must match or something, but shouldn't this be valid 'logically'? since AmmoBox is a Ammo?
How should I get around this? And in general, is my design correct?
(Note I was using interfaces IClipWeapon and IShellWeapon but I ran into trouble, so I moved to using classes instead)
Thanks in advance.
but shouldn't this be valid 'logically'?
No. Your interface says that the caller can pass in any Ammo - where you're restricting it to require an AmmoBox, which is more specific.
What would you expect to happen if someone were to write:
Firearm firearm = new ShellWeapon();
firearm.Reload(new Ammo());
? That should be entirely valid code - so do you want it to blow up at execution time? Half the point of static typing is to avoid that sort of problem.
You could make Firearm generic in the type of ammo is uses:
public abstract class Firearm<TAmmo> : Weapon where TAmmo : Ammo
{
public abstract void Reload(TAmmo ammo);
}
Then:
public class ShellWeapon : Firearm<AmmoBox>
That may or may not be a useful way of doing things, but it's at least worth considering.
You can use composition with interface extensions instead of multiple-inheritance:
class Ammo {}
class Clip : Ammo {}
class AmmoBox : Ammo {}
class Firearm {}
interface IClipReloadable {}
interface IAmmoBoxReloadable {}
class ClipWeapon : Firearm, IClipReloadable, IAmmoBoxReloadable {}
class AmmoBoxWeapon : Firearm, IAmmoBoxReloadable {}
static class IClipReloadExtension {
public static void Reload(this IClipReloadable firearm, Clip ammo) {}
}
static class IAmmoBoxReloadExtension {
public static void Reload(this IAmmoBoxReloadable firearm, AmmoBox ammo) {}
}
So that you will have 2 definitions of Reload() method with Clip and AmmoBox as arguments in ClipWeapon and only 1 Reload() method in AmmoBoxWeapon class with AmmoBox argument.
var ammoBox = new AmmoBox();
var clip = new Clip();
var clipWeapon = new ClipWeapon();
clipWeapon.Reload(ammoBox);
clipWeapon.Reload(clip);
var ammoBoxWeapon = new AmmoBoxWeapon();
ammoBoxWeapon.Reload(ammoBox);
And if you try pass Clip to AmmoBoxWeapon.Reload you will get an error:
ammoBoxWeapon.Reload(clip); // <- ERROR at compile time
The problem with which you are wrestling comes from the need to call a different implementation based on the run-time types of both the ammo and the weapon. Essentially, the action of reloading needs to be "virtual" with respect to two, not one, object. This problem is called double dispatch.
One way to address it would be creating a visitor-like construct:
abstract class Ammo {
public virtual void AddToShellWeapon(ShellWeapon weapon) {
throw new ApplicationException("Ammo cannot be added to shell weapon.");
}
public virtual void AddToClipWeapon(ClipWeapon weapon) {
throw new ApplicationException("Ammo cannot be added to clip weapon.");
}
}
class AmmoBox : Ammo {
public override void AddToShellWeapon(ShellWeapon weapon) {
...
}
public override void AddToClipWeapon(ClipWeapon weapon) {
...
}
}
class Clip : Ammo {
public override void AddToClipWeapon(ClipWeapon weapon) {
...
}
}
abstract class Weapon {
public abstract void Reload(Ammo ammo);
}
class ShellWeapon : Weapon {
public void Reload(Ammo ammo) {
ammo.AddToShellWeapon(this);
}
}
class ClipWeapon : Weapon {
public void Reload(Ammo ammo) {
ammo.AddToClipWeapon(this);
}
}
"The magic" happens in the implementations of Reload of the weapon subclasses: rather than deciding what kind of ammo they get, they let the ammo itself do "the second leg" of double dispatch, and call whatever method is appropriate, because their AddTo...Weapon methods know both their own type, and the type of the weapon into which they are being reloaded.
I think, that it's perfectly fine to check, whether passed Ammo is of valid type. The similar situation is, when function accepts a Stream, but internally checks, whether it is seekable or writeable - depending on its requirements.