Pass type as parameter to instanciate a given child

Hello there.
I’m moving from GameMaker to Unity, and I’m having some troubles.
For instance (for those who know GameMaker), you can pass a the type of an object in a method and do what I’m trying to achieve simply by using:

myMethod(object_index, position)

// In "myMethod"
instance_create(argument0, argument1)

When I’ve started trying to do something similar in Unity, I haven’t found a proper way despite visiting forums to look for solutions. In my example I want to instanciate a given piece for a chess game. I have the following code:

// Somewhere we call a method:
PlacePiece(typeof(Pawn), Vector3 (0, 0, 0));

// The PlacePiece method
void PlacePiece(System.Type t, Vector3 v) {
        Piece inst = Instantiate (t, v, Quaternion.identity);
        if(isBlack) a = 1;
        else a = 2;
}

I’ve also tryied to use generics with “void PlacePiece(Vector3 v)”, but then when I try to call this method with PlacePiece(Vector3(0,0,0)), I have a similar error stating that I’m denoting a type instead of a variable / value / method group.
Any idea to solve the problem?

Instantiate is for creating instances from prefabs. It basically clones a unity object and it’s entire component/hierarchy structure.

System.Activator.CreateInstance - Activator.CreateInstance Method (System) | Microsoft Learn
This will create an instance of a class from a type.

There is also a generic version:

This is used for creating instances of regular old classes. It’s like calling ‘new Pawn()’ but when you don’t explicitly know it’s ‘Pawn’ and instead only have the Type object for it instead.

This doesn’t work for unity components though, because you can’t call ‘new Pawn()’ if Pawn is a component (a MonoBehaviour). Unity requires them to be attached to a GameObject.

GameObject.AddComponent - Unity - Scripting API: GameObject.AddComponent

AddComponent is how you add components to GameObjects. There is a version that takes string, one that takes the System.Type object, and one that works with generics.

Note, you must already have an instance of GameObject to add to first.

You can just pass a GameObject in the argument, which is usually a prefab.

GameObject PlacePiece(GameObject piece,Vector3 pos){
  GameObject go =Instantiate(piece, pos, Quaternion.identity);
return go;
}

Now that I reread your question, I don’t think that’s what you were after.

My goal is to create an instance from a prefab without having any variable prior to the method call.
If I want to use the PlacePiece method to instantiate a Pawn, considering the fact I haven’t instanciated anything yet, how should I do then? If I cannot specify the type of prefab I want to instanciate, because my Pawn is indeed a MonoBehaviour

I’m not sure I still understand, but generally, and you probably already know this, but you create your pawn prefab, then you create a public GameObject pawn or whatever, and drag it onto that variable, so it stays in the project until you instantiate it, it’s not in the scene, but you do need a reference to it for instantiation.

So if I understand you correctly, I cannot have a way to instanciate an object that I haven’t referenced somewhere? Except via the Resource folder…

But I just cannot understand the logic, like why it isn’t possible to instanciate an object X that you’ve made a class for.
Like you’d do with the new keyword

The classes you write and attach to GameObjects are MonoBehaviours, which are simply components. A MonoBehaviour on its own won’t be useful, and likely just crash depending on how it’s coded. You could create a new game object and add the components you need to create a chess piece but that’s a lot of unnecessary work. With how Unity works, it’s easier to instantiate a prefab because of how the component system works.

But then if I have to instantiate a Piece that could be either a Pawn, a Rook, or Knight, I will have to use 3 public variables like Pawn pawnPrefab, Rook rookPrefab, Knight knightPrefab, and drag the prefabs into the correct fields so I can later use PlacePiece(pawn/rook/knightPrefab)?
I mean, is it the cleanest and/or the fastest way to do it?

Yes, they’ll have ti be referenced somewhere or in the scene. But specific implementation depends on what you’re trying to do. Are you going to have different styles of pieces or is this for when a pawn reaches the other side of the board?

I’ve started with a basic chess game but I could imagine variations, and in my case I wanted to be able to use a method in my Player class so that the Player places a piece on the board. To make it generic I wanted to be able to specify only a Piece type and then see at runtime which one he places. That’s where I had my problem, since I wanted to specify a class name only

Hmm…will the player get to choose which piece to place, or will it be a predetermined order?

No, the player will be able to choose, depending on various settings that can seem unpredictable depending on many factors.

My working solution seems weird but works for now:

public class Player : MonoBehaviour {

    // References
    public Pawn pawnPrefab;
    public Rook rookPrefab;
    public Bishop bishopPrefab;
    public Knight knightPrefab;
    public Queen queenPrefab;
    public Material whiteColor;
    public Material blackColor;
    // Player properties
    public bool isHuman;
    public bool isBlack = false;
    //private Pawn[] pawns = new Pawn[8];

    void Start () {
        if (isHuman) {
            PlacePiece (pawnPrefab, new Vector3 (0, 0, 0));
        }
    }

    void PlacePiece(Piece p, Vector3 v) {
        Piece inst = Instantiate (p, v, Quaternion.identity);
        if(isBlack) inst.GetComponent<Renderer> ().material = blackColor;
        else inst.GetComponent<Renderer> ().material = whiteColor;
        //pawns [0] = (Pawn)inst;
    }

}

But since I’m new to Unity, I couldn’t say how messy or not this solution is.
In this case I just used my booleans to perform the test but it has nothing to do with what it’ll be in the end. The interesting part that I’ll reuse for sure is calling “PlacePiece” with the right prefab depending on the player’s choice