Reputation: 976
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*/);
}
}
Upvotes: 1
Views: 755
Reputation: 976
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
Upvotes: 1