Is there a way to draw faster the gameobjects in editorwindow? - c#

using UnityEngine;
using System.Collections;
using UnityEditor;
using UnityEngine.SceneManagement;
using System;
using System.Collections.Generic;
public class EditorGUIHierarchyViewExampleWindow : EditorWindow
{
EditorGUIHierarchyView hierarchyView = new EditorGUIHierarchyView();
[MenuItem("Window/EditorGUIHierarchy - Show Scene View")]
static void Init()
{
EditorGUIHierarchyViewExampleWindow window = (EditorGUIHierarchyViewExampleWindow)GetWindow(typeof(EditorGUIHierarchyViewExampleWindow));
window.Show();
}
struct SceneGameObjectComparer : IComparer<GameObject>
{
public int Compare(GameObject go1, GameObject go2)
{
return go1.transform.GetSiblingIndex().CompareTo(go2.transform.GetSiblingIndex());
}
}
void OnEnable()
{
this.titleContent = new GUIContent("Scene View");
}
public void OnGUI()
{
var gameObjects = SceneManager.GetActiveScene().GetRootGameObjects();
Array.Sort(gameObjects, new SceneGameObjectComparer());
hierarchyView.BeginHierarchyView();
foreach (GameObject gameObject in gameObjects)
{
gameObject.transform.GetSiblingIndex();
DrawGameObject(gameObject);
}
hierarchyView.EndHierarchyView();
Repaint();
}
void DrawGameObject(GameObject go)
{
if (go.transform.childCount > 0)
{
if (go.activeInHierarchy)
{
hierarchyView.BeginNode(go.name);
}
else
{
hierarchyView.BeginNode(go.name, Color.gray, Color.gray);
}
foreach (Transform child in go.transform)
{
DrawGameObject(child.gameObject);
}
hierarchyView.EndNode();
}
else
{
if (go.activeInHierarchy)
{
hierarchyView.Node(go.name);
}
else
{
hierarchyView.Node(go.name, Color.gray, Color.gray);
}
}
}
}
This is the EditorGUIHierarchyView class:
using UnityEngine;
using System.Collections;
using UnityEditor;
using System.Collections.Generic;
using System.Text;
public class EditorGUIHierarchyView
{
List<string> OpenIds = new List<string>();
List<string> SelectedIds = new List<string>();
GUIStyle foldoutChildessStyle;
GUIStyle selectedAreaStyle;
GUIStyle selectedLabel;
GUIStyle selectedFoldout;
GUIStyle normalFoldout;
Color defaultSelectedTextColorDarkSkin = Color.white;
Color defaultUnselectedTextColorDarkSkin = new Color(0.705f, 0.705f, 0.705f);
Color defaultSelectedTextColorWhiteSkin = Color.white;
Color defaultUnselectedTextColorWhiteSkin = Color.black;
Color defaultSelectedTextColor;
Color defaultUnselectedTextColor;
bool defaultTextColorsSet;
Vector2 scrollPosition;
string previousNodeID;
bool isCurrentNodeVisible = true;
string lastVisibleNodeID;
List<string> nodeIDBreadcrumb = new List<string>();
public void BeginHierarchyView()
{
isCurrentNodeVisible = true;
lastVisibleNodeID = null;
nodeIDBreadcrumb.Clear();
EditorGUI.indentLevel = 0;
if (foldoutChildessStyle == null)
CreateStyles();
EditorGUILayout.BeginVertical();
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
previousNodeID = null;
}
void CreateStyles()
{
foldoutChildessStyle = new GUIStyle(EditorStyles.label);
var padding = foldoutChildessStyle.padding;
padding.left = 16;
foldoutChildessStyle.padding = padding;
selectedAreaStyle = new GUIStyle(GUIStyle.none);
selectedAreaStyle.normal.background = MakeTex(1, 1, new Color(0.24f, 0.49f, 0.91f));
selectedAreaStyle.active.background = selectedAreaStyle.normal.background;
selectedLabel = new GUIStyle(foldoutChildessStyle);
selectedLabel.normal.textColor = Color.white;
selectedFoldout = new GUIStyle(EditorStyles.foldout);
selectedFoldout.normal.textColor = Color.white;
selectedFoldout.active.textColor = Color.white;
selectedFoldout.focused.textColor = Color.white;
selectedFoldout.onNormal.textColor = Color.white;
selectedFoldout.onActive.textColor = Color.white;
selectedFoldout.onFocused.textColor = Color.white;
normalFoldout = new GUIStyle(EditorStyles.foldout);
normalFoldout.active = normalFoldout.normal;
normalFoldout.focused = normalFoldout.normal;
normalFoldout.onActive = normalFoldout.onNormal;
normalFoldout.onFocused = normalFoldout.onNormal;
SetDefaultTextColors();
}
void SetDefaultTextColors()
{
if (defaultTextColorsSet)
return;
if (EditorGUIUtility.isProSkin)
{
defaultSelectedTextColor = defaultSelectedTextColorDarkSkin;
defaultUnselectedTextColor = defaultUnselectedTextColorDarkSkin;
}
else
{
defaultSelectedTextColor = defaultSelectedTextColorWhiteSkin;
defaultUnselectedTextColor = defaultUnselectedTextColorWhiteSkin;
}
defaultTextColorsSet = true;
}
private Texture2D MakeTex(int width, int height, Color col)
{
Color[] pix = new Color[width * height];
for (int i = 0; i < pix.Length; i++)
pix[i] = col;
Texture2D result = new Texture2D(width, height);
result.SetPixels(pix);
result.Apply();
return result;
}
bool IsOpened(string id)
{
return OpenIds.Contains(id);
}
void Open(string id)
{
if (!IsOpened(id))
{
OpenIds.Add(id);
}
}
void Close(string id)
{
if (IsOpened(id))
{
OpenIds.Remove(id);
}
}
void AddToSelection(string id)
{
SelectedIds.Add(id);
}
bool IsSelected(string id)
{
return SelectedIds.Contains(id);
}
void RemoveFromSelection(string id)
{
SelectedIds.Remove(id);
}
void SetSelected(string id)
{
SelectedIds.Clear();
SelectedIds.Add(id);
GUI.FocusControl(id);
}
//Returns true if this node is selected
public bool BeginNode(string label)
{
return Node(label, true, defaultUnselectedTextColor, defaultSelectedTextColor);
}
//Returns true if this node is selected
public bool BeginNode(string label, Color unselectedTextColor, Color selectedTextColor)
{
return Node(label, true, unselectedTextColor, selectedTextColor);
}
//Returns true if this node is selected
public bool Node(string label, Color unselectedTextColor, Color selectedTextColor)
{
return Node(label, false, unselectedTextColor, selectedTextColor);
}
//Returns true if this node is selected
public bool Node(string label)
{
return Node(label, false, defaultUnselectedTextColor, defaultSelectedTextColor);
}
bool Node(string label, bool isParent, Color unselectedTextColor, Color selectedTextColor)
{
var id = GetIDForLabel(label);
if (isParent)
{
nodeIDBreadcrumb.Add(id);
}
if (!isCurrentNodeVisible)
return false;
bool wasOpened = IsOpened(id);
bool isSelected = IsSelected(id);
bool touchedInside = DrawNodeTouchableArea(id);
GUI.SetNextControlName(id);
bool opened = false;
if (isParent)
{
GUIStyle styleToUse = isSelected ? selectedFoldout : normalFoldout;
Color colorToUse = isSelected ? selectedTextColor : unselectedTextColor;
styleToUse.normal.textColor = colorToUse;
styleToUse.onNormal.textColor = colorToUse;
styleToUse.active.textColor = colorToUse;
styleToUse.onActive.textColor = colorToUse;
styleToUse.focused.textColor = colorToUse;
styleToUse.onFocused.textColor = colorToUse;
opened = EditorGUILayout.Foldout(wasOpened, label, styleToUse);
if (isSelected && Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.RightArrow)
{
opened = true;
}
else if (isSelected && Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.LeftArrow)
{
opened = false;
}
}
else
{
GUIStyle styleToUse = isSelected ? selectedLabel : foldoutChildessStyle;
Color colorToUse = isSelected ? selectedTextColor : unselectedTextColor;
styleToUse.normal.textColor = colorToUse;
styleToUse.active.textColor = colorToUse;
EditorGUILayout.LabelField(label, styleToUse);
}
EditorGUILayout.EndHorizontal();
bool useCurrentEvent = false;
if (wasOpened != opened)
{
useCurrentEvent = true;
if (opened)
Open(id);
else
Close(id);
}
else if (touchedInside)
{
useCurrentEvent = true;
if (Event.current.command)
{
if (IsSelected(id))
{
RemoveFromSelection(id);
}
else
{
AddToSelection(id);
}
}
else
SetSelected(id);
}
HandleKeyboardCycle(previousNodeID, id);
previousNodeID = id;
if (useCurrentEvent)
{
Event.current.Use();
}
if (isParent && !opened)
{
isCurrentNodeVisible = false;
lastVisibleNodeID = id;
}
if (isParent)
{
EditorGUI.indentLevel++;
}
return IsSelected(id);
}
public void EndNode()
{
string endedNodeId = nodeIDBreadcrumb[nodeIDBreadcrumb.Count - 1];
if (endedNodeId == lastVisibleNodeID)
{
isCurrentNodeVisible = true;
lastVisibleNodeID = null;
}
nodeIDBreadcrumb.RemoveAt(nodeIDBreadcrumb.Count - 1);
if (isCurrentNodeVisible)
EditorGUI.indentLevel--;
}
string GetIDForLabel(string label)
{
StringBuilder sb = new StringBuilder();
foreach (string id in nodeIDBreadcrumb)
{
sb.Append(id);
sb.Append("_");
}
sb.Append(label);
return sb.ToString();
}
void HandleKeyboardCycle(string previousNodeID, string currentNodeID)
{
if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.DownArrow)
{
if (IsSelected(previousNodeID))
{
Event.current.Use();
SetSelected(currentNodeID);
}
}
else if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.UpArrow)
{
if (IsSelected(currentNodeID))
{
Event.current.Use();
SetSelected(previousNodeID);
}
}
}
bool DrawNodeTouchableArea(string id)
{
var area = EditorGUILayout.BeginHorizontal(IsSelected(id) ? selectedAreaStyle : GUIStyle.none, GUILayout.ExpandWidth(true));
Event currentEvent = Event.current;
bool touchedInside = false;
if (currentEvent.type == EventType.MouseUp)
{
Vector2 mousePosition = currentEvent.mousePosition;
if (area.Contains(mousePosition))
{
touchedInside = true;
}
}
return touchedInside;
}
public void EndHierarchyView()
{
if (nodeIDBreadcrumb.Count > 0)
{
Debug.LogError("Called EndHierarchyView with nodes still opened. Please ensure that you have a EndNode() for every BeginNode()");
}
EditorGUILayout.EndVertical();
EditorGUILayout.EndScrollView();
}
}
The script show all the hierarchy scene objects in the editorwindow.
I want then in the editorwindow to manipulate and make changes to the objects.
The problem is that scrolling up down between the objects and childs is very slow not like in the original hierarchy window that is much faster.
The main goal is to show the hierarchy scene gameobjects in the editorwindow and then work on the objects in the editor window.

