I’ve been searching around online for the past 5 hours for ways to do this and I keep coming up with results that are seem like they are similar to what I want to do, but just haven’t helped me in getting this working. I have a feeling I’m either trying to bite off WAY more then I should at the moment since I’m still trying to learn all the ins and outs of C# or trying to do something that personal edition of Unity just doesn’t support/do. Here’s the full rundown:
I have a few different prefab gameobject item templates in the resources folder of my project that get’s loaded dynamically. Both require some custom information that is in their scripts for how they act in the game, but they also have some shared properties. These properties I have in a class called “Item” in separate class-holding script. I’ve got another script in the Editor folder that should properly extend the editor and create a property drawer for this class. For the inventory system I’m working on, the “Item” class is used to provide a way to give each item it’s own int numerical ID & high-level item type through an enum.
The main problem I am running into is there is no errors, yet the Item class, which should added to each prefab object, which has in it’s script “[RequireComponent(typeof(Item))]”, doesn’t seem to appear in the inspector.
I’ve included the Item script below as well as it’s property drawer. Any help will be much appreciated. Also, as a side-note, I know the inspector side doesn’t have anything for quantity. That doesn’t need to be touched on the item prefabs. The item Type and the Item ID are the main two I want to set through this. The quantity is just there for after it’s already in the inventory for another section of script.
Item
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
[System.Serializable]
public class Item : MonoBehaviour,IComparable<Item> {//is used
public int itemID;
public int quantity;
public ItemType itemType;
public Item(int id, int qty, ItemType type){
itemID = id;
quantity = qty;
itemType = type;
}
public int CompareTo(Item other){
if(other == null){
return 1;
}
return quantity-other.quantity;
}
}
Item Property Drawer
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
[CustomPropertyDrawer(typeof(Item))]
public class Editor_Item : PropertyDrawer {
Item _target;
void OnEnable(){
/*_target = (Item)target;
if (_target == null){
Debug.LogError ("There is no Item Attached to " + _target.gameObject.name);
}*/
}
public override void OnGUI(Rect pos, SerializedProperty property, GUIContent label){
GUILayout.BeginVertical();
GUILayout.Label("Item Script",EditorStyles.boldLabel);
_target.itemID = EditorGUILayout.IntField ("Item Identification Number",_target.itemID);
_target.itemType = (ItemType)EditorGUILayout.EnumPopup ("Item Type",_target.itemType);
GUILayout.EndVertical();
if(GUI.changed){
EditorUtility.SetDirty (_target);
}
}
}
If I understand correctly, you want that your Item script being auto added to existing prefabs that have RequireComponent dependency on Item. However, RequireComponent only works for newly created prefabs, i.e. for prefabs that was created after putting RequireComponent in a script.
If you want to modify existing prefabs, you can write an Editor script that will scan for prefabs and add missing components to them. This script can be triggered via Editor menu extension or with InitializeOnLoad attribute. However, if you have just a few invalid prefabs, it will be faster to just add the Item script manually.
I still don’t know if this does work or how to go about it, but I’ve given up on it for the moment to use an alternate system. I’ve scrapped the propertydrawer altogether at the moment. Need to learn how to make Unity Custom Inspector GUIs at some point…
For now however, this question is semi-closed, however, I’d still like to know if this is possible/doable and if anyone knows of any methods to implement it properly.
Either way, to share & share alike, I’ll be posting the code that I’ve moved to just in case it helps someone else. The code isn’t in it’s “final” state, as I’m still adding items to the enum ItemTypes and for each new type there should be a new foreach loop and static list of each new itemtype, but it should be fairly easy for someone to take an expand from here. Also, the gameplaydatamanager might be a tad over-engineered, but wanted to make sure I don’t accidentally write to the item-type lists, so I made them read-only.
Item Class
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
using System.Linq;
public class Item : IComparable<Item> {
public int itemID;
public int quantity;
public ItemType itemType;
public UnityEngine.GameObject itemObject;
public Item(int id, int qty, ItemType type){
itemID = id;
quantity = qty;
itemType = type;
if (type==ItemType.Rune){
Item temp = GameplayDataManager.masterRuneList.First (item => item.itemID == id);
itemObject = temp.itemObject;
}else if (type == ItemType.Waystone){
Item temp = GameplayDataManager.masterWaystoneList.First (item => item.itemID == id);
itemObject = temp.itemObject;
}else{
}
}
public Item(int id, ItemType type, UnityEngine.GameObject obj){
itemID = id;
itemType = type;
itemObject = obj;
}
public int CompareTo(Item other){
if(other == null){
return 1;
}
return quantity-other.quantity;
}
}
GameplayDataManager
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class GameplayDataManager : MonoBehaviour {
private static List<Item> _masterRuneList = new List<Item>();
private static List<Item> _masterWaystoneList = new List<Item>();
public static List<Item> masterRuneList{
get{
return _masterRuneList;
}
}
public static List<Item> masterWaystoneList{
get{
return _masterWaystoneList;
}
}
public static void UpdateLists(){
GameObject[] runeList = Resources.LoadAll<GameObject>("Runes");
GameObject[] waystoneList = Resources.LoadAll<GameObject>("Waystones");
print(runeList.Length);
print (waystoneList.Length);
foreach(GameObject entry in runeList){
print ("adding to RuneList " + entry.name);
_masterRuneList.Add(new Item(entry.GetComponent<Rune>().itemId, entry.GetComponent<Rune>().itemType,entry));
print ("MasterRuneList has " + masterRuneList.Count + " entries");
}
foreach(GameObject entry in waystoneList){
print ("adding to WaystoneList " + entry.name);
_masterWaystoneList.Add(new Item(entry.GetComponent<Waystone>().itemId, entry.GetComponent<Waystone>().itemType,entry));
}
}
}