[C#] Using Static Create() methods with inheritance and Monobehaviours?

I have a world composed of Regions, Cities, Buildings, and [specific buildings]. They all inherit from an abstract Location, and the specific buildings inherit from Buildings.

I keep running into problems in creation though, since I can’t use a constructor. Where I would usually just do:

public City(Region inParentRegion, string inName): base(inName)
{
	//stuff
}

I was thinking I’d have the “top-level real gameobjects” like cities/regions/etc pass a prefab up to the Location create method, have it go through adding all the location specific code, return that object to the City(or such) Create method where the specific code is added and the object is parented to the right thing, but I’m not quite sure how to go about doing that or if it’s even the right direction.

How have you dealt with inheritance in monobehaviours? And with the complications from having an abstract top-level class?

To add more wrinkles to the problem, it seems that while usually a class inheriting from a monobehaviour counts as one as well, it doesn’t work if that class is abstract?

Currently, this is what I have but doesn’t work, as “Location newLoc = (Location) Instantiate(prefab);” obviously wouldn’t work in this context, but I’m not quite sure how to do this part.

public abstract class Location: MonoBehaviour, ITargetable
{
	//stuff	
	protected static Location Create(GameObject prefab, string name)
	{
		Debug.Log(string.Format("Generating new location: {0}", name));
		//Make Object
		Location newLoc = (Location) Instantiate(prefab);
		newLoc.Name = name;
		//etc		
		return newLoc;
	}
}

public class City: Location
{
	//stuff
	
	public static City Create(Region parentRegion, string name)
	{
		City newCity = (City) Location.Create(WorldManager.Find.CityPrefab, name);

		newCity.ParentRegion = parentRegion;
		//etc		
		return newCity;
	}
}

It is not obvious from your question as to what you’re trying to accomplish. But my interpretation is that you need your buildings to be some sort of a data class. Unity has ScriptableObjects for exactly that purpose. They are internally the same thing as MonoBehaviour, only don’t need to be attached to a gameobject. Unity - Scripting API: ScriptableObject

However, if you do not need the functionality of a MonoBehaviour, as would be the case when representing some sort of internal logic of a part of your world, you need not inherit from MonoBehaviour, which leaves you open to programming ‘normally’ whereby your constructor approach could work.

Well, Start and Awake are essentially the constructor for MonoBehaviours. Awake runs inline with your code as you instantiate a thing, but Start waits until … well, later. It’s like, just before the next frame or something. But you can essentially “send constructor parameters to Start” by setting the behaviour’s fields after instantiation/Awake. Then the MB can handle whatever it needs to do privately in Start. It’s messy, but that’s the way of MBs.

Set the values after instantiating your city, then each class’s Start can call its own base.Start().

public abstract class Location : MonoBehaviour {
  public string myName = "";
  public virtual void Start() {
    myName = "Location " + myName;
  }
}

public class City : Location {
  public override void Start() {
    base.Start();
    myName = "City " + myName;
    Debug.Log(name + "'s name is " + myName);
  }
}

...
City newCity = Instantiate(prefab);
newCity.myName = "Durham";

You could try to use interfaces

interface ILocation {

// put your interface members here
// Variables, methods..

}

then in your classes you inherit from MonoBehaviour and from the interface so your class needs to implement the interfaces members.

class City : MonoBehaviour, ILocation {
// implement ILocation member

}

Then you can handle all your objects as ILocation where needed.