From what I can see your foreach loop is constantly getting a sibling index every iteration along with all the gameObjects in the scene. You should initially grab the gameobjects store them into a class with variables and then add that to a Collection. Iterate that collection and just pull the values.
EditorGUIHierarchyView hierarchyView = new EditorGUIHierarchyView();
private static GameObject[] _sceneObjects;
[MenuItem("Window/EditorGUIHierarchy - Show Scene View")]
static void Init()
{
EditorGUIHierarchyViewExampleWindow window = (EditorGUIHierarchyViewExampleWindow)GetWindow(typeof(EditorGUIHierarchyViewExampleWindow));
_sceneObjects = SceneManager.GetActiveScene().GetRootGameObjects();
Array.Sort(_sceneObjects, new SceneGameObjectComparer());
window.Show();
}
struct SceneGameObjectComparer : IComparer<GameObject>
{
public int Compare(GameObject go1, GameObject go2)
{
return go1.transform.GetSiblingIndex().CompareTo(go2.transform.GetSiblingIndex());
}
}
void OnEnable()
{
this.titleContent = new GUIContent("Scene View");
}
public void OnGUI()
{
hierarchyView.BeginHierarchyView();
foreach (GameObject gameObject in _sceneObjects)
{
gameObject.transform.GetSiblingIndex();
DrawGameObject(gameObject);
}
hierarchyView.EndHierarchyView();
Repaint();
}
void DrawGameObject(GameObject go)
{
if (go.transform.childCount > 0)
{
if (go.activeInHierarchy)
{
hierarchyView.BeginNode(go.name);
}
else
{
hierarchyView.BeginNode(go.name, Color.gray, Color.gray);
}
foreach (Transform child in go.transform)
{
DrawGameObject(child.gameObject);
}
hierarchyView.EndNode();
}
else
{
if (go.activeInHierarchy)
{
hierarchyView.Node(go.name);
}
else
{
hierarchyView.Node(go.name, Color.gray, Color.gray);
}
}
}

Related

Prefab instantiating outside of viewport, and giving null reference exception in Unity C#

