Need help with Editor script

Hi,

I wrote this scripts only as example for my question.
This script named PlaySound

var sound : AudioClip[];
var someAnimation : String[];  

function noMatter()
{
	audio.clip = sound[Random.Range(0, sound.length)];
	audio.Play();
	
	animation.CrossFadeQueued(someAnimation[Random.Range(0, someAnimation.Length)], 0.15, QueueMode.PlayNow);
}

And now i want to add “sound” and “someAnimation” (from PlaySound script) to my editor script.
This script is placed inside folder Editor

@CustomEditor(PlaySound)
class ExampleScriptEditor extends Editor {

function OnInspectorGUI ()
{
    editorGUIUtility.LookLikeInspector();
  
    target.someAnimation =                     and i'm stuck here.  
    target.sound =                                   
}

}

I wrote some editor scripts before, but with that i need help.

Thanks.

I’ve never written Editors in js before…

I was about to answer too with too much haste! Didn’t see that you were looking to use Arrays. I have an example of mine. But I used a list… Since it doesn’t require you to set the array size…

In my class that I was editing I had this

Part of the Edited Class looks like. 
        [SerializeField]
	pubic List<bool> foldout = new List<bool>();
	
	[SerializeField]
	public List<QuestDialog> DialogList = new List<QuestDialog>();				//Dialog

Where QuestDialog is nothing more then a custom data type I made, Which holds a 3 different strings.

The Editor
                   //Add Dialog and User Options to Quest
		    self.Counter = EditorGUILayout.IntSlider(self.Counter, 0, 10);	//Slider Counter
			
			if(self.Counter > self.foldout.Count)				//If the counter is greater then foldout count 
			{
				var temp = (self.Counter - self.foldout.Count);
				for(int j = 0; j < temp ; j++)
						self.foldout.Add(true);						
			}
			
			if(self.Counter > self.DialogList.Count)				//If the Slider is higher add more elements.	
			{
				
				var temp = self.Counter - self.DialogList.Count;
				for(int j = 0; j < temp ; j++)
				{
					self.DialogList.Add(new QuestDialog() );
				}
				
			}
			if(self.DialogList.Count > self.Counter)
			{
				self.DialogList.RemoveRange( (self.Counter), self.DialogList.Count - (self.Counter));	// If the list is longer then the set size
				self.foldout.RemoveRange( (self.Counter), self.foldout.Count-(self.Counter));
			}
			
			for(int i = 0; i < self.Counter; i++)
			{					
				if(self.foldout[i] = EditorGUILayout.Foldout(self.foldout[i],"Dialog "+ i ) )
				{
					EditorGUILayout.LabelField("Dialog", ":smile:ialog By NPC");
			        self.DialogList[i].Dialog = EditorGUILayout.TextArea(self.DialogList[i].Dialog, GUILayout.Width(300) );
					
					EditorGUILayout.LabelField("Accept",":User Accepting to NPC Dialog", GUILayout.Width(300) );
					self.DialogList[i].InputAccept = EditorGUILayout.TextArea(self.DialogList[i].InputAccept, GUILayout.Width(300));
					
					EditorGUILayout.LabelField("Decline:",":User Declining to NPC Dialog", GUILayout.Width(300) );
			        self.DialogList[i].InputDecline = EditorGUILayout.TextArea(self.DialogList[i].InputDecline,GUILayout.Width(300));
						
					GUILayout.Space(10.0f);
				}
			}

Edit Heres a picture : 660421--23613--$QuestDialogEditor.png
I made a List of bools so I each added quest dialog could be independantly foldedout or in. I wrote this quite some time ago. But it did the trick. Probably go back to it eventually and fix it up… Anyways I hope this helped you out in someway.

Thanks for your answer Eiznek :slight_smile:
Sorry, but i can’t find solution looking on your script :confused:
Maybe someone could give me answer based on my example?

If you ignore the foldout menus

Still has to be in C# because I don’t know how js uses lists and such if its different and I don’t really want to go and google it.

 self.Counter = EditorGUILayout.IntSlider(self.Counter, 0, 10); // Must use some way of inputing a number for the array size or list size. 
if(self.Counter > self.DialogList.Count)				//If the Slider is higher add more elements.	
{			
        var temp = self.Counter - self.DialogList.Count;   //Forgot that I used a counter to keep track of the slider, Since all 
                                                                               //Information stored from Editors isn't kept.
	for(int j = 0; j < temp ; j++)                                //For a list we add as many elements we need
	{
		self.DialogList.Add(new QuestDialog() );
	}

	//If you wanted to use arrays
       target.someAnimation = new String[target.Counter]; //C# also when I use self.. its merly the target script being referenced.
       target.sound = new AudioClip[target.Counter]; //C#		
//Now the problem with arrays is when you change the size you lose all data.. Lists you can keep update your min slider point.. If you use my above method to only remove the range that your missing. 
}

//After you figure out what you want to do there simply loop through your new created objects.. to there count value.
for(int i = 0; i < self.Counter; i++)
{
      EditorGUILayout.BeginHorizontal();
      EditorGUILayout.PrefixLabel("Animation String");
      target.someAnimation[i] = EditorGUILayout.TextField(target.someAnimation[i] );
      EditorGUILayout.EndHorizontal();
    
    //same thing for your AudioClips
      EditorGUILayout.BeginHorizontal();
      EditorGUILayout.PrefixLabel("Animation String");
      target.sound[i] = (AudioClip) EditorGUILayout.ObjectField(target.sound[i], typeof(AudioClip), true );
      EditorGUILayout.EndHorizontal();
}

I typed this all in this window so it may look hidious… If you can’t figure it out based on this then I can’t help you ;P…

I hope you can understand this however.

To respond to your initial question… None of this is “Editor” material. This is all GameObject stuff. And your stuck on it because you are not referencing the first class correctly:

