Code Snippet: In-Line Vector3Field for Editors

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;
    }
}

Using this code is easy, here’s how we call it:

Vector3 tmpVector = EditorUtilities.Vector3Field("Position:", referenceValue);
if(tmpVector != referenceValue) referenceValue = tmpVector;

Hope you found this useful!

ShadowBox: Icon Studio [v1.1.0 – Released!]

ShadowBox: Icon Studio v1.1.0 has been released and is available now on the Unity Asset Store! This update adds the option to create solid colored icons, perfect for creating UI elements.

ShadowBox: Icon Studio gives you the power to create 1:1 icons from any game object in your project! Whether you need UI icons, icons with transparent backgrounds, frames, overlays, or icons with fancy backgrounds, Icon Studio has you covered.

AFS – Ultimate Workshops and Crafting

The ULTIMATE Workshops and Crafting pack has finally arrived! It covers an enormous range of professions and crafting supplies – too many to list! There are stations for enchanters, painters, armor and weapon smiths, woodcutters, farmers, weavers, tinkerers, engineers, leatherworkers, tailors, and so much more!

These pieces are designed to fit in beautifully with the rest of the Aquarius Fantasy Series or any other pack! You can find the demo on Aquarius Max’ Discord, or pick the asset up here: https://www.shadowed.games/maxworkshops

February Update

To begin, our apologies for the lack of updates; we’ve had our noses to the grind stone! The art team has been working hard on the upcoming AFS – Ultimate Workshops and Crafting pack to get it prepared for release.

Meanwhile, I have been working on an entirely new asset – ShadowBox: Game Toolkit. This asset will be the spiritual successor of ShadowBox: Interaction Toolkit, and includes a bevy of new utility modules to enhance your workflow and bring immersion to your games.

Standard modules for ShadowBox: Game Toolkit will include Archivist, Interactions, Menu Master, Stagehand, and UI Toolkit. Here’s a brief rundown on their features.

Archivist: A robust, event driven data serialization manager powered by Odin Serializer. (+U)
Interactions: Add interactive props and game objects to your scenes in moments. (+I)
Menu Master: Easily add graphics quality, audio, and keybind settings to your game(s). (+U)
Stagehand: A powerful scene manager for loading, unloading, and managing scenes in builds.
UI Toolkit: Adds a handful of useful utilities and functionality to Unity’s IMGUI.

These modules will be included in ShadowBox: Game Toolkit by default, to compliment future modules such as Magellan, Fleet Footed, Bag of Holding, Homesteading, Boot Camp, and more!

Stay tuned, folks! We’ve got a lot coming your way.

Legend:
+U – Utility
+I – Immersion

Lunar New Year Mega Bundle

Happy Lunar New Year! To celebrate the Year of the Rabbit, Unity has released another Mega Bundle!

It includes some amazing assets like Skill & Attack Indicators by DTT, SciFi Space Base by Daelonik Artworks, Easy AR : Make Awesome AR Apps Without Coding by Render Island and so much more! With three tiers starting at $29.99, $39.99, and $44.99 USD, you’re saving more per tier than you would if buying these assets individually – up to 95% off the total price at the $44.99 USD tier.

What are you waiting for? Get the Lunar New Year Mega Bundle today!

https://www.shadowed.games/LunarRabbit

ShadowBox: Idle Actions

Level up the immersion in your games with ShadowBox: Idle Actions! Instead of a single idle animation, setting up complex animation controllers, or coding a state machine yourself, let ShadowBox: Idle Actions do the work for you!

ShadowBox: Idle Actions detects when your player or their companions haven’t moved or been interactive, and chooses from a defined list of available Idle Actions to perform. Each idle action has two states; on entering, and on exiting. When entering or exiting an idle state, you can play an animation and/or sound clip, and invoke UnityEvents. Get it on the Unity Asset Store today!

Inspector with Tabbed Toolbar

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.
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!

ShadowBox: Icon Studio

We’re back again, this time with a very useful utility to help you generate icons for your games with a few easy clicks! ShadowBox: Icon Studio enables anyone to create icons of their game objects within seconds.

Want to add an overlay? No problem! Spice up your icons even further by adding a foreground overlay to add layered effects! Need transparency instead? ShadowBox: Icon Studio has you covered, regardless of the style you choose.

Simply enter the studio scene, place your object(s), scale and rotate them into the desired position(s), and let ShadowBox: Icon Studio do the rest. Available now on the Unity Asset Store.

Black Friday Sale!

The Unity Asset Store is kicking off its Black Friday sale early! This year features flash sales for featured assets at 70% off while supplies last! The first set of assets includes the World Building Bundle – 2021 Edition by Procedural Worlds, and The Big Castle Kit by Triplebrick.

World Building Bundle – 2021 Edition by Procedural Worlds includes the following assets: GeNa Pro – Terrains, Villages, Roads & Rivers, Gaia Pro 2021, Ambient Sounds – Interactive Soundscapes, Pegasus, and SECTR COMPLETE 2019. This bundle of world building tools allows you to procedurally generate gorgeous environments with relative ease. Featured in the Intel AI GameDev Toolkit!

The Big Castle Kit by Triplebrick includes everything you need to create a realistic medieval castle environment that makes you feel like you’re really there.

These are accompanied by Atavism X.6 On-Premises and Flat Kit: Toon Shading and Water.

The sale kicks off in a few hours, don’t miss it!