So, I'm aware that null reference exceptions are a pretty commonly brought up issue on here, but I'm genuinely stuck on this, as this code went from working fine to really not working, and I can't figure out why. I used this tutorial as a starter to get to where I am, https://www.youtube.com/watch?v=2TYLBusJKjc, and then added/adapted for my purposes. I then copied the buttonlistcontrol and buttonlistbutton script files, and renamed and edited them to use as a separate settings menu, which is when it all went downhill.
[SerializeField]
public GameObject upButtonTemplate, buttonTemplate, headingTemplate;
public void GenButtons()
{
ClearAll();
bankIms = Resources.LoadAll("buttons/bank", typeof(Sprite));
coinIms = Resources.LoadAll("buttons/coin", typeof(Sprite));
bgIms = Resources.LoadAll("BgPrevs", typeof(Sprite));
upgrades = new string[]{"text,some more text, even more text none of which matters here"};
upPrices[0] = gameManager.bank;
GenHeading("UPGRADES");
for (int i = 0; i < upgrades.Length; i++)
{
GameObject button = Instantiate(upButtonTemplate) as GameObject;
button.SetActive(true);
Debug.Log("button: " + button);
button.GetComponent<ButtonListButton>().ButtonSetup("upgrade", i); // Null Reference occuring on this line
button.GetComponent<ButtonListButton>().SetUpText(upgrades[i]);
button.GetComponent<ButtonListButton>().SetPrice(upPrices[i]);
button.transform.SetParent(upButtonTemplate.transform.parent,false);
upButts.Add(button);
}
void GenHeading(string head)
{
GameObject heading = Instantiate(headingTemplate) as GameObject;
heading.SetActive(true);
heading.GetComponent<TextMeshProUGUI>().text = head;
heading.transform.SetParent(headingTemplate.transform.parent,false);
headings.Add(heading);
}
When GenButtons is run now, the heading is still being created as expected, but I get an error Object reference not set to an instance of an object, and a clone of the button prefab gets added outside the canvas.
Heading added as expected, but StoreListUpgrade is wildly and annoyingly off
Any help that could sort it would be thoroughly appreciated.
Below is the ButtonListButton script, if it helps.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
public class ButtonListButton : MonoBehaviour
{
[SerializeField]
private TextMeshProUGUI upButtText, buttText;
[SerializeField]
private ButtonListControl buttonControl;
[SerializeField]
private Image buttonImage;
[SerializeField]
private SoundManager soundManager;
public GameManager gameManager;
public double buttonPrice;
public int buttonID;
public bool owned;
public bool selected;
public string buttonType;
public void ButtonSetup(string type, int id)
{
if (type == "bank") {
owned = buttonControl.bankOwn[id];
selected = buttonControl.bankSel[id];
} else if (type == "coin") {
owned = buttonControl.coinOwn[id];
selected = buttonControl.coinSel[id];
} else if (type == "bg") {
owned = buttonControl.bgOwn[id];
selected = buttonControl.bgSel[id];
}
buttonType = type;
buttonID = id;
}
public void SetPrice(double price)
{
if (owned) {
if (selected) {
buttText.text = "✔";
} else {
buttText.text = "Owned";
}
} else {
buttonPrice = price;
buttText.text = "$" + price.ToString("N0");
}
TextColour();
}
public void PriceUpdate(bool onPurchase, bool onSetup)
{
if (buttonType == "upgrade"){
if (buttonID == 0) {
buttonPrice = 0;
SetPrice(0);
} else if (buttonID == 1) {
buttonPrice = (double)(buttonPrice * 1.2f);
buttonControl.upPrices[buttonID] = buttonPrice;
SetPrice(buttonPrice);
} else if (buttonID == 2) {
buttonPrice = (double)(buttonPrice * 1.5f);
buttonControl.upPrices[buttonID] = buttonPrice;
SetPrice(buttonPrice);
} else if (buttonID == 3) {
buttonPrice = (double)(buttonPrice * 1.5f);
buttonControl.upPrices[buttonID] = buttonPrice;
SetPrice(buttonPrice);
}
} else {
if (onPurchase) {
buttText.text = "✔";
selected = true;
owned = true;
buttonControl.OwnSel(buttonType, buttonID, "sel", true);
buttonControl.OwnSel(buttonType, buttonID, "own", true);
buttonPrice = 0;
} else {
if (onSetup == false && selected) {
selected = false;
buttonControl.OwnSel(buttonType, buttonID, "sel", false);
buttText.text = "Owned";
}
}
}
TextColour();
}
public void SetImage(Object ob)
{
Debug.Log("Set Image: " + ob);
buttonImage.sprite = ob as Sprite;
}
public void SetUpText(string upgrade)
{
upButtText.text = upgrade;
}
public void TextColour()
{
if (gameManager.bank >= buttonPrice && buttonPrice > 0 || owned) {
buttText.color = Color.black;
} else {
buttText.color = new Color(180, 0, 0, 1);
}
}
public void OnClick()
{
Debug.Log("bank: " + gameManager.bank + ", buttprice: " + buttonPrice + ", compareto: " + gameManager.bank.CompareTo(buttonPrice));
Debug.Log("adjust compare: " + gameManager.bank.CompareTo(buttonPrice - 0.001f) + "bank: " + gameManager.bank + ", buttprice-: " + (buttonPrice - 0.001f));
if (gameManager.bank.CompareTo(buttonPrice - 0.001f) >= 0) {
if (buttonID == 0 && gameManager.bank == 0) {
soundManager.playnobuy(1);
} else {
soundManager.playmenuopen(0.8f);
buttonControl.ButtonClicked(buttonPrice, buttonType, buttonID);
PriceUpdate(true,false);
}
} else {
soundManager.playnobuy(1);
}
}
}
I think the formatting went a bit off there, apologies for that.

Scene is Loading in Unity but unable to Load Scene in Android

My Game is working perfectly in Unity but when I export apk tp Android Mobile 2nd Scene doesn't load properly and does not work.
Please look at the image. It is the second Scene and not loaded properly and the Run button is not working which is working perfectly in unity play mode.
enter image description here
CODES ARE BELOW
SCENE 1 CODE#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
#if UNITY_ANALYTICS
using UnityEngine.Analytics;
#endif
#if UNITY_PURCHASING
using UnityEngine.Purchasing;
#endif
public class StartButton : MonoBehaviour
{
public void StartGame()
{
if (PlayerData.instance.ftueLevel == 0)
{
PlayerData.instance.ftueLevel = 1;
PlayerData.instance.Save();
#if UNITY_ANALYTICS
AnalyticsEvent.FirstInteraction("start_button_pressed");
#endif
}
#if UNITY_PURCHASING
var module = StandardPurchasingModule.Instance();
#endif
SceneManager.LoadScene("main");
}
}
SCENE 2 CODE#
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
#if UNITY_ANALYTICS
using UnityEngine.Analytics;
#endif
/// <summary>
/// State pushed on the GameManager during the Loadout, when player select player, theme and accessories
/// Take care of init the UI, load all the data used for it etc.
/// </summary>
public class LoadoutState : AState
{
public Canvas inventoryCanvas;
[Header("Char UI")]
public Text charNameDisplay;
public RectTransform charSelect;
public Transform charPosition;
[Header("Theme UI")]
public Text themeNameDisplay;
public RectTransform themeSelect;
public Image themeIcon;
[Header("PowerUp UI")]
public RectTransform powerupSelect;
public Image powerupIcon;
public Text powerupCount;
public Sprite noItemIcon;
[Header("Accessory UI")]
public RectTransform accessoriesSelector;
public Text accesoryNameDisplay;
public Image accessoryIconDisplay;
[Header("Other Data")]
public Leaderboard leaderboard;
public MissionUI missionPopup;
public Button runButton;
public GameObject tutorialBlocker;
public GameObject tutorialPrompt;
public MeshFilter skyMeshFilter;
public MeshFilter UIGroundFilter;
public AudioClip menuTheme;
[Header("Prefabs")]
public ConsumableIcon consumableIcon;
Consumable.ConsumableType m_PowerupToUse = Consumable.ConsumableType.NONE;
protected GameObject m_Character;
protected List<int> m_OwnedAccesories = new List<int>();
protected int m_UsedAccessory = -1;
protected int m_UsedPowerupIndex;
protected bool m_IsLoadingCharacter;
protected Modifier m_CurrentModifier = new Modifier();
protected const float k_CharacterRotationSpeed = 45f;
protected const string k_ShopSceneName = "shop";
protected const float k_OwnedAccessoriesCharacterOffset = -0.1f;
protected int k_UILayer;
protected readonly Quaternion k_FlippedYAxisRotation = Quaternion.Euler (0f, 180f, 0f);
public override void Enter(AState from)
{
tutorialBlocker.SetActive(!PlayerData.instance.tutorialDone);
tutorialPrompt.SetActive(false);
inventoryCanvas.gameObject.SetActive(true);
missionPopup.gameObject.SetActive(false);
charNameDisplay.text = "";
themeNameDisplay.text = "";
k_UILayer = LayerMask.NameToLayer("UI");
skyMeshFilter.gameObject.SetActive(true);
UIGroundFilter.gameObject.SetActive(true);
// Reseting the global blinking value. Can happen if the game unexpectedly exited while still blinking
Shader.SetGlobalFloat("_BlinkingValue", 0.0f);
if (MusicPlayer.instance.GetStem(0) != menuTheme)
{
MusicPlayer.instance.SetStem(0, menuTheme);
StartCoroutine(MusicPlayer.instance.RestartAllStems());
}
runButton.interactable = false;
runButton.GetComponentInChildren<Text>().text = "Loading...";
if(m_PowerupToUse != Consumable.ConsumableType.NONE)
{
//if we come back from a run and we don't have any more of the powerup we wanted to use, we reset the powerup to use to NONE
if (!PlayerData.instance.consumables.ContainsKey(m_PowerupToUse) || PlayerData.instance.consumables[m_PowerupToUse] == 0)
m_PowerupToUse = Consumable.ConsumableType.NONE;
}
Refresh();
}
public override void Exit(AState to)
{
missionPopup.gameObject.SetActive(false);
inventoryCanvas.gameObject.SetActive(false);
if (m_Character != null) Addressables.ReleaseInstance(m_Character);
GameState gs = to as GameState;
skyMeshFilter.gameObject.SetActive(false);
UIGroundFilter.gameObject.SetActive(false);
if (gs != null)
{
gs.currentModifier = m_CurrentModifier;
// We reset the modifier to a default one, for next run (if a new modifier is applied, it will replace this default one before the run starts)
m_CurrentModifier = new Modifier();
if (m_PowerupToUse != Consumable.ConsumableType.NONE)
{
PlayerData.instance.Consume(m_PowerupToUse);
Consumable inv = Instantiate(ConsumableDatabase.GetConsumbale(m_PowerupToUse));
inv.gameObject.SetActive(false);
gs.trackManager.characterController.inventory = inv;
}
}
}
public void Refresh()
{
PopulatePowerup();
StartCoroutine(PopulateCharacters());
StartCoroutine(PopulateTheme());
}
public override string GetName()
{
return "Loadout";
}
public override void Tick()
{
if (!runButton.interactable)
{
bool interactable = ThemeDatabase.loaded && CharacterDatabase.loaded;
if(interactable)
{
runButton.interactable = true;
runButton.GetComponentInChildren<Text>().text = "Run!";
//we can always enabled, as the parent will be disabled if tutorial is already done
tutorialPrompt.SetActive(true);
}
}
if(m_Character != null)
{
m_Character.transform.Rotate(0, k_CharacterRotationSpeed * Time.deltaTime, 0, Space.Self);
}
charSelect.gameObject.SetActive(PlayerData.instance.characters.Count > 1);
themeSelect.gameObject.SetActive(PlayerData.instance.themes.Count > 1);
}
public void GoToStore()
{
UnityEngine.SceneManagement.SceneManager.LoadScene(k_ShopSceneName, UnityEngine.SceneManagement.LoadSceneMode.Additive);
}
public void ChangeCharacter(int dir)
{
PlayerData.instance.usedCharacter += dir;
if (PlayerData.instance.usedCharacter >= PlayerData.instance.characters.Count)
PlayerData.instance.usedCharacter = 0;
else if(PlayerData.instance.usedCharacter < 0)
PlayerData.instance.usedCharacter = PlayerData.instance.characters.Count-1;
StartCoroutine(PopulateCharacters());
}
public void ChangeAccessory(int dir)
{
m_UsedAccessory += dir;
if (m_UsedAccessory >= m_OwnedAccesories.Count)
m_UsedAccessory = -1;
else if (m_UsedAccessory < -1)
m_UsedAccessory = m_OwnedAccesories.Count-1;
if (m_UsedAccessory != -1)
PlayerData.instance.usedAccessory = m_OwnedAccesories[m_UsedAccessory];
else
PlayerData.instance.usedAccessory = -1;
SetupAccessory();
}
public void ChangeTheme(int dir)
{
PlayerData.instance.usedTheme += dir;
if (PlayerData.instance.usedTheme >= PlayerData.instance.themes.Count)
PlayerData.instance.usedTheme = 0;
else if (PlayerData.instance.usedTheme < 0)
PlayerData.instance.usedTheme = PlayerData.instance.themes.Count - 1;
StartCoroutine(PopulateTheme());
}
public IEnumerator PopulateTheme()
{
ThemeData t = null;
while (t == null)
{
t = ThemeDatabase.GetThemeData(PlayerData.instance.themes[PlayerData.instance.usedTheme]);
yield return null;
}
themeNameDisplay.text = t.themeName;
themeIcon.sprite = t.themeIcon;
skyMeshFilter.sharedMesh = t.skyMesh;
UIGroundFilter.sharedMesh = t.UIGroundMesh;
}
public IEnumerator PopulateCharacters()
{
accessoriesSelector.gameObject.SetActive(false);
PlayerData.instance.usedAccessory = -1;
m_UsedAccessory = -1;
if (!m_IsLoadingCharacter)
{
m_IsLoadingCharacter = true;
GameObject newChar = null;
while (newChar == null)
{
Character c = CharacterDatabase.GetCharacter(PlayerData.instance.characters[PlayerData.instance.usedCharacter]);
if (c != null)
{
m_OwnedAccesories.Clear();
for (int i = 0; i < c.accessories.Length; ++i)
{
// Check which accessories we own.
string compoundName = c.characterName + ":" + c.accessories[i].accessoryName;
if (PlayerData.instance.characterAccessories.Contains(compoundName))
{
m_OwnedAccesories.Add(i);
}
}
Vector3 pos = charPosition.transform.position;
if (m_OwnedAccesories.Count > 0)
{
pos.x = k_OwnedAccessoriesCharacterOffset;
}
else
{
pos.x = 0.0f;
}
charPosition.transform.position = pos;
accessoriesSelector.gameObject.SetActive(m_OwnedAccesories.Count > 0);
AsyncOperationHandle op = Addressables.InstantiateAsync(c.characterName);
yield return op;
if (op.Result == null || !(op.Result is GameObject))
{
Debug.LogWarning(string.Format("Unable to load character {0}.", c.characterName));
yield break;
}
newChar = op.Result as GameObject;
Helpers.SetRendererLayerRecursive(newChar, k_UILayer);
newChar.transform.SetParent(charPosition, false);
newChar.transform.rotation = k_FlippedYAxisRotation;
if (m_Character != null)
Addressables.ReleaseInstance(m_Character);
m_Character = newChar;
charNameDisplay.text = c.characterName;
m_Character.transform.localPosition = Vector3.right * 1000;
//animator will take a frame to initialize, during which the character will be in a T-pose.
//So we move the character off screen, wait that initialised frame, then move the character back in place.
//That avoid an ugly "T-pose" flash time
yield return new WaitForEndOfFrame();
m_Character.transform.localPosition = Vector3.zero;
SetupAccessory();
}
else
yield return new WaitForSeconds(1.0f);
}
m_IsLoadingCharacter = false;
}
}
void SetupAccessory()
{
Character c = m_Character.GetComponent<Character>();
c.SetupAccesory(PlayerData.instance.usedAccessory);
if (PlayerData.instance.usedAccessory == -1)
{
accesoryNameDisplay.text = "None";
accessoryIconDisplay.enabled = false;
}
else
{
accessoryIconDisplay.enabled = true;
accesoryNameDisplay.text = c.accessories[PlayerData.instance.usedAccessory].accessoryName;
accessoryIconDisplay.sprite = c.accessories[PlayerData.instance.usedAccessory].accessoryIcon;
}
}
void PopulatePowerup()
{
powerupIcon.gameObject.SetActive(true);
if (PlayerData.instance.consumables.Count > 0)
{
Consumable c = ConsumableDatabase.GetConsumbale(m_PowerupToUse);
powerupSelect.gameObject.SetActive(true);
if (c != null)
{
powerupIcon.sprite = c.icon;
powerupCount.text = PlayerData.instance.consumables[m_PowerupToUse].ToString();
}
else
{
powerupIcon.sprite = noItemIcon;
powerupCount.text = "";
}
}
else
{
powerupSelect.gameObject.SetActive(false);
}
}
public void ChangeConsumable(int dir)
{
bool found = false;
do
{
m_UsedPowerupIndex += dir;
if(m_UsedPowerupIndex >= (int)Consumable.ConsumableType.MAX_COUNT)
{
m_UsedPowerupIndex = 0;
}
else if(m_UsedPowerupIndex < 0)
{
m_UsedPowerupIndex = (int)Consumable.ConsumableType.MAX_COUNT - 1;
}
int count = 0;
if(PlayerData.instance.consumables.TryGetValue((Consumable.ConsumableType)m_UsedPowerupIndex, out count) && count > 0)
{
found = true;
}
} while (m_UsedPowerupIndex != 0 && !found);
m_PowerupToUse = (Consumable.ConsumableType)m_UsedPowerupIndex;
PopulatePowerup();
}
public void UnequipPowerup()
{
m_PowerupToUse = Consumable.ConsumableType.NONE;
}
public void SetModifier(Modifier modifier)
{
m_CurrentModifier = modifier;
}
public void StartGame()
{
if (PlayerData.instance.tutorialDone)
{
if (PlayerData.instance.ftueLevel == 1)
{
PlayerData.instance.ftueLevel = 2;
PlayerData.instance.Save();
}
}
manager.SwitchState("Game");
}
public void Openleaderboard()
{
leaderboard.displayPlayer = false;
leaderboard.forcePlayerDisplay = false;
leaderboard.Open();
}
}
When you are building an APK file it can be splited to APK + OBB.
So, it is possible that you are trying to load a scene that is absent in your APK. You need to force the creation of the APK without the OBB. To do it you need to check Player Settings in Android, go to Publishing Settings and uncheck Split Application Binary.

Porblem with game once builded

in my game to pass from one level to another you must answer some questions. Each question has an associated image. For each level of play there is a different set of questions. During the Unity game simulation there is no problem, but when I play the build of the game, the set of questions is not updated between one level and another, in fact the last question made at the first level is re-proposed.
public class MiniGameManager : MonoBehaviour
{
public Question[] questions;
private static List<Question> unanswered;
private Question currentQuestion;
[SerializeField]
private Image sprite;
[SerializeField]
private float timeQuestion = 1f;
public static int contCorrect;
public Button firstSelected;
void Start()
{
if(unanswered == null || unanswered.Count == 0)
{
unanswered = questions.ToList<Question>();
}
contCorrect = 0;
SetCurrentQuestion();
firstSelected.Select();
}
void SetCurrentQuestion()
{
int index = UnityEngine.Random.Range(0, unanswered.Count);
currentQuestion = unanswered[index];
sprite.sprite = currentQuestion.questionSprite;
}
IEnumerator ToQuestion()
{
unanswered.Remove(currentQuestion);
yield return new WaitForSeconds(timeQuestion);
SetCurrentQuestion();
}
public void UserSelectFirst()
{
if (currentQuestion.answer == 0)
{
currentQuestion.correct = true;
countCorrect++;
}
else
{
currentQuestion.correct = false;
}
if (unanswered.Count > 1)
{
StartCoroutine(ToQuestion());
}
else
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1, LoadSceneMode.Single);
}
}
public void UserSelectSecond()
{
if (currentQuestion.answer == 1)
{
currentQuestion.correct = true;
countCorrect++;
}
else
{
currentQuestion.correct = false;
}
if (unanswered.Count > 1)
{
StartCoroutine(ToQuestion());
}
else
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1, LoadSceneMode.Single);
}
}
public void UserSelectThird()
{
if (currentQuestion.answer == 2)
{
currentQuestion.correct = true;
countCorrect++;
}
else
{
currentQuestion.correct = false;
}
if (unanswered.Count > 1)
{
StartCoroutine(ToQuestion());
}
else
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1, LoadSceneMode.Single);
}
}
public void UserSelectFourth()
{
if (currentQuestion.answer == 3)
{
currentQuestion.correct = true;
countCorrect++;
}
else
{
currentQuestion.correct = false;
}
if (unanswered.Count > 1)
{
StartCoroutine(ToQuestion());
}
else
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1, LoadSceneMode.Single);
}
}
}
I solved the problem. I just had to clear the list of questions before moving to the next level

