After fighting with Unity for the better part of an hour, attempting to align the label for a Vector3Field in an editor window on the same horizontal line as the Vector3Field, I decided to tackle it with a different approach.
Before and After using the new class.
using UnityEditor;
using UnityEngine;
public static class EditorUtilities
{
/// <summary>
/// Draws an inline Vector3Field with label.
/// </summary>
/// <param name="label">String to be used as the label.</param>
/// <param name="input">Initial Vector3 input for this field.</param>
/// <param name="options">GUILayoutOption parameters<</param>
/// <see href="https://docs.unity3d.com/ScriptReference/EditorGUILayout.Vector3Field.html">EditorGUILayout.Vector3Field</see>
/// <returns>Vector3 value defined by this inspector field.</returns>
public static Vector3 Vector3Field(string label, Vector3 input, GUILayoutOption[] options = null)
{
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel(label);
Vector3 ret = input;
if (options != null) ret = EditorGUILayout.Vector3Field("", input, options);
else ret = EditorGUILayout.Vector3Field("", input);
EditorGUILayout.EndHorizontal();
return ret;
}
/// <summary>
/// Draws an inline Vector3Field with label.
/// </summary>
/// <param name="label">GUIContent to be used as the label.</param>
/// <param name="input">Initial Vector3 input for this field.</param>
/// <param name="options">GUILayoutOption parameters<</param>
/// <returns>Vector3 value defined by this inspector field.</returns>
/// <see href="https://docs.unity3d.com/ScriptReference/EditorGUILayout.Vector3Field.html">EditorGUILayout.Vector3Field</see>
public static Vector3 Vector3Field(GUIContent label, Vector3 input, GUILayoutOption[] options = null)
{
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel(label);
Vector3 ret = input;
if (options != null) ret = EditorGUILayout.Vector3Field("", input, options);
else ret = EditorGUILayout.Vector3Field("", input);
EditorGUILayout.EndHorizontal();
return ret;
}
}
Hi folks! Today I’ve been building out some editors, and felt like sharing something useful. The following snippet is a function that draws a tabbed toolbar. Useful for custom editors and inspectors!
public static int Toolbar(int value, string[] strings, int width = -1) => (width == -1) ? GUILayout.Toolbar(value, strings) : GUILayout.Toolbar(value, strings, GUILayout.Width(width));
Suppose we have a custom editor base class with some helper functions in it. It may look like this:
using UnityEngine;
using UnityEditor;
namespace Shadowed.Editors
{
public abstract class ShadowedEditor : Editor
{
private static readonly string[] _exclude = new string[] { "m_Script" };
public override void OnInspectorGUI()
{
serializedObject.Update();
DrawPropertiesExcluding(serializedObject, _exclude);
serializedObject.ApplyModifiedProperties();
}
private static void GenerateTooltip(string text)
{
var propRect = GUILayoutUtility.GetLastRect();
GUI.Label(propRect, new GUIContent("", text));
}
public static int Toolbar(int value, string[] strings, int width = -1) => (width == -1) ? GUILayout.Toolbar(value, strings) : GUILayout.Toolbar(value, strings, GUILayout.Width(width));
}
}
Now, let’s say we have a MonoBehaviour that has two primary functions – OnUse() and OnAfterUse(). When the object is used, OnUse() is called, which then calls OnAfterUse().
It may look something like this:
using UnityEngine;
using UnityEngine.Events;
namespace Shadowed
{
public class UsableGameObject : MonoBehaviour
{
public AudioSource aud;
public AudioClip OnUseAudio;
public AudioClip OnAfterUseAudio;
public UnityEvent OnUseEvent = new UnityEvent();
public UnityEvent OnAfterUseEvent = new UnityEvent();
public void OnUse()
{
if(aud != null && OnUseAudio != null)
{
aud.clip = OnUseAudio;
aud.Play();
}
OnUseEvent?.Invoke();
OnAfterUse();
}
private void OnAfterUse()
{
if(aud != null && OnAfterUseAudio != null)
{
aud.clip = OnAfterUseAudio;
aud.Play();
}
OnAfterUseEvent?.Invoke();
}
}
}
Before applying a custom inspector, that component looks like this:
UsableGameObject MonoBehaviour without a custom inspector.
Our next step is to make an ‘Editor’ folder if one does not exist. Any scripts in this folder do not get included when your game is built, and execute solely within Unity Editor.
Within the Editor folder, create a new C# script named ‘UsableGameObjectInspector’. Inside the file, your code might look something like this:
using UnityEditor;
using UnityEngine;
namespace Shadowed.Editors
{
[CustomEditor(typeof(UsableGameObject), true)]
public class UsableGameObjectInspector : ShadowedEditor
{
private int currentTab = 0;
private string[] tabStrings = new string[] { "On Use", "On After Use" };
private UsableGameObject t;
public override void OnInspectorGUI()
{
// Get a reference to the current UsableGameObject via type casting.
t = target as UsableGameObject;
// Draws a toolbar using tabStrings[] for the tab names, and keeps track of the active tab using currentTab.
currentTab = Toolbar(currentTab, tabStrings);
// Switch statement to draw the content depending on the selected tab.
switch(currentTab)
{
case 0:
default:
DrawOnUse();
break;
case 1:
DrawAfterUse();
break;
}
}
private void DrawOnUse()
{
// Increase the indent level for this inspector.
EditorGUI.indentLevel++;
// Begin the vertical layout group.
EditorGUILayout.BeginVertical();
// Declare a reference to the OnUseEvent UnityEvent on the selected UsableGameObect.
var e = serializedObject.FindProperty("OnUseEvent");
// Draw a field to display or set the reference above.
EditorGUILayout.PropertyField(e, true);
// Apply any modified data to the game object.
serializedObject.ApplyModifiedProperties();
// Add a space.
EditorGUILayout.Space();
// Begin a horizontal layout group
EditorGUILayout.BeginHorizontal();
// Create the space for a new label with tooltip.
var cLbl = new GUIContent("On Use Audio", "Plays when this Usable Game Object is being used.");
// Draw a field to display or set the OnUseAudio AudioClip on the selected UsableGameObject
t.OnUseAudio = (AudioClip)EditorGUILayout.ObjectField(cLbl, t.OnUseAudio, typeof(AudioClip), true);
// End the horizontal layout group
EditorGUILayout.EndHorizontal();
// End the vertical layout group
EditorGUILayout.EndVertical();
// Decrease the indent level for this inspector.
EditorGUI.indentLevel--;
}
private void DrawAfterUse()
{
// Increase the indent level for this inspector.
EditorGUI.indentLevel++;
// Begin the vertical layout group.
EditorGUILayout.BeginVertical();
// Declare a reference to the OnAfterUseEvent UnityEvent on the selected UsableGameObect.
var e = serializedObject.FindProperty("OnAfterUseEvent");
// Draw a field to display or set the reference above.
EditorGUILayout.PropertyField(e, true);
// Apply any modified data to the game object.
serializedObject.ApplyModifiedProperties();
// Add a space.
EditorGUILayout.Space();
// Begin a horizontal layout group
EditorGUILayout.BeginHorizontal();
// Create the space for a new label with tooltip.
var cLbl = new GUIContent("On After Use Audio", "Plays after this Usable Game Object has being used.");
// Draw a field to display or set the OnAfterUseAudio AudioClip on the selected UsableGameObject
t.OnAfterUseAudio = (AudioClip)EditorGUILayout.ObjectField(cLbl, t.OnAfterUseAudio, typeof(AudioClip), true);
// End the horizontal layout group
EditorGUILayout.EndHorizontal();
// End the vertical layout group
EditorGUILayout.EndVertical();
// Decrease the indent level for this inspector.
EditorGUI.indentLevel--;
}
}
}
After saving this file, your inspector should look like the following image!
I hope you had fun reading this article, and learned something useful!
It has been far too long since RPG Builder 2.0.0 was released, but after a long upgrade process, (we recreated the asset from the ground up!) UMA for RPG Builder 2.0.0 has been submitted to the Unity Asset Store for approval! While you wait, check out the new tutorial video!
Hi guys! I have taken some time to compile a list of some of the tutorial and learning resources I’ve come across for the Unity Engine, amongst other things. We’ll kick it off with the beginner level!
Beginner Unity Tutorials
Brackeys – although now retired, Brackeys YouTube channel remains a source of viable content for the beginner!
Zenva – Zenva Academy has a wide variety of free and paid learning courses for the beginner to intermediate Unity programmer.
CodeMonkey – Code Monkey is an experienced Indie Developer with a heavy focus on 2D tutorials for beginner and intermediate learners.
Intermediate Unity Tutorials
Blackthornprod – Blackthornprod‘s YouTube channel has a lot of really cool tutorials covering all manner of systems for a plethora of games.
Infallible Code – Infallible Code’s videos include a lot of conversations with himself; he asks really good questions – then answers them, accordingly!
LlamAcademy – LlamAcademy has a lot of videos on NavMesh, AI, and an assortment of other topics.
Tarodev – Tarodev has a colorful vocabulary and a lot of knowledge – check him out!
GameDevGuide – Matt from Game Dev Guide is another creator with a breadth of topics and some editor code sprinkled in!
Advanced Unity Tutorials
Dilmer Valecillos – Dilmer Valecillos‘s YouTube channel has a heavy focus on VR and XR programming.
Sebastian Lague – Sebastian Lague‘s channel is the result of an overactive imagination and a lot of brain power. Check this stuff out already!
Sharp Accent – Sharp Accent covers a lot of topics, and quite a few tutorial series for many different game types.
CatLikeCoding – CatLikeCodinghas a ton of shader and intermediate to advance system tutorials on their website.
Unity Shader Graph Tutorials
AETuts – AETuts is a channel covering intermediate and advanced Shader Graph recipes.
Gabriel Aguiar Productions – Gabriel Aguiar‘s YouTube channel focuses on Shader Graph recipes with a huge variety of effects!
Jetelly – Jetelly‘s YouTube channel focuses on the VFX Graph within Unity, and is available en EspaƱol!
Game Development – General
The Game Architect – Adam Millard, The Game Architect‘s YouTube channel covers a vast variety of topics with a smattering of video game industry expertise throughout.
Mental Checkpoint – Mental Checkpoint‘s videos go in depth into tricks, secrets, and all manner of practices within the games industry directly from an industry veteran.
Today I’m going to walk you through how to configure a Linux server to run your Unity Publisher Invoice Verification Discord Bot! This tutorial assumes you already have a Virtual Private Server up and running with Ubuntu 18.04 or later installed.
Step 1: Installing .NET 3.1 SDK
We will begin by installing the Microsoft .NET 3.1 SDK from their repositories, but first, we need to tell the package manager where those repositories are. Let’s do that now. *For newer versions of Ubuntu, make sure you are running a supported distribution by checking the list of supported distributions for .NET 3.1.
Additionally, we will want to install the Screen utility so the bot can run in the background, and ensure the unzip utility is installed so that we can extract the bot from its’ archive.
sudo apt-get install -y screen unzip
Step 2: Extracting and configuring the bot.
Upload the bot to your server using the method of your choice, navigate to the folder in which it is located, and type the following:
unzip ShadowedBot.zip -d ShadowedBot && cd ShadowedBot/
After that, we will need to configure the bot! You will need the following information:
An Application Token from Discord
Your Unity Publisher API Key
Step 2.1: Discord Application Token
Go to the Applications page on the Discord Developer portal.
Press the New Application button.
On the New Application page, enter your bot’s application name in the name field.
Press the Create button.
On the General Information page, under the Settings pane, select Bot.
On the Bot page, add a username and display icon for your bot.
Under Bot Permissions, select Manage Roles underneath General Settings, and Send Messages underneath Text Permissions.
Underneath Username, you will find Token. Click Copy to copy your bot’s token – this is the application token necessary for the bot configuration. Do not lose this!
Copy your API key. This is the apiKey necessary for the bot configuration. Do not lose this either!
Step 2.3: Adjusting the config.json file
Open the config.json file in your favorite text editor (Ours is JOE!) and change your configuration file to include your token, API key, server name, asset name(s), and role(s) to be assigned upon verification. Here’s a sample:
{
"token": "DISCORDAPPLICATIONTOKENFORVERIFICATIONBOT", // Your bot application token from Discord.
"prefix": "!", // The prefix to use for this bot (default: !verify)
"apiKey": "UNITYPUBLISHERAPIKEYFORINVOICEVERIFICATION", // Your Unity Publisher API key!
"serverName": "Shadowed Souls Studios", // The name of your Discord server (example: Official Unity Discord)
"assetRoles": { // A dictionary containing the full name of your asset and the Discord role to assign.
"UMA Add-On for RPG Builder":"UMA Verified",
"TOP_SECRET":"COMING_SOON"
}
}
Step 3: Run the bot!
We will use the Linux Screen utility to help keep the bot running in the background. This will require you to send keyboard commands through your terminal if remotely connected, and will be denoted with an asterisk (*) when necessary.
Type the following commands into your terminal!
screen -S shadowedbot
dotnet ShadowedBot.dll
*CTRL+A+D (this releases the window into the background!)
And that’s it! If you followed these steps, you should be up and running! To verify an invoice, simply message the bot with the following command: