- Home /
Why can't I access the Name field in the Custom Styles section of a GUISkin in the Inspector?
In working out an answer to my last question regarding creating an array of unique GUIStyles from a single GUIStyle I came up with the following code excerpt:
public class sharkTrackRender : MonoBehaviour {
public GUISkin buttonGUISkin;
bool firstpass = true;
void OnGUI () {
if (firstpass) {
for (int i=0; i<pttcnt; i++) {
btnGUIArray[i] = new GUIStyle(buttonGUISkin.GetStyle(""));
}
firstpass = false;
}
}
}
This basically does what I want. By setting up a GUISkin from the Project tab Create menu and dropping it in the public GUISkin variable slot in the script's Inspector I can set up a GUIStyle in the Custom Styles array section of the GUISkin Inspector and use that GUISkin/GUIStyle combination to set up dynamically sized arrays of unique GUIStyles. The problem is in the Inspector I cannot access the Name field of the Custom Styles array elements. The array elements have no default name, and there seems to be no way to give them a name. Clicking on the Name field does not open a text entry box. I found that using the empty string "" in the GetStyle call will access the first element in the Custom Styles array, so, for the moment I can continue coding, but, there appears to be no way to add and use another uniquely named style in the GUISkin Custom Styles array; which at some point I will probably need to do. Adding multiple GUISkins is not an option any more than would be adding multiple GUIStyles, (see my last question). Any ideas on what I'm missing would be greatly appreciated.
BTW...I'd still be happy hear from anyone on my sequential quaternion question...;^)
Answer by nicloay · Oct 22, 2013 at 08:21 AM
The problem is that you create your own instance of GUIStyle and it dosn't linked to any skins, Have a look at this code which should solve your problem.
using UnityEngine;
using System.Collections;
using System;
public class CustomStyles : MonoBehaviour {
public GUISkin skin;
void Start(){ // this method just for test, don't use it here, all operations with skins should be in OnGUI method
GUIStyle buttonStyle = skin.FindStyle("button");
buttonStyle.border = new RectOffset(20,20,20,20);//BE CAREFULL this is linked to your style and all changes is permanent
GUIStyle customButton = new GUIStyle(buttonStyle); // now we have new instance;/
GUIStyle[] customStyles=skin.customStyles;
Array.Resize<GUIStyle>(ref customStyles,skin.customStyles.Length+1); // add one more element to the array
skin.customStyles[skin.customStyles.Length-1]=customButton; // see comment from Bunny83. to rebuild cache, we have to prepare array at first and then assign it back to skin
skin.customStyles = customStyles; // assign array to the skin
}
}
This sort of works. It appears to add an element since the element count changes to 2 in the inspector, but, the added element does not show up in the inspector so other than completely scripting, it isn't available.
You should swap and change those two lines:
skin.customStyles = customStyles;
skin.customStyles[skin.customStyles.Length-1] = customButton;
to
customStyles[customStyles.Length-1] = customButton;
skin.customStyles = customStyles;
And just for those it's not obvious, you have to do this in OnGUI and not in Start. Just like the OP did.
ps: keep in $$anonymous$$d that any changes made to the GUISkin while testing in the editor will permanently change the GUISkin asset. In a built game those changes would not be saved between starts.
I agree with you about Start. I made that just to test. Changes in skin in play mode is permanent. The same as for example if you change texture2d or mesh. In play mode And it doesn't matter when you add element to array.
Yes, you're right. Actually i was pretty sure that skin.customStyles returns a temp-array like most other Unity stuff does (ParticleEmitter.particles / $$anonymous$$esh.vertices / $$anonymous$$esh.triangles / Renderer.materials / ...) but it seems to directly reference the array.
However when you do it this way it can't find the style because the internal function BuildStyleCache is only executed when you assign the array back to the customStyles property. Since the new style doesn't have a name yet (or at least not the proper name) FindStyle won't find that style.
Answer by Bunny83 · Oct 26, 2013 at 09:55 AM
I would recommend an extension method like this to create the procedural styles:
public static GUIStyle GetStyleOrCreate(this GUISkin aSkin, string aStyleName, GUIStyle aSource)
{
var S = aSkin.FindStyle(aStyleName);
if (S == null)
{
S = new GUIStyle(aSource);
S.name = aStyleName;
GUIStyle[] customStyles = aSkin.customStyles;
Array.Resize<GUIStyle>(ref customStyles, customStyles.Length+1);
customStyles[customStyles.Length-1] = S;
aSkin.customStyles = customStyles;
}
return S;
}
With this you can simply do this:
void OnGUI()
{
if (first)
{
GUI.skin = skin;
var S = skin.GetStyleOrCreate("MyNewStyle", "Button");
S.border = ...
If you'll add a lot of new styles you should use a List instead and just convert the final List to an array and assign it to skin.customStyles as last step.
This sounds promising, but, whether I try and set up the extension method as a separate file, or as a class within the main code, I get "The name "GetStyleOrCreate" does not exist in the current context." So, there is something not clear to me about making the extension class recognizable by the main code.
Extension methods have to be declared in a static class. The name of the class doesn't matter. The method of course need to be public and static as well as the class that contains it.