GUI text created during runtime is not visible

I am using the DebugConsole script to show the debug output on screen.It works perfectly but appears at the top left corner. I want it to appear inside a panel where I have created a window and a GUI text element and the script gives this option as well. I see the gui text formed as an element in the project console, but is not visible.
I do have a GUI layer
My gui text element is the direct child of a canvas
Camera is set to screen space overlay. I tried worldspace , still not visible.
My code:
namespace OctopartApi
{
using Newtonsoft.Json;
using RestSharp;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine;
using System.Net;
using UnityEngine.UI;
public class KeywordSearch1 : MonoBehaviour
{
public InputField mainInputField;
public Canvas can;
public Text infoText;
public float x, y;
void Start () {
mainInputField.onEndEdit.AddListener(delegate {LockInput(mainInputField); });
}
void LockInput(InputField input)
{
ExecuteSearch (input.text);
}
public void ExecuteSearch(string inp)
{
// -- your search query --
string query = inp;
string octopartUrlBase = "http://octopart.com/api/v3";
string octopartUrlEndpoint = "parts/search";
string apiKey = "57af648b";
// Create the search request
var client = new RestClient(octopartUrlBase);
var req = new RestRequest(octopartUrlEndpoint, Method.GET)
.AddParameter("apikey", apiKey)
.AddParameter("q", query)
.AddParameter("start", "0")
.AddParameter("limit", "10");
var resp = client.Execute(req);
string octojson = resp.Content;
RootOb rr = JsonUtility.FromJson<RootOb> (octojson);
string hhts = (rr.hits).ToString();
hhts = hhts + rr.user_currency;
infoText.horizontalOverflow = HorizontalWrapMode.Overflow;
infoText.verticalOverflow = VerticalWrapMode.Overflow;
infoText.text = hhts;
// sendR (inp);
// Perform the search and obtain results
/* var resp = client.Execute(req);
var search_response = JsonConvert.DeserializeObject<dynamic>(resp.Content);
Console.WriteLine (search_response);
// Print the number of hits and results
Console.WriteLine("Number of hits: " + search_response["hits"]);
Debug.Log(search_response ["hits"]+"OCTO");
foreach (var result in search_response["results"])
{
var part = result["item"];
Debug.Log(part["brand"]["name"] + "OCTO" + part["mpn"]+part["octopart_url"]);
DebugConsole.Log (part ["brand"] ["name"] + "-- " + part ["mpn"]+" " +part["octopart_url"]);
}*/
}
// -- your API key -- (https://octopart.com/api/register)
private const string APIKEY = "57af648b";
}
}
DebugConsole script :
using UnityEngine;
using System.Collections;
public class DebugConsole : MonoBehaviour
{
public GameObject DebugGui = null; // The GUI that will be duplicated
public Vector3 defaultGuiPosition = new Vector3(0.01F, 0.98F, 0F);
public Vector3 defaultGuiScale = new Vector3(0.5F, 0.5F, 1F);
public Color normal = Color.green;
public Color warning = Color.yellow;
public Color error = Color.red;
public int maxMessages = 30; // The max number of messages displayed
public float lineSpacing = 0.02F; // The amount of space between lines
public ArrayList messages = new ArrayList();
public ArrayList guis = new ArrayList();
public ArrayList colors = new ArrayList();
public bool draggable = true; // Can the output be dragged around at runtime by default?
public bool visible = true; // Does output show on screen by default or do we have to enable it with code?
public bool pixelCorrect = false; // set to be pixel Correct linespacing
public static bool isVisible
{
get
{
return DebugConsole.instance.visible;
}
set
{
DebugConsole.instance.visible = value;
if (value == true)
{
DebugConsole.instance.Display();
}
else if (value == false)
{
DebugConsole.instance.ClearScreen();
}
}
}
public static bool isDraggable
{
get
{
return DebugConsole.instance.draggable;
}
set
{
DebugConsole.instance.draggable = value;
}
}
private static DebugConsole s_Instance = null; // Our instance to allow this script to be called without a direct connection.
public static DebugConsole instance
{
get
{
if (s_Instance == null)
{
s_Instance = FindObjectOfType(typeof(DebugConsole)) as DebugConsole;
if (s_Instance == null)
{
GameObject console = new GameObject();
console.AddComponent<DebugConsole>();
console.name = "DebugConsoleController";
s_Instance = FindObjectOfType(typeof(DebugConsole)) as DebugConsole;
DebugConsole.instance.InitGuis();
}
}
return s_Instance;
}
}
void Awake()
{
s_Instance = this;
InitGuis();
}
protected bool guisCreated = false;
protected float screenHeight =-1;
public void InitGuis()
{
float usedLineSpacing = lineSpacing;
screenHeight = Screen.height;
if(pixelCorrect)
usedLineSpacing = 1.0F / screenHeight * usedLineSpacing;
if (guisCreated == false)
{
if (DebugGui == null) // If an external GUIText is not set, provide the default GUIText
{
DebugGui = new GameObject();
DebugGui.AddComponent<GUIText>();
DebugGui.name = "DebugGUI(0)";
DebugGui.transform.position = defaultGuiPosition;
DebugGui.transform.localScale = defaultGuiScale;
}
// Create our GUI objects to our maxMessages count
Vector3 position = DebugGui.transform.position;
guis.Add(DebugGui);
int x = 1;
while (x < maxMessages)
{
position.y -= usedLineSpacing;
GameObject clone = null;
clone = (GameObject)Instantiate(DebugGui, position, transform.rotation);
clone.name = string.Format("DebugGUI({0})", x);
guis.Add(clone);
position = clone.transform.position;
x += 1;
}
x = 0;
while (x < guis.Count)
{
GameObject temp = (GameObject)guis[x];
temp.transform.parent = DebugGui.transform;
x++;
}
guisCreated = true;
} else {
// we're called on a screensize change, so fiddle with sizes
Vector3 position = DebugGui.transform.position;
for(int x=0;x < guis.Count; x++)
{
position.y -= usedLineSpacing;
GameObject temp = (GameObject)guis[x];
temp.transform.position= position;
}
}
}
bool connectedToMouse = false;
void Update()
{
// If we are visible and the screenHeight has changed, reset linespacing
if (visible == true && screenHeight != Screen.height)
{
InitGuis();
}
if (draggable == true)
{
if (Input.GetMouseButtonDown(0))
{
if (connectedToMouse == false && DebugGui.GetComponent<GUIText>().HitTest((Vector3)Input.mousePosition) == true)
{
connectedToMouse = true;
}
else if (connectedToMouse == true)
{
connectedToMouse = false;
}
}
if (connectedToMouse == true)
{
float posX = DebugGui.transform.position.x;
float posY = DebugGui.transform.position.y;
posX = Input.mousePosition.x / Screen.width;
posY = Input.mousePosition.y / Screen.height;
DebugGui.transform.position = new Vector3(posX, posY, 0F);
}
}
}
//+++++++++ INTERFACE FUNCTIONS ++++++++++++++++++++++++++++++++
public static void Log(string message, string color)
{
DebugConsole.instance.AddMessage(message, color);
}
//++++ OVERLOAD ++++
public static void Log(string message)
{
DebugConsole.instance.AddMessage(message);
}
public static void Clear()
{
DebugConsole.instance.ClearMessages();
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//---------- void AddMesage(string message, string color) ------
//Adds a mesage to the list
//--------------------------------------------------------------
public void AddMessage(string message, string color)
{
messages.Add(message);
colors.Add(color);
Display();
}
//++++++++++ OVERLOAD for AddMessage ++++++++++++++++++++++++++++
// Overloads AddMessage to only require one argument(message)
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
public void AddMessage(string message)
{
messages.Add(message);
colors.Add("normal");
Display();
}
//----------- void ClearMessages() ------------------------------
// Clears the messages from the screen and the lists
//---------------------------------------------------------------
public void ClearMessages()
{
messages.Clear();
colors.Clear();
ClearScreen();
}
//-------- void ClearScreen() ----------------------------------
// Clears all output from all GUI objects
//--------------------------------------------------------------
void ClearScreen()
{
if (guis.Count < maxMessages)
{
//do nothing as we haven't created our guis yet
}
else
{
int x = 0;
while (x < guis.Count)
{
GameObject gui = (GameObject)guis[x];
gui.GetComponent<GUIText>().text = "";
//increment and loop
x += 1;
}
}
}
//---------- void Prune() ---------------------------------------
// Prunes the array to fit within the maxMessages limit
//---------------------------------------------------------------
void Prune()
{
int diff;
if (messages.Count > maxMessages)
{
if (messages.Count <= 0)
{
diff = 0;
}
else
{
diff = messages.Count - maxMessages;
}
messages.RemoveRange(0, (int)diff);
colors.RemoveRange(0, (int)diff);
}
}
//---------- void Display() -------------------------------------
// Displays the list and handles coloring
//---------------------------------------------------------------
void Display()
{
//check if we are set to display
if (visible == false)
{
ClearScreen();
}
else if (visible == true)
{
if (messages.Count > maxMessages)
{
Prune();
}
// Carry on with display
int x = 0;
if (guis.Count < maxMessages)
{
//do nothing as we havent created our guis yet
}
else
{
while (x < messages.Count)
{
GameObject gui = (GameObject)guis[x];
//set our color
switch ((string)colors[x])
{
case "normal": gui.GetComponent<GUIText>().material.color = normal;
break;
case "warning": gui.GetComponent<GUIText>().material.color = warning;
break;
case "error": gui.GetComponent<GUIText>().material.color = error;
break;
}
//now set the text for this element
gui.GetComponent<GUIText>().text = (string)messages[x];
//increment and loop
x += 1;
}
}
}
}
}// End DebugConsole Class

Unity: Can't find UI Layout Element Max Size

In Unity UI, LayoutElement has a min, prefered and flxible size, but it do not have a max size property.
For example if I have a text1 and
layoutElement.flxibleWith = 1
layoutElement.minHeight = 19
text1 with one line txt:
But when I load text in text1 it continues spreading it height with no limits:
I have made a script:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
[ExecuteInEditMode]
[RequireComponent(typeof(LayoutElement))]
public class LayoutElementMaxSize : MonoBehaviour
{
private LayoutElement layoutElement;
private ContentSizeFitter contentSizeFitter;
private RectTransform rectransform;
public bool controllWidth;
public bool controllHeight;
public float maxHight;
public float maxWidth;
void Start()
{
layoutElement = GetComponent<LayoutElement>();
rectransform = GetComponent<RectTransform>();
}
public void Update()
{
if(rectransform.hasChanged)
{
rectransform.hasChanged = false;
if (controllHeight)
{
layoutElement.preferredHeight = -1;
layoutElement.CalculateLayoutInputHorizontal();
layoutElement.CalculateLayoutInputVertical();
if (rectransform.rect.height >= maxHight)
{
layoutElement.preferredHeight = maxHight;
}
}
if (controllWidth)
{
if (rectransform.rect.height >= maxWidth)
{
layoutElement.preferredWidth = maxWidth;
}
else
{
layoutElement.preferredWidth = -1;
}
}
}
}}
but it is not full filing my requirement plz take a look on it ..
I know this is an old question, but I was looking for something like this and I end up rewriting your class and it now works fine for me. Instead of just making another MonoBehaviour I override the LayoutElement, I also added an custom inspector to make it easy to edit it. Hope my solution could help you or anyone else that would like something like this.
using UnityEngine;
using UnityEngine.UI;
#if UNITY_EDITOR
using UnityEditor;
#endif
[RequireComponent(typeof(RectTransform))]
[System.Serializable]
public class LayoutMaxSize : LayoutElement
{
public float maxHeight = -1;
public float maxWidth = -1;
public override void CalculateLayoutInputHorizontal()
{
base.CalculateLayoutInputHorizontal();
UpdateMaxSizes();
}
public override void CalculateLayoutInputVertical()
{
base.CalculateLayoutInputVertical();
UpdateMaxSizes();
}
protected override void OnRectTransformDimensionsChange()
{
base.OnRectTransformDimensionsChange();
UpdateMaxSizes();
}
protected override void OnValidate()
{
base.OnValidate();
UpdateMaxSizes();
}
private void UpdateMaxSizes()
{
if (maxHeight != -1)
{
if (preferredHeight == -1 && maxHeight < GetComponent<RectTransform>().sizeDelta.y)
{
preferredHeight = maxHeight;
}
else if (preferredHeight != -1 && transform.childCount > 0)
{
bool first = true;
float biggestY = 0;
float lowestY = 0;
for (int i = 0; i < transform.childCount; i++)
{
var childrenTransform = transform.GetChild(i).GetComponent<RectTransform>();
if (childrenTransform == null) continue;
var childPos = childrenTransform.localPosition;
var childSize = childrenTransform.sizeDelta;
var childPivot = childrenTransform.pivot;
if(first)
{
biggestY = childPos.y + (childSize.y * (1f - childPivot.y));
lowestY = childPos.y - (childSize.y * childPivot.y);
}
else
{
biggestY = Mathf.Max(biggestY, childPos.y + (childSize.y * (1f - childPivot.y)));
lowestY = Mathf.Min(lowestY, childPos.y - (childSize.y * childPivot.y));
}
first = false;
}
if (first) return;
var childrenYSize = Mathf.Abs(biggestY - lowestY);
if(preferredHeight > childrenYSize)
{
preferredHeight = -1;
}
}
}
if (maxWidth != -1)
{
if (preferredWidth == -1 && maxWidth < GetComponent<RectTransform>().sizeDelta.x)
{
preferredWidth = maxWidth;
}
else if (preferredWidth != -1 && transform.childCount > 0)
{
bool first = true;
float biggestX = 0;
float lowestX = 0;
for (int i = 0; i < transform.childCount; i++)
{
var childrenTransform = transform.GetChild(i).GetComponent<RectTransform>();
if (childrenTransform == null) continue;
var childPos = childrenTransform.localPosition;
var childSize = childrenTransform.sizeDelta;
var childPivot = childrenTransform.pivot;
if (first)
{
biggestX = childPos.x + (childSize.x * (1f - childPivot.x));
lowestX = childPos.x - (childSize.x * childPivot.x);
}
else
{
biggestX = Mathf.Max(biggestX, childPos.x + (childSize.x * (1f - childPivot.x)));
lowestX = Mathf.Min(lowestX, childPos.x - (childSize.x * childPivot.x));
}
first = false;
}
if (first) return;
var childrenXSize = Mathf.Abs(biggestX - lowestX);
if (preferredWidth > childrenXSize)
{
preferredWidth = -1;
}
}
}
}
}
#if UNITY_EDITOR
[CustomEditor(typeof(LayoutMaxSize))]
public class LayoutMaxSizeEditor : Editor
{
public override void OnInspectorGUI()
{
LayoutMaxSize layoutMax = target as LayoutMaxSize;
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel("Ignore Layout");
layoutMax.ignoreLayout = EditorGUILayout.Toggle(layoutMax.ignoreLayout);
EditorGUILayout.EndHorizontal();
if (!layoutMax.ignoreLayout)
{
EditorGUILayout.Space();
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel("Min Width");
var allowMinWidth = EditorGUILayout.Toggle(layoutMax.minWidth != -1);
if (allowMinWidth)
{
if (layoutMax.minWidth == -1) layoutMax.minWidth = 0;
layoutMax.minWidth = EditorGUILayout.FloatField(layoutMax.minWidth);
}
else if (layoutMax.minWidth != -1)
{
layoutMax.minWidth = -1;
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel("Min Height");
var allowMinHeight = EditorGUILayout.Toggle(layoutMax.minHeight != -1);
if (allowMinHeight)
{
if (layoutMax.minHeight == -1) layoutMax.minHeight = 0;
layoutMax.minHeight = EditorGUILayout.FloatField(layoutMax.minHeight);
}
else if (layoutMax.minHeight != -1)
{
layoutMax.minHeight = -1;
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel("Max Width");
var allowMaxWidth = EditorGUILayout.Toggle(layoutMax.maxWidth != -1);
if (allowMaxWidth)
{
if (layoutMax.maxWidth == -1) layoutMax.maxWidth = Mathf.Max(0, layoutMax.minWidth);
layoutMax.maxWidth = Mathf.Max(EditorGUILayout.FloatField(layoutMax.maxWidth), layoutMax.minWidth);
}
else if(layoutMax.maxWidth != -1)
{
layoutMax.maxWidth = -1;
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel("Max Height");
var allowMaxHeight = EditorGUILayout.Toggle(layoutMax.maxHeight != -1);
if (allowMaxHeight)
{
if (layoutMax.maxHeight == -1) layoutMax.maxHeight = Mathf.Max(0, layoutMax.minHeight);
layoutMax.maxHeight = Mathf.Max(EditorGUILayout.FloatField(layoutMax.maxHeight), layoutMax.minHeight);
}
else if (layoutMax.maxHeight != -1)
{
layoutMax.maxHeight = -1;
}
EditorGUILayout.EndHorizontal();
}
}
}
#endif
I wrote a new script which includes maxheight and maxwidth field for layout element it is not fuly tested but if you want you can use it.
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;
#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.UI;
#endif
[RequireComponent(typeof(RectTransform))]
[System.Serializable]
public class LayoutElementWithMaxValues : LayoutElement {
public float maxHeight;
public float maxWidth;
public bool useMaxWidth;
public bool useMaxHeight;
bool ignoreOnGettingPreferedSize;
public override int layoutPriority {
get => ignoreOnGettingPreferedSize ? -1 : base.layoutPriority;
set => base.layoutPriority = value; }
public override float preferredHeight {
get {
if (useMaxHeight) {
var defaultIgnoreValue = ignoreOnGettingPreferedSize;
ignoreOnGettingPreferedSize = true;
var baseValue = LayoutUtility.GetPreferredHeight(transform as RectTransform);
ignoreOnGettingPreferedSize = defaultIgnoreValue;
return baseValue > maxHeight ? maxHeight : baseValue;
}
else
return base.preferredHeight;
}
set => base.preferredHeight = value;
}
public override float preferredWidth {
get {
if (useMaxWidth) {
var defaultIgnoreValue = ignoreOnGettingPreferedSize;
ignoreOnGettingPreferedSize = true;
var baseValue = LayoutUtility.GetPreferredWidth(transform as RectTransform);
ignoreOnGettingPreferedSize = defaultIgnoreValue;
return baseValue > maxWidth ? maxWidth : baseValue;
}
else
return base.preferredWidth;
}
set => base.preferredWidth = value;
}
}
#if UNITY_EDITOR
[CustomEditor(typeof(LayoutElementWithMaxValues), true)]
[CanEditMultipleObjects]
public class LayoutMaxSizeEditor : LayoutElementEditor {
LayoutElementWithMaxValues layoutMax;
SerializedProperty maxHeightProperty;
SerializedProperty maxWidthProperty;
SerializedProperty useMaxHeightProperty;
SerializedProperty useMaxWidthProperty;
RectTransform myRectTransform;
protected override void OnEnable() {
base.OnEnable();
layoutMax = target as LayoutElementWithMaxValues;
myRectTransform = layoutMax.transform as RectTransform;
maxHeightProperty = serializedObject.FindProperty(nameof(layoutMax.maxHeight));
maxWidthProperty = serializedObject.FindProperty(nameof(layoutMax.maxWidth));
useMaxHeightProperty = serializedObject.FindProperty(nameof(layoutMax.useMaxHeight));
useMaxWidthProperty = serializedObject.FindProperty(nameof(layoutMax.useMaxWidth));
}
public override void OnInspectorGUI() {
Draw(maxWidthProperty, useMaxWidthProperty);
Draw(maxHeightProperty, useMaxHeightProperty);
serializedObject.ApplyModifiedProperties();
EditorGUILayout.Space();
base.OnInspectorGUI();
}
void Draw(SerializedProperty property, SerializedProperty useProperty) {
Rect position = EditorGUILayout.GetControlRect();
GUIContent label = EditorGUI.BeginProperty(position, null, property);
Rect fieldPosition = EditorGUI.PrefixLabel(position, label);
Rect toggleRect = fieldPosition;
toggleRect.width = 16;
Rect floatFieldRect = fieldPosition;
floatFieldRect.xMin += 16;
var use = EditorGUI.Toggle(toggleRect, useProperty.boolValue);
useProperty.boolValue = use;
if (use) {
EditorGUIUtility.labelWidth = 4;
property.floatValue = EditorGUI.FloatField(floatFieldRect, new GUIContent(" "), property.floatValue);
EditorGUIUtility.labelWidth = 0;
}
EditorGUI.EndProperty();
}
}
#endif

Categories