class PlaySound{
	public var sound : AudioClip[];
	public var someAnimation : String[];  
	
	public function Play(obj : GameObject)
	{
		if(obj.audio){
			obj.audio.clip = sound[Random.Range(0, sound.length)];
			obj.audio.Play();
		}
		
		if(obj.animation)
			obj.animation.CrossFadeQueued(someAnimation[Random.Range(0, someAnimation.Length)], 0.15, QueueMode.PlayNow);
	}
}


var playSound : PlaySound;

function Start(){
	print(playSound.sound.Length);
}

and this must be editor script for PlaySound script?
you are confusing me more and more… I need only find the way how to add arrays(like variable var sound : AudioClip[ ];) to my editor script. I can’t find the right way how to do that.

No, none of this has to be an Editor script. Add the code I gave you to an object. In the inspector for that object, click the arrow beside Play Sound. This will open up two arrays. Set the length of the array, drag sounds to the sound, fill the strings with animation names and let her rip.

An editor script should only be created when you are trying to fulfill these obligations without directly dragging them. So in script, you would fulfill the string array like this:

someAnimation = [“this”, “is”, “a”, “test”];

clips would be a bit different as you would have to have them in the system and generate a list.

Can I ask a dumb question: Is all you want to do is specify the list of sounds and animations to be randomly picked from?

Sounds and animations are just for example of my question.
all i want is to add arrays [ ] to my editor script , but i don’t know how. Everything else i know how to add.

if you read my reply you’d know exactly how to add arrays with the editor.

yeah i tried, but for some reason i can’t get it to work :confused: Tomorrow i will try again.

Howdy,

The easiest way I’ve found so far to deal with situations like this is to just use DrawDefaultInspector() in your editor script(which does what the name implies) to get the array editor functionality, and then just draw your own inspector after that. It is possible to duplicate the built in editor functionality on your own, but it’s quite a bit simpler to just let the default code do it.

I wrote a quick class and editor. Again I don’t understand JS enough to write stuff well enough in there so I did it in c# but I’m including the files I wrote in a handy zip file…

You can load it into your project and see that it works the same as the picture.
661673–23676–$__eTest.zip (1.16 KB)

im getting two errors:
Assets/Editor/HolderClassEditor.cs(51,61): error CS1502: The best overloaded method match for UnityEditor.EditorGUILayout.ObjectField(string, UnityEngine.Object, System.Type, params UnityEngine.GUILayoutOption[ ])' has some invalid arguments Assets/Editor/HolderClassEditor.cs(51,61): error CS1503: Argument #4’ cannot convert bool' expression to type UnityEngine.GUILayoutOption[ ]’

This error looks its because of this area:

  self.sounds[i] = (AudioClip)EditorGUILayout.ObjectField("Clip_" + i + ":" , self.sounds[i], typeof(AudioClip), true );

This code should be formatted as such–

(OurSoundatArrayLocation_i) = (casting)EditorGUILayout.ObjectField((String), (OurSoundatArrayLocation_i)(ObjectType), true

The true added at the end is so Unity will stop complaining and giving some warning. The code in the Zip folder works. That’s exactly how I took the SS of that. What Version of Unity are you running? I think that his true at the end is new.

i updated unity engine to current version and errors disappear. Only one problem, i know about C# as much as you about UnityScript(JS). :smile:

in “JS” it must look something like that:
PlaySoundEditor.js

@CustomEditor(PlaySound)
class PlaySoundEditor extends Editor {

override function OnInspectorGUI ()
	{
	    var self =  ??????         // need help here.
		
		self.soundCount = EditorGUILayout.IntSlider(self.soundCount, 0, 10);
		if(self.soundCount > self.sounds.Count)	
		{
			var temp = self.soundCount - self.sounds.Count;
			for(var j : int = 0; j < temp ; j++)
				self.sounds.Add(new AudioClip());
			
		}
		if(self.sounds.Count > self.soundCount)
		{	//Our list is longer then our Counter.. Remove the extra's
			self.sounds.RemoveRange( (self.soundCount), self.sounds.Count - (self.soundCount));	
		}

		//Display our last list.
		for(var i : int = 0; i < self.soundCount; i++)
		{					
	        self.sounds[i] = EditorGUILayout.ObjectField("Clip_" + i + ":" , self.sounds[i], AudioClip, true );
			GUILayout.Space(10.0);
		}

	}
}

and PlaySound.js

class PlaySound extends MonoBehaviour { 
var soundCount : int;
var sounds : AudioClip[];
}

I’m using Lists to Store the data for sound and strings. Your using array. I don’t think its going to work the same for you…
I’m positive js has lists… But I don’t know how to write them.

The “self” that I reference is the same as your “target”.

So instead of putting self put target in instead.

visually all works fine and i don’t get any errors, but for some reasons i can’t add sounds :face_with_spiral_eyes:

@CustomEditor(HolderClass)
class HolderClassEditor extends Editor{

override function OnInspectorGUI (){
		var sk : HolderClass = target as HolderClass;
		
		EditorGUILayout.BeginVertical ();
		sk.size = EditorGUILayout.IntField("Size", sk.size);
                sk.sounds = new AudioClip[sk.size];

		for( var i : int = 0; i < sk.sounds.length; i++){					
	        sk.sounds[i] = EditorGUILayout.ObjectField("Clip_" + i + ":" , sk.sounds[i], AudioClip, true) as AudioClip;
		GUILayout.Space(10);

			}
		
	    EditorGUILayout.EndVertical ();
	}
}
class HolderClass extends MonoBehaviour {

     var size : int = 0;
     var sounds : AudioClip[];
}

You’re recreating the sk.sounds array every OnInspectorGUI update, which is wiping out any previously saved object references.