- Home /
Creating new instances of a child class within a function's for loop after it's passed as a parameter of the parent class type
(Edit: Do not post when you're tired and stupid, and you're changing names of classes without updating posts with the same new information, like me) I have a RoadsideObject parent class that contains fields (settings) that all derived classes should share. I have a derived class named TreeLeft. TreeLeft's constructor will randomize the settings derived from RoadsideObject when new instances of TreeLeft are created. I have a function to add RoadsideObjects to a road named AddRoadsideObjects(RoadsideObject ro) which I pass TreeLeft to. AddRoadsideObjects(TreeLeft) has a for loop that needs to create new instances of TreeLeft and add them to an array (I've left that code out, because it's irrelevant). Is it possible to do this or am I thinking about this entirely wrong? Pointing me in the right direction, possibly to a tutorial that doesn't read like some kind of AGI wrote the thing without concern for the idiots (me) that can't understand its lingo would be appreciated. I keep coming across things like "generics" and "reflection", which I suspect is closer to some answer, but I'm still not really understanding how any of that could apply to what I need. Thanks.
public class RoadsideObject{
public float xOffset;
public float yOffset;
public float xScale;
public float yScale;
}
public class TreeLeft : RoadsideObject{
public TreeLeft(){
xOffset = Random.Range(-7, 7)
yOffset = Random.Range(-7, -5);
xScale = Random.Range(2, 4);
yScale = Random.Range(2, 4);
}
}
//ANOTHER MONOBEHAVIOUR SCRIPT
void Start(){
AddRoadsideObjects(TreeLeft){
}
}
private void AddRoadsideObjects(RoadsideObject ro){
for(int i = 0; i < count; i++){
//CREATE NEW INSTANCES OF RO AND PUT THAT SILLINESS ON THE ROAD.
}
}
The most naive way to do this seems to be just making an enum for the kind of Roadside Object you want to make:
public enum RoadsideObjectType
{
Tree = 1,
Barrel = 2,
Box = 3,
// ...
}
Then have that function return whatever type that enum specifies by giving the base type back:
private RoadsideObject AddRO(RoadsideObjectType objectType)
{
switch( objectType)
{
case RoadsideObjectType.Tree:
return new ROTreeLeft();
case RoadsideObjectType.Box:
return new ROBox();
//...
}
}
@TreyH Looks doable, but I think bunny83's answer may be more of what I need. I haven't used enumerations before, but it looks easy enough. Thanks. I'll come back after refactoring and give upvotes or however this works.
Is this a normal c# class that just happens to have a method called Start() or is this a monobehaviour? $$anonymous$$onoBehaviours can't have. Constructors :/
To give a "good answer" we'd probably need to know still a bit more about the whole system. Or maybe I'm jist lacking in imagination :)
Is the AddRO() there for adding RO's to ther RO's or why do you need a method like that to exist on a RO?
Why does it take an RO as a parameter? Does it need to copy some field values from it or is it just for letting the method know which type of object to create (in that case the parameter's type should probably be System.Type)
Should the method always produce an object of the child type on which the method was called?
@Nose$$anonymous$$ills Sorry for the confusion. I've fixed the post and code and with new comments. Again, I think bunny's answer is what I really need.
Answer by Bunny83 · Jun 19, 2017 at 05:25 PM
Uhm, your code doesn't have a class named ROTree but only a class called RSOTreeLeft. If that's the class you want to create an instance of, just do
AddRO( new RSOTreeLeft() );
This will create an instance of your "RSOTreeLeft" class and pass the new instance to the AddRO method.
If you want to just pass a type argument to the method, you can't do that with a normal parameter but with a generic type parameter. Though in order for the method to be able to create a new instance of the type argument passed you need to add some constraints. First we require the type to be derived from RoadsideObject and we require the type to have a parameterless constructor:
private void AddRO<T>() where T : RoadsideObject, new()
{
RoadsideObject inst = new T();
// ...
}
This method can be used like this:
AddRO<RSOTreeLeft>();
edit
There's another way using reflection and a System.Type reference. You can do:
void AddRO(System.Type aType)
{
if (aType == null)
throw new System.ArgumentNullException("aType");
if (typeof(RoadsideObject).IsAssignableFrom(aType)) // dynamic type check
throw new System.ArgumentException("aType is not derived from RoadsideObject", "aType");
RoadsideObject inst = (RoadsideObject)System.Activator.CreateInstance(aType);
// ...
}
To use this version you would need to pass the type like this;
AddRO( typeof(RSOTreeLeft) );
Note that in this case there's no way to restrict the type at compiletime as reflection operates at runtime. So you have to make sure the System.Type reference you pass is actually derived from "RoadsideObject" and has a parameterless constructor that the Activator can use.
Updated to fix my dyslexic mistakes, thanks. I'll give both your answers a try and come back with the results (marking of answers) after refactoring.
@Bunny83 Thank you so much for being awesome in the community. I always find your answers really helpful, that is, if I understand what the hell you're talking about, which I did this time.
private void AddRoadsideObjects<T>(int start, int num, int interval) where T : RoadsideObject, new(){
for(int i = start; i < num * interval; i += interval){
RoadsideObject ro = new T();
Stuff[i].ros.Add(ro);
}
}
void Start(){
AddRoadsideObjects<TreeLeft>(0, 100, 1);
}
wave! :)
Is there not a way to send "P$$anonymous$$s" on answers.unity3d ?!
Your answer
Follow this Question
Related Questions
GUI set max amount of characters for Label 1 Answer
Make a simple tree 1 Answer
Delegates and class constructors 1 Answer
Edit each Parameter Class on Function 1 Answer
All Arrayinstances get changed -1 Answers