- Home /
A list of all NPCs in Editorwindow - not working and I'm not sure why
Hi guys. I'm working on creating a gui for myself in the unity editor which will allow me to change properties of multiple NPCs from one place. The first part of this is to make a box, and populate it with a list of all the NPCs names as buttons. it seeks them out by tag and displays them by name.
Using what I've learnt so far, and what I have found online, I have created this script
var scrollPosition : Vector2 = Vector2.zero;
var allNpcs;
var NpcsList = [];
class Conversations extends EditorWindow
{
@MenuItem ("Database Editor/Conversations")
static function ShowConversationsWindow ()
{
// EditorWindow.GetWindow (Conversations);
var window : Conversations =
EditorWindow.GetWindowWithRect(Conversations, Rect(0,0,600,200));
}
function OnGUI ()
{
// The actual window code goes here
GUILayout.BeginArea(Rect(10,10,100,200));
scrollPosition = GUI.BeginScrollView (Rect (10,300,100,100), scrollPosition, Rect (0, 0, 220, 200));
if (GUILayout.Button("Refresh Object List"))
{
UpdateTags();
Debug.Log("Clicked");
for (i = 0; i < NpcsList.length; i++)
{
}
}
GUI.EndScrollView ();
GUILayout.EndArea();
}
}
function UpdateTags()
{
Npcslist = [];
var allNpcs = GameObject.FindGameObjectsWithTag ("NPC");
for (var NPC in allNpcs)
{
NpcsList.push(NPC.name);
GUILayout.Button(NPC.name);
}
Debug.Log(allNpcs);
}
The problem is, when I load it into unity, I get a box with no buttons or anything on it. If anyone has any experience in this matter I would greatly appreciate your advice.
Answer by Bunny83 · Aug 02, 2012 at 05:14 PM
Ok some general notes:
A script which contains an EditorWindow is an editor class, so the script have to be placed in an "editor" folder (usually "Assets/editor/").
Your UpdateTags function should be inside your class (in your messy comment i can see you've done this already ;))
When you write if (GUILayout.Button("Refresh Object List")), the code in the if block is only executed once when ever the button is pressed.
You're mixing GUI and GUILayout stuff. That won't really work. GUILayout works a lot different. I almost always use GUILayout, but that's up to you.
Unity's GUI system is an immediate-mode system. That means when you call GUI.Button (or GUILayout.Button) the button is drawn at this moment. So you have to call the functions every frame. If you call it only for one frame, it's only visible for one frame.
Here's how it might should look like since i still have no idea what you actually want to show:
// Conversations.js
#pragma strict
import System.Collections.Generic;
class Conversations extends EditorWindow
{
var scrollPosition : Vector2 = Vector2.zero;
var NpcsList = new List.<GameObject>();
@MenuItem ("Database Editor/Conversations")
static function ShowConversationsWindow ()
{
EditorWindow.GetWindowWithRect(Conversations, Rect(0,0,600,200));
}
function OnGUI ()
{
if (GUILayout.Button("Refresh Object List"))
{
UpdateTags();
}
scrollPosition = GUILayout.BeginScrollView (scrollPosition);
for (var i = 0; i < NpcsList.Count; i++)
{
if (GUILayout.Button(NpcsList[i].name))
{
Debug.Log("GO:" + NpcsList[i].name + " has been clicked");
}
}
GUILayout.EndScrollView ();
}
function UpdateTags()
{
NpcsList = new List.<GameObject>(GameObject.FindGameObjectsWithTag ("NPC"));
}
}
This editor window is tested and works. Some additional things:
Don't use GetWindowWithRect unless you really want to restrict the window to that size. GetWindowWithRect will remove the window border and you can't resize the window. In most cases just use GetWindow.
If you want to use GUILayout you should make yourself familiar with all GUILayout functions. The most useful / powerful are horizontal and vertical groups.
When you create editor gui stuff, don't forget the extensions in EditorGUILayout or EditorGUI if you don't want to use auto-layouting.
Bunny, I can't thank you enough. not only have you solved my problem but you've also taught me a wealth of information about unity coding and set me in a good direction. Thanks for your answer!
Is a list functionally the same as an array? for instance, can I retrieve and store a value from it in a similar way? when is it better to use one or the other?
Generally you have to distinguish between 3 things:
native array
javaScript Array class
generic container classes like List
$$anonymous$$ost things are already explained in the docs, but here are the most important things:
native array
+ it's fast
+ it's type-safe
+ smallest memory footprint
- can't be resized
Array class
+ flexible (you can add / remove / change elements)
- slow since it contains System.Objects which have to be casted
- slightly larger memory usage
-/+ not type-safe
Generic List
+ flexible (you can add / remove / change elements)
+ type-safe
+ uses internally a native array
+ almost as fast as a native array
- slightly larger memory usage
// UnityScript
// native array of float
var myArray : float[];
// Array class
var myArray : Array;
// generic List
var myArray : List.<float>;
So in most cases you can easily use a List ins$$anonymous$$d of an array, however if you don't need to change the array dynamically you can just use a native array.
The Array class should be avoided. Not just because it's slow, but also not type-safe. In some rare cases you might want to store different types in the same array, in such a case you can use the Array class but that's an unusual approach. An array or vector is defined as a collection of multiple similar items, usually of the same type.
Don't forget arrays are reference types / classes so they need to be created before you can use them. If you have a public variable in a $$anonymous$$onoBehaviour script, the array is automatically created by the Unity inspector / serialization process.
That's how you would create those arrays:
// UnityScript
// native array of float with 5 elements
var myArray : float[] = new float[5];
// Array class
var myArray : Array = new Array();
// generic List
var myArray : List.<float> = new List.<float>();
Thanks to type inference you can omit the type when you assign a value to the variable when you create the variable:
// UnityScript
// native array of float with 5 elements
var myArray = new float[5];
// Array class
var myArray = new Array();
// generic List
var myArray = new List.<float>();
Thanks dude, newbies like me really appreciate the effort that goes into long answers like this
Answer by cupsster · Aug 02, 2012 at 08:56 AM
I think you need to place your variables in Conversations class.
like so?
class Conversations extends EditorWindow {
var scrollPosition : Vector2 = Vector2.zero;
var allNpcs; var NpcsList = [];
I've included the UpdateTags function to the class as well. Sorry if the whole conversations part is a bit confusing, basically, it's called conversations under the database editor menu, as it will be a collection of dialogues that will occur when the player talks to each npc.
I'm at work at the moment (on lunch) but I'll try it out as soon as I get home and then post my results. thank you for the help
That's another thing why i don't like UnityScript for beginners. If you know that every script is going to be a class that's not a problem, but most beginners aren't familiar with classes / scopes. UnityScript hides the actual class construct so they never learn real oop.
for (var NPC in allNpcs) should be: foreach (var npcVar:NPC in allNpcs)
Your answer
Follow this Question
Related Questions
Can not close editor window not in GUILayout.somemethod in OnGUI method 0 Answers
How to trigger button press on a button in an editor window by pressing the return key ? 0 Answers
Using Handles in EditorWindow 0 Answers
EditorWindow: Scrollview 1 Answer
Elements of a 2D array are always null 0 Answers