/// <summary>
/// Hack And Slash Quick Mob Maker
/// RJ Mitchell - 21 August 2011
/// YouTube Channel - RJ36UK
/// The object of this class is to help simplify the process of creating new mobs for the Hack and Slash series currently being run by Burgzerg Arcade.
/// I highly recommend that you make a new folder in your Assets directory for saving the prefabs to, aside from making it easy for you to locate
/// those models straight away it will help prevent any accidental overwrite of any previous prefabs you may have made with the same name.
///
/// When using this Editor script I suggest you use an empty scene with nothing in the heirarchy other than the main camera if you wish. You do not need to keep the scene after
/// you have finished setting up your mobs as it is only there to help avoid any cross references from other models in the heirarchy.
/// All models once generated will be saved into either your Assets folder by default or to a pre-designated folder assigned in the interface.
/// UPDATE: Updated the prefab save to use the new PrefabUtility command. 03/06/12
/// </summary>
///
using UnityEngine;
using UnityEditor;
public class HackAndSlashMobMaker : EditorWindow
{
// GUI Layout predifined positions for easier placements
private const float NAME_X_POS = 5F;
private const float NAME_Y_POS = 20F;
private const float NAME_WIDTH = 100F;
private const float NAME_HEIGHT = 20F;
private const float NAME_X_OFFSET = 0F;
private const float NAME_Y_OFFSET = 25F;
private const float FIELD_X_POS = 110F;
private const float FIELD_Y_POS = 20F;
private const float FIELD_WIDTH = 150F;
private const float FIELD_HEIGHT = 20F;
private const float FIELD_X_OFFSET = 0F;
private const float FIELD_Y_OFFSET = 25F;
private const string DEFAULT_NAME = "Enter Name";
// Mount point names (exposed in interface to allow for different naming conventions via Get/Set)
private string _mpWeaponMount = "WeaponMount";
private string _mpOffHandMount = "OffHandMount";
private string _mpHairMount = "HairMount";
private string _mpHelmetMount = "HelmetMount";
private string _mpCMatMesh = "CharacterMaterialMeshMount";
private string _mpNameText = "Name";
private string _mpTagName = "Enemy";
#region Object variables
// Mob stat variables, If the mob is at these defaults it will prevent a mob from being generated.
public GameObject createdChar;
private int _hitPoints = 0;
private int _mana = 0;
private string _name = "Enter Name";
// Precheck variables
private bool[] _pregenCheck = new bool[4] {false, false, false, false};
private string[] _checkName = new string[4] {"Mob Name", "Hit Points", "Mana", "Mob Model"};
// Mount point holders
private Object _mobGO = null;
private Object _mobWM = null;
private Object _mobOH = null;
private Object _mobHairMount = null;
private Object _mobHelmetMount = null;
private Object _mobCMMesh = null;
private Object _mobNP = null;
// Misc Variables
private bool _generateMob = false;
private bool _warnMSG = false;
private string _errorCheckName = "";
private string _saveFolder = "";
private bool _reset = false;
private bool _defaults = false;
#endregion
// Public Variables
#region Getters & Setters
public int HitPoints {
get {
return this._hitPoints;
}
set {
_hitPoints = value;
}
}
public int Mana {
get {
return this._mana;
}
set {
_mana = value;
}
}
public string Name {
get {
return this._name;
}
set {
_name = value;
}
}
public Object MobPrefab {
get {
return this._mobGO;
}
set {
_mobGO = value;
}
}
public Object MobWeaponMount {
get {
return this._mobWM;
}
set {
_mobWM = value;
}
}
public Object MobOffHandMount {
get {
return this._mobOH;
}
set {
_mobOH = value;
}
}
public Object MobCharacterMaterialMesh {
get {
return this._mobCMMesh;
}
set {
_mobCMMesh = value;
}
}
public Object MobHairMount {
get {
return this._mobHairMount;
}
set {
_mobHairMount = value;
}
}
public Object MobHelmetMount {
get {
return this._mobHelmetMount;
}
set {
_mobHelmetMount = value;
}
}
public Object MobTextName {
get {
return this._mobNP;
}
set {
_mobNP = value;
}
}
public string MpTagName {
get {
return this._mpTagName;
}
set {
_mpTagName = value;
}
}
public string MpCMatMesh {
get {
return this._mpCMatMesh;
}
set {
_mpCMatMesh = value;
}
}
public string MpHairMount {
get {
return this._mpHairMount;
}
set {
_mpHairMount = value;
}
}
public string MpHelmetMount {
get {
return this._mpHelmetMount;
}
set {
_mpHelmetMount = value;
}
}
public string MpTextName {
get {
return this._mpNameText;
}
set {
_mpNameText = value;
}
}
public string MpOffHandMount {
get {
return this._mpOffHandMount;
}
set {
_mpOffHandMount = value;
}
}
public string MpWeaponMount {
get {
return this._mpWeaponMount;
}
set {
_mpWeaponMount = value;
}
}
public string SaveFolder {
get {
return this._saveFolder;
}
set {
_saveFolder = value;
}
}
#endregion
public GUISkin EdGuiSkin;
// Link to this tool in Windows Toolbar option
[MenuItem ("Window/Hack And Slash Mob Maker")]
// Initialize our window when we call
static void Init()
{
GetWindow(typeof(HackAndSlashMobMaker));
}
public HackAndSlashMobMaker()
{
}
#region Update
void Update()
{
if(_reset)
{
Name = DEFAULT_NAME;
HitPoints = 0;
Mana = 0;
MobPrefab = null;
_generateMob = false;
_warnMSG = false;
}
if(_defaults)
{
Name = DEFAULT_NAME;
HitPoints = 0;
Mana = 0;
MobPrefab = null;
_generateMob = false;
_warnMSG = false;
_mpWeaponMount = "WeaponMount";
_mpOffHandMount = "OffHandMount";
_mpHairMount = "HairMount";
_mpHelmetMount = "HelmetMount";
_mpCMatMesh = "CharacterMaterialMeshMount";
_mpNameText = "Name";
_mpTagName = "Enemy";
_saveFolder = "";
}
if(_generateMob)
GenerateMob();
}
#endregion
public void OnGUI()
{
GUI.skin = EdGuiSkin;
// Set background colour of Editor Panel
EditorGUIUtility.DrawColorSwatch(new Rect(0F, 0F, Screen.width, Screen.height), new Color(0.16F, 0.17F, 0.16F));
// Main Header
GUI.Label(new Rect(NAME_X_POS, NAME_Y_POS*0.5F, NAME_WIDTH*2.35F, NAME_HEIGHT+5), " Hack & Slash Mob Maker - RJM36UK", GUI.skin.GetStyle("Box"));
// Area Box outliner
GUI.Box(new Rect(0F, NAME_Y_POS+NAME_Y_OFFSET -5F, NAME_WIDTH + FIELD_WIDTH +15F, NAME_Y_OFFSET*3F+5F), "");
GUI.Label (new Rect(NAME_X_POS, NAME_Y_POS + NAME_Y_OFFSET, NAME_WIDTH, NAME_HEIGHT), "Mob Name ", GUI.skin.GetStyle("Box"));
Name = EditorGUI.TextField(new Rect(FIELD_X_POS, FIELD_Y_POS + FIELD_Y_OFFSET, FIELD_WIDTH, FIELD_HEIGHT), Name, GUI.skin.GetStyle("TextField"));
if(Name != DEFAULT_NAME)
{
_pregenCheck[0] = true;
}
GUI.Label (new Rect(NAME_X_POS, NAME_Y_POS + (NAME_Y_OFFSET*2F), NAME_WIDTH, NAME_HEIGHT), "Hit Points ", GUI.skin.GetStyle("Box"));
HitPoints = EditorGUI.IntField (new Rect(FIELD_X_POS, FIELD_Y_POS + (FIELD_Y_OFFSET*2F), FIELD_WIDTH, FIELD_HEIGHT), HitPoints, GUI.skin.GetStyle("TextField"));
if(HitPoints > 1)
_pregenCheck[1] = true;
else
_pregenCheck[1] = false;
GUI.Label (new Rect(NAME_X_POS, NAME_Y_POS + (NAME_Y_OFFSET*3F), NAME_WIDTH, NAME_HEIGHT), "Mana Points ", GUI.skin.GetStyle("Box"));
Mana = EditorGUI.IntField (new Rect(FIELD_X_POS, FIELD_Y_POS + (FIELD_Y_OFFSET*3F), FIELD_WIDTH, FIELD_HEIGHT), Mana, GUI.skin.GetStyle("TextField"));
if(Mana <= -1)
_pregenCheck[2] = false;
else
_pregenCheck[2] = true;
// Area Box outline
GUI.Box(new Rect(0F, NAME_Y_POS+NAME_Y_OFFSET*5F -5F, NAME_WIDTH + FIELD_WIDTH +15F, NAME_Y_OFFSET*9F+5F), "");
// Header
GUI.Label(new Rect(NAME_X_POS, NAME_Y_POS + (NAME_Y_OFFSET*5F), NAME_WIDTH, NAME_HEIGHT), "MOB OBJECTS", GUI.skin.GetStyle("Box"));
GUI.Label(new Rect(NAME_X_POS, NAME_Y_POS + (NAME_Y_OFFSET*6F), NAME_WIDTH, NAME_HEIGHT), "Mob Model", GUI.skin.GetStyle("Box"));
// Object Selecter with Text Field backdrop
GUI.Label(new Rect(FIELD_X_POS, FIELD_Y_POS + (FIELD_Y_OFFSET*6F), FIELD_WIDTH, FIELD_HEIGHT), "", GUI.skin.GetStyle("TextField"));
MobPrefab = EditorGUI.ObjectField(new Rect(FIELD_X_POS+1F, FIELD_Y_POS+1F + FIELD_Y_OFFSET*6F, FIELD_WIDTH-1F, FIELD_HEIGHT-1F), MobPrefab, typeof(GameObject), true);
if(MobPrefab != null)
_pregenCheck[3] = true;
else
_pregenCheck[3] = false;
// Mount Points
GUI.Label(new Rect(NAME_X_POS, NAME_Y_POS + (NAME_Y_OFFSET*7F), NAME_WIDTH, NAME_HEIGHT), "Weapon Mount", GUI.skin.GetStyle("Box"));
if(!_generateMob)
{
MpWeaponMount = GUI.TextField(new Rect(FIELD_X_POS+1F, FIELD_Y_POS+1F + FIELD_Y_OFFSET*7F, FIELD_WIDTH-1F, FIELD_HEIGHT-1F), MpWeaponMount);
}
else
{
GUI.Label(new Rect(FIELD_X_POS, FIELD_Y_POS + (FIELD_Y_OFFSET*7F), FIELD_WIDTH, FIELD_HEIGHT), "", GUI.skin.GetStyle("TextField"));
MobWeaponMount = EditorGUI.ObjectField(new Rect(FIELD_X_POS+1F, FIELD_Y_POS+1F + FIELD_Y_OFFSET*7F, FIELD_WIDTH-1F, FIELD_HEIGHT-1F), MobWeaponMount, typeof(GameObject ), true);
}
GUI.Label(new Rect(NAME_X_POS, NAME_Y_POS + (NAME_Y_OFFSET*8F), NAME_WIDTH, NAME_HEIGHT), "Off Hand Mount", GUI.skin.GetStyle("Box"));
if(!_generateMob)
{
MpOffHandMount = GUI.TextField(new Rect(FIELD_X_POS+1F, FIELD_Y_POS+1F + FIELD_Y_OFFSET*8F, FIELD_WIDTH-1F, FIELD_HEIGHT-1F), MpOffHandMount);
}
else
{
GUI.Label(new Rect(FIELD_X_POS, FIELD_Y_POS + (FIELD_Y_OFFSET*8F), FIELD_WIDTH, FIELD_HEIGHT), "", GUI.skin.GetStyle("TextField"));
MobOffHandMount = EditorGUI.ObjectField(new Rect(FIELD_X_POS+1F, FIELD_Y_POS+1F + FIELD_Y_OFFSET*8F, FIELD_WIDTH-1F, FIELD_HEIGHT-1F), MobOffHandMount, typeof(GameObject), true);
}
GUI.Label(new Rect(NAME_X_POS, NAME_Y_POS + (NAME_Y_OFFSET*9F), NAME_WIDTH, NAME_HEIGHT), "Hair Mount", GUI.skin.GetStyle("Box"));
if(!_generateMob)
{
MpHairMount = GUI.TextField(new Rect(FIELD_X_POS+1F, FIELD_Y_POS+1F + FIELD_Y_OFFSET*9F, FIELD_WIDTH-1F, FIELD_HEIGHT-1F), MpHairMount);
}
else
{
GUI.Label(new Rect(FIELD_X_POS, FIELD_Y_POS + (FIELD_Y_OFFSET*9F), FIELD_WIDTH, FIELD_HEIGHT), "", GUI.skin.GetStyle("TextField"));
MobHairMount = EditorGUI.ObjectField(new Rect(FIELD_X_POS+1F, FIELD_Y_POS+1F + FIELD_Y_OFFSET*9F, FIELD_WIDTH-1F, FIELD_HEIGHT-1F), MobHairMount, typeof(GameObject), true);
}
GUI.Label(new Rect(NAME_X_POS, NAME_Y_POS + (NAME_Y_OFFSET*10F), NAME_WIDTH, NAME_HEIGHT), "Helmet Mount", GUI.skin.GetStyle("Box"));
if(!_generateMob)
{
MpHelmetMount = GUI.TextField(new Rect(FIELD_X_POS+1F, FIELD_Y_POS+1F + FIELD_Y_OFFSET*10F, FIELD_WIDTH-1F, FIELD_HEIGHT-1F), MpHelmetMount);
}
else
{
GUI.Label(new Rect(FIELD_X_POS, FIELD_Y_POS + (FIELD_Y_OFFSET*10F), FIELD_WIDTH, FIELD_HEIGHT), "", GUI.skin.GetStyle("TextField"));
MobHelmetMount = EditorGUI.ObjectField(new Rect(FIELD_X_POS+1F, FIELD_Y_POS+1F + FIELD_Y_OFFSET*10F, FIELD_WIDTH-1F, FIELD_HEIGHT-1F), MobHelmetMount, typeof(GameObject), true);
}
GUI.Label(new Rect(NAME_X_POS, NAME_Y_POS + (NAME_Y_OFFSET*11F), NAME_WIDTH, NAME_HEIGHT), "Char Mat Mesh", GUI.skin.GetStyle("Box"));
if(!_generateMob)
{
MpCMatMesh = GUI.TextField(new Rect(FIELD_X_POS+1F, FIELD_Y_POS+1F + FIELD_Y_OFFSET*11F, FIELD_WIDTH-1F, FIELD_HEIGHT-1F), MpCMatMesh);
}
else
{
GUI.Label(new Rect(FIELD_X_POS, FIELD_Y_POS + (FIELD_Y_OFFSET*11F), FIELD_WIDTH, FIELD_HEIGHT), "", GUI.skin.GetStyle("TextField"));
MobCharacterMaterialMesh = EditorGUI.ObjectField(new Rect(FIELD_X_POS+1F, FIELD_Y_POS+1F + FIELD_Y_OFFSET*11F, FIELD_WIDTH-1F, FIELD_HEIGHT-1F), MobCharacterMaterialMesh, typeof(GameObject), true);
}
GUI.Label(new Rect(NAME_X_POS, NAME_Y_POS + (NAME_Y_OFFSET*12F), NAME_WIDTH, NAME_HEIGHT), "3D Text Mount", GUI.skin.GetStyle("Box"));
if(!_generateMob)
{
MpTextName = GUI.TextField(new Rect(FIELD_X_POS+1F, FIELD_Y_POS+1F + FIELD_Y_OFFSET*12F, FIELD_WIDTH-1F, FIELD_HEIGHT-1F), MpTextName);
}
else
{
GUI.Label(new Rect(FIELD_X_POS, FIELD_Y_POS + (FIELD_Y_OFFSET*12F), FIELD_WIDTH, FIELD_HEIGHT), "", GUI.skin.GetStyle("TextField"));
MobTextName = EditorGUI.ObjectField(new Rect(FIELD_X_POS+1F, FIELD_Y_POS+1F + FIELD_Y_OFFSET*12F, FIELD_WIDTH-1F, FIELD_HEIGHT-1F), MobTextName, typeof(GameObject), true);
}
GUI.Label(new Rect(NAME_X_POS, NAME_Y_POS + (NAME_Y_OFFSET*13F), NAME_WIDTH, NAME_HEIGHT), "Mob Tag Name", GUI.skin.GetStyle("Box"));
if(!_generateMob)
{
MpTagName = GUI.TextField(new Rect(FIELD_X_POS+1F, FIELD_Y_POS+1F + FIELD_Y_OFFSET*13F, FIELD_WIDTH-1F, FIELD_HEIGHT-1F), MpTagName);
}
else
{
GUI.Label(new Rect(FIELD_X_POS, FIELD_Y_POS + (FIELD_Y_OFFSET*13F), FIELD_WIDTH, FIELD_HEIGHT), MpTagName , GUI.skin.GetStyle("TextField"));
}
GUI.Label(new Rect(NAME_X_POS, NAME_Y_POS + NAME_Y_OFFSET *15F, NAME_WIDTH, NAME_HEIGHT), "Save Folder", GUI.skin.GetStyle("Box"));
SaveFolder = GUI.TextField(new Rect(FIELD_X_POS, FIELD_Y_POS + FIELD_Y_OFFSET*15F, FIELD_WIDTH, FIELD_HEIGHT), SaveFolder);
_generateMob = GUI.Button(new Rect(NAME_X_POS, NAME_Y_POS + NAME_Y_OFFSET *16F , NAME_WIDTH+30F, NAME_HEIGHT), "GENERATE MOB");
_reset = GUI.Button(new Rect(FIELD_X_POS+30F, FIELD_Y_POS+FIELD_Y_OFFSET*16F, FIELD_WIDTH-30F, FIELD_HEIGHT),"RESET");
_defaults = GUI.Button(new Rect(FIELD_X_POS+30F, FIELD_Y_POS+FIELD_Y_OFFSET*17F, FIELD_WIDTH-30F, FIELD_HEIGHT),"DEFAULTS");
if(_warnMSG == true)
GUI.Label(new Rect(5F, NAME_Y_POS + NAME_Y_OFFSET * 18F, 240F, 20F), "Please Assign: " + _errorCheckName);
var createdChar = GameObject.Find(_name);
if(createdChar != null)
SearchModelMountPoints();
}
void GenerateMob()
{
int cnt = 0;
// Check slots before creating
for(int i = 0; i < _pregenCheck.Length; i++)
{
if(_pregenCheck[i] == false)
{
_errorCheckName = _checkName[i];
_generateMob = false;
_warnMSG = true;
break;
}
else
{
cnt++;
if(cnt == _pregenCheck.Length)
{
_errorCheckName = "";
_warnMSG = false;
CreateMobObject();
}
}
}
}
void CreateMobObject()
{
createdChar = null;
if(MobPrefab == null)
{
_generateMob = false;
_errorCheckName = "Mob Model";
return;
}
else
createdChar = GameObject.Instantiate(MobPrefab) as GameObject;
if(createdChar != null)
{
createdChar.name = _name;
// Check to see if we need to add a MeshRenderer component to the mob
if(createdChar.GetComponent<MeshRenderer>() == null)
if(createdChar.transform.GetChildCount() >=1)
if(createdChar.GetComponentInChildren<MeshRenderer>() == null)
createdChar.AddComponent("MeshRenderer");
// Check to see if we need to add a MeshFilter component to the mob
if(createdChar.GetComponent<MeshFilter>() == null)
if(createdChar.transform.GetChildCount() >=1)
if(createdChar.GetComponentInChildren<MeshFilter>() == null)
createdChar.AddComponent("MeshFilter");
// Check to see if we need to add an Animation component to the mob
if(createdChar.GetComponent<Animation>() == null)
if(createdChar.transform.GetChildCount() >=1)
if(createdChar.GetComponentInChildren<Animation>() == null)
createdChar.AddComponent("Animation");
// Add H&S Scripts
createdChar.AddComponent("CharacterController");
createdChar.AddComponent("AdvancedMovement");
createdChar.AddComponent("AI");
createdChar.AddComponent("Mob");
// Set mob tag
createdChar.tag = MpTagName;
// Set mob hit points
createdChar.GetComponent<Mob>().maxHealth = HitPoints;
createdChar.GetComponent<Mob>().curHealth = HitPoints;
// This at end of function to avoid multiple copies
_generateMob = false;
}
}
void SearchModelMountPoints()
{
if(createdChar != null)
{
if(createdChar.transform.GetChildCount() >=1)
{
var wm = GameObject.Find(_mpWeaponMount);
if(wm !=null)
{
MobWeaponMount = wm;
createdChar.GetComponent<Mob>().weaponMount = MobWeaponMount as GameObject;
}
else
Debug.Log("Unable to find Weapon Mount");
var oh = GameObject.Find(_mpOffHandMount);
if(oh !=null)
{
MobOffHandMount = oh;
createdChar.GetComponent<Mob>().offHandMount = MobOffHandMount as GameObject;
}
else
Debug.Log("Unable to find OffHand Mount");
var hm = GameObject.Find(_mpHairMount);
if(hm !=null)
{
MobHairMount = hm;
createdChar.GetComponent<Mob>().hairMount = MobHairMount as GameObject;
}
else
Debug.Log("Unable to find Hair Mount");
var helm = GameObject.Find(_mpHelmetMount);
if(helm !=null)
{
MobHelmetMount = helm;
createdChar.GetComponent<Mob>().helmetMount = MobHelmetMount as GameObject;
}
else
Debug.Log("Unable to find Helmet Mount");
var cmm = GameObject.Find(_mpCMatMesh);
if(cmm !=null)
{
MobCharacterMaterialMesh = cmm;
createdChar.GetComponent<Mob>().characterMaterialMesh = MobCharacterMaterialMesh as GameObject;
}
else
Debug.Log("Unable to find Character Material Mesh Mount");
var nm = GameObject.Find(_mpNameText);
if(nm !=null)
{
MobTextName = nm;
nm.GetComponent<TextMesh>().text = Name;
}
else
Debug.Log("Unable to find Name 3DText");
}
CreatePrefabFromMob();
}
}
void CreatePrefabFromMob()
{
// Save a prefab of our newly configured mob in the assigned folder
string localPath = "Assets/";
if(SaveFolder != "")
localPath = "Assets/" + SaveFolder + "/" + createdChar.name + ".prefab";
else
localPath = "Assets/" + createdChar.name + ".prefab";
PrefabUtility.CreatePrefab(localPath, createdChar);
AssetDatabase.Refresh();
DestroyImmediate(createdChar);
Name = DEFAULT_NAME;
HitPoints = 0;
Mana = 0;
createdChar = null;
MobPrefab = null;
EditorApplication.RepaintProjectWindow();
}
}