Jump to content
Aveyond Studios Community
Sign in to follow this  
Ant

Tutorial: Create a custom variable

Recommended Posts

In this tutorial, we are going to add a new type of variable to HeroKit called Vector3. You can already use any variable supported by Unity in HeroKit, but this lets you store a Vector3 value on a hero object.

Step 1: Create a list for your variable.

Spoiler

In this tutorial, we are going to create a hero list for Vector3s.

  1. In Unity, open the Project tab.
  2. Expand HeroKit > Hero Engine > Framework > 1. Hero Objects > Data > Hero Lists > Lists.
  3. Right-click on the Lists folder and choose Create > C# Script.
  4. Name your script (ex. Vector3List).
    EDYzG6i.png
  5. Open the script and delete the contents.
  6. Copy and paste the code below into the script. Save your work.

Notes Another alternative to the steps above is to clone the FloatList (that's what I did to create this tutorial), and replace all instances of Float with Vector3, and float with Vector3. Then, rename the cloned script Vector3List.

Vector3List.cs

Spoiler


// --------------------------------------------------------------
// Copyright (c) 2016-2017 Aveyond Studios. 
// All Rights Reserved.
// --------------------------------------------------------------
using System.Collections.Generic;
using System.Linq;
using HeroKit.Editor;
using UnityEngine;

namespace HeroKit.Scene
{
    // A Hero List for vector3 values 
    [System.Serializable]
    public class Vector3List : HeroListObject
    {
        // The list of fields on a hero object
        public List<Vector3Field> items = new List<Vector3Field>();

        // Clone the list, remove references.
        public Vector3List Clone(Vector3List oldList)
        {
            Vector3List tempList = new Vector3List(); 
            List<Vector3Field> tempItems = (oldList == null || oldList.items == null) ? new List<Vector3Field>() : new List<Vector3Field>(oldList.items.Select(x => x.Clone(x)));
            tempList.items = tempItems;
            return tempList;
        }

        // Save the fields in a save game file.
        public Vector3[] Save()
        {
            if (items == null) return null;

            Vector3[] saveItems = new Vector3[items.Count];
            for (int i = 0; i < saveItems.Length; i++)
            {
                saveItems[i] = items[i].Save();
            }

            return saveItems;
        }
    }

    // A Hero List field for a vector3.
    [System.Serializable]
    public class Vector3Field : HeroListObjectField<Vector3>, IHeroListField<Vector3Field>
    {
        public Vector3Field() { }
        public Vector3Field(Vector3Field field)
        {
            name = field.name;
            value = field.value;
        }

        // Clone the field, remove references.
        public Vector3Field Clone(Vector3Field field)
        {
            Vector3Field temp = new Vector3Field();
            temp.name = field.name;
            temp.value = field.value;
            return temp;
        }

        // Get the field to save.
        public Vector3 Save()
        {
            return value;
        }
    }
}

 

 

 

Step 2: Add your list to the Hero List.

Spoiler

The HeroList is a class that is used by all HeroKit variables, globals, and properties. Once you've added your variable list to this class, it will be available in all Hero Objects and Hero Properties. In this example, we are going to add our Vector3 list.

  1. In the Project tab, expand HeroKit > Hero Engine > Framework > 1. Hero Objects > Data > Hero Lists.
  2. Open the C# file called HeroList.
  3. Add the list for your variable (line 45-48).
    
    /// <summary>
    /// List that contains vector3 fields.
    /// </summary>
    public Vector3List vector3s = new Vector3List();

     

  4. Add your vector3 list inside HeroList() (line 62).
    
    public HeroList()
    {
        ints = new IntList();
        floats = new FloatList();
        bools = new BoolList();
        strings = new StringList();
        gameObjects = new GameObjectList();
        heroObjects = new HeroObjectList();
        unityObjects = new UnityObjectList();
        vector3s = new Vector3List ();
    }

     

  5. Add your vector3 list inside HeroList(HeroList list) (line 78).
    
    public HeroList(HeroList list)
    {
        visible = list.visible;
        ints = (list.ints == null) ? new IntList() : list.ints.Clone(list.ints);  
        floats = (list.floats == null) ? new FloatList() : list.floats.Clone(list.floats);
        bools = (list.bools == null) ? new BoolList() : list.bools.Clone(list.bools);
        strings = (list.strings == null) ? new StringList() : list.strings.Clone(list.strings);
        gameObjects = (list.gameObjects == null) ? new GameObjectList() : list.gameObjects.Clone(list.gameObjects);
        heroObjects = (list.heroObjects == null) ? new HeroObjectList() : list.heroObjects.Clone(list.heroObjects);
        unityObjects = (list.unityObjects == null) ? new UnityObjectList() : list.unityObjects.Clone(list.unityObjects);
        vector3s = (list.vector3s == null) ? new Vector3List () : list.vector3s.Clone(list.vector3s);
    }

     

  6. Add your vector3 list inside Clone(HeroList field) (line 97). 
    
    public HeroList Clone(HeroList field)
    {
        HeroList temp = new HeroList();
        temp.visible = field.visible;
        temp.ints = (field.ints == null) ? new IntList() : field.ints.Clone(field.ints);
        temp.floats = (field.floats == null) ? new FloatList() : field.floats.Clone(field.floats);
        temp.bools = (field.bools == null) ? new BoolList() : field.bools.Clone(field.bools);
        temp.strings = (field.strings == null) ? new StringList() : field.strings.Clone(field.strings);
        temp.gameObjects = (field.gameObjects == null) ? new GameObjectList() : field.gameObjects.Clone(field.gameObjects);
        temp.heroObjects = (field.heroObjects == null) ? new HeroObjectList() : field.heroObjects.Clone(field.heroObjects);
        temp.unityObjects = (field.unityObjects == null) ? new UnityObjectList() : field.unityObjects.Clone(field.unityObjects);
        temp.vector3s = (field.vector3s == null) ? new Vector3List() : field.vector3s.Clone(field.vector3s);
        return temp;
    }

     

 

Step 3: Add a layout for your variable field.

Spoiler

When you open a hero object and choose a variable list from the menu on the left, this opens the canvas for the variable list. The canvas contains a list of variable fields (one field per variable). In this tutorial, we are going to create the layout for our Vector3 variable field.

  1. In the Project tab, expand HeroKit > Hero Engine > SimpleGUI > Editor > Fields.
  2. Open the C# file called SimpleGUI.
  3. Add the following code after HeroObjectListField() (line 871-880)
    
    /// <summary>
    /// A field that can contain a vector3 from a Vector3Field object.
    /// </summary>
    public static Vector3 Vector3ListField(Vector3Field vector3Field, int index)
    {
        int bodyWidth = 200;
        int height = 20;
        Vector3 value = vector3Field.value;
        GUIStyle bodyStyle = Fields.TextBox.StyleA;
    
        BeginHorizontal();
        Vector3 result = EditorGUILayout.Vector3Field("", value, GUILayout.Width(bodyWidth), GUILayout.Height(height));
        EndHorizontal();
    
        return result;
    }

     

Step 4: Add a canvas for your list.

Spoiler

When you open a hero object and choose a variable list from the menu on the left, this opens the canvas for the variable list. The canvas is where you give a variable values and a description. In this tutorial, we are going to create a canvas for a Vector3 list.

  1. In the Project tab, expand HeroKit > Hero Engine > Framework > 1. Hero Objects > Editor > Hero Kit Editor > Windows > Canvas Window > Hero Variables.
  2. Right-click on the Hero Variables folder and choose Create > C# Script.
  3. Name your script (ex. Vector3ListBlock).
  4. Open the script and delete the contents.
  5. Copy and paste the code below into the script. Save your work.

Note: Another alternative to the steps above is to clone the FloatListBlock (that's what I did to create this tutorial), and replace all instances of floats with vector3s and Float with Vector3. Then, rename the cloned script Vector3List.

Vector3ListBlock.cs

Spoiler


// --------------------------------------------------------------
// Copyright (c) 2016-2017 Aveyond Studios. 
// All Rights Reserved.
// --------------------------------------------------------------
using HeroKit.Scene;
using SimpleGUI;
using SimpleGUI.Fields;
using System.Collections.Generic;

namespace HeroKit.Editor
{
    /// <summary>
    /// Block for Hero Object variables (Vector3s) that appear in Hero Kit Editor.
    /// </summary>
    internal static class Vector3ListBlock
    {
        // --------------------------------------------------------------
        // Variables
        // --------------------------------------------------------------

        /// <summary>
        /// The hero object.
        /// </summary>
        private static HeroObject heroObject;
        /// <summary>
        /// Name of the block.
        /// </summary>
        private static string blockName = "Vector3";
        /// <summary>
        /// Show the tools menu.
        /// </summary>
        private static bool showTools;
        /// <summary>
        /// List of fields in the Vector3 list.
        /// </summary>
        private static List<Vector3Field> items;
        /// <summary>
        /// List of Vector3 fields that were copied (and can be pasted somewhere).
        /// </summary>
        private static List<Vector3Field> savedFieldList;
        /// <summary>
        /// List of the most recently deleted Vector3 fields.
        /// </summary>
        private static LinkedList<Vector3Field> deletedFields;
        /// <summary>
        /// List of the index values for the most recently deleted Vector3 fields.
        /// The index tells us where the Vector3 field was in the list before it was deleted.
        /// </summary>
        private static LinkedList<int> deletedFieldsIndex;
        /// <summary>
        /// The smallest number of items that can be copied or deleted in a Vector3 list.
        /// </summary>
        private static int rangeBottom;
        /// <summary>
        /// The largest number of items that can be copied or deleted in a Vector3 list.
        /// </summary>
        private static int rangeTop;

        // --------------------------------------------------------------
        // Methods (General)
        // --------------------------------------------------------------

        /// <summary>
        /// Constructor.
        /// </summary>
        static Vector3ListBlock()
        {
            // create deleted field list
            deletedFields = new LinkedList<Vector3Field>();
            deletedFieldsIndex = new LinkedList<int>();
        }
        /// <summary>
        /// Block to display on the canvas. Get list from hero kit object.
        /// </summary>
        /// <param name="heroKitObject">Hero object info to display in the block.</param>
        /// <param name="globals">Display gobal variables instead of local variables?</param>
        public static void Block(HeroObject heroKitObject, bool globals = false)
        {
            // exit early if object is null
            if (heroKitObject == null)
            {
                return;
            }

            // assign hero object to this class
            heroObject = heroKitObject;
            items = (globals) ? HeroKitCommon.GetGlobals().globals.vector3s.items : heroObject.lists.vector3s.items;

            // draw components
            DrawHeader();
            DrawBlock();
        }
        /// <summary>
        /// Block to display on the canvas. Get list from hero kit property.
        /// </summary>
        /// <param name="heroKitObject">Hero object info to display in the block.</param>
        public static void Block(HeroKitProperty heroKitProperty)
        {
            // exit early if object is null
            if (heroKitProperty == null) return;

            // assign hero object to this class
            items = heroKitProperty.properties.vector3s.items;

            // draw components
            DrawHeader();
            DrawBlock();
        }
        /// <summary>
        /// Draw the header of the block.
        /// </summary>
        private static void DrawHeader()
        {
            HeroKitCommon.DrawBlockTitle("Vector3 List");
        }
        /// <summary>
        /// Draw the block.
        /// </summary>
        private static void DrawBlock()
        {
            HeroKitCommon.DrawMenuBar(blockName, addItem, pasteItem, restoreItem, toggleItemTools, showTools);
            DrawTools();
            DrawItems();
        }
        /// <summary>
        /// Draw the body of the block.
        /// </summary>
        private static void DrawItems()
        {
            // exit early if there are no items
            if (items == null || items.Count == 0)
            {
                HeroKitCommon.DrawNoItemsInList(blockName);
                return;
            }

            SimpleLayout.BeginVertical(Box.StyleCanvasBox);

            // display items (move up, move down, int field, 
            for (int i = 0; i < items.Count; i++)
            {
                SimpleLayout.BeginHorizontal();
                HeroKitCommon.DrawListArrows(moveItemUp, moveItemDown, i);
                SimpleLayout.BeginVertical();

                items[i].value = SimpleLayout.Vector3ListField(items[i], i);
                items[i].name = SimpleLayout.StringListField(items[i].name, HeroKitCommon.GetWidthForField(264));

                SimpleLayout.EndVertical();
                HeroKitCommon.DrawListButtons(addItem, copyItem, pasteItem, deleteItem, i);
                SimpleLayout.EndHorizontal();

                if (i != items.Count-1)
                   SimpleLayout.Line();
            }

            SimpleLayout.EndVertical();

            SimpleLayout.Space(20);
        }

        // --------------------------------------------------------------
        // Methods (Tools)
        // --------------------------------------------------------------

        /// <summary>
        /// Draw the tools menu in the block.
        /// </summary>
        private static void DrawTools()
        {
            HeroKitCommon.DrawTools(ref showTools, ref rangeBottom, ref rangeTop, blockName, copyItemRange, pasteItem, deleteItemRange);
        }
        /// <summary>
        /// Show or hide the tools menu.
        /// </summary>
        private static void toggleItemTools()
        {
            showTools = HeroKitCommon.toggleItemTools(showTools);
        }

        // --------------------------------------------------------------
        // Methods (Other)
        // --------------------------------------------------------------

        /// <summary>
        /// Move item up.
        /// </summary>
        /// <param name="index">Move item to this index in the list.</param>
        private static void moveItemUp(int index)
        {
            items = HeroKitCommon.moveItemUp(items, index);
        }
        /// <summary>
        /// Move item down.
        /// </summary>
        /// <param name="index">Move item to this index in the list.</param>
        private static void moveItemDown(int index)
        {
            items = HeroKitCommon.moveItemDown(items, index);
        }

        /// <summary>
        /// Add item at end of list.
        /// </summary>
        private static void addItem()
        {
            HeroKitCommon.addItem(items, new Vector3Field());
        }
        /// <summary>
        /// Add item at specific position in the list.
        /// </summary>
        /// <param name="index">Index in list where item should be added.</param>
        private static void addItem(int index)
        {
            HeroKitCommon.addItem(items, new Vector3Field(), index);
        }

        /// <summary>
        /// Copy an item.
        /// </summary>
        /// <param name="index">Index of item to copy.</param>
        private static void copyItem(int index)
        {
            savedFieldList = HeroKitCommon.copyItem(new Vector3Field(items[index]));
        }
        /// <summary>
        /// Copy a range of items in the list.
        /// </summary>
        /// <param name="start">Start index.</param>
        /// <param name="stop">Stop index.</param>
        private static void copyItemRange(int start, int stop)
        {
            savedFieldList = HeroKitCommon.copyItemRange(items, start, stop);
        }

        /// <summary>
        /// Insert item(s) at the end of the list.
        /// </summary>
        private static void pasteItem()
        {
            // paste at end of list
            items = HeroKitCommon.pasteItem(savedFieldList, items);
        }
        /// <summary>
        /// Insert item(s) at a specific index in the list.
        /// </summary>
        /// <param name="index">The index where the items should be inserted.</param>
        private static void pasteItem(int index)
        {
            // paste at specific location in list
            items = HeroKitCommon.pasteItem(savedFieldList, items, index);
        }

        /// <summary>
        /// Delete item at a specific index in the list.
        /// </summary>
        /// <param name="index">The index of the item.</param>
        private static void deleteItem(int index)
        {
            items = HeroKitCommon.deleteItem(ref deletedFields, ref deletedFieldsIndex, items, index, blockName);
        }
        /// <summary>
        /// Delete a range of items from the list.
        /// </summary>
        /// <param name="start">Index of the first item in the range.</param>
        /// <param name="stop">Index of the last item in the range.</param>
        private static void deleteItemRange(int start, int stop)
        {
            items = HeroKitCommon.deleteItemRange(ref deletedFields, ref deletedFieldsIndex, items, start, stop, blockName);
        }

        /// <summary>
        /// Restor the last item (or range of items) that were deleted from the list.
        /// </summary>
        private static void restoreItem()
        {
            items = HeroKitCommon.restoreItem(ref deletedFields, ref deletedFieldsIndex, items);
        }
    }
}

 

 

Step 5: Add the variable list to the variable menus

Spoiler

There are three variable menus. They are used inside hero objects and hero properties. One of these menus is dedicated to hero properties. One is dedicated to variables in a hero object. One is dedicated to globals in a hero object. 

In this tutorial, we are going to add our Vector3 variables to the variable menus.

  1. In the Project tab, expand HeroKit > Hero Engine > Framework > 1. Hero Objects > Editor > Hero Kit Editor > Windows > Menu Window.
  2. Open the C# file called VariablesMenuBlock.
  3. Add the following code in DrawItems() after line 106.
    
    DrawListItem("Vector3s", 7);
  4. Open the C# file called GlobalsMenuBlock.
  5. Add the following code in DrawItems() after line 106.
    
    DrawListItem("Vector3s", 7);
  6. Open the C# file called HeroPropertyMenuBlock.
  7. Add the following code in DrawItems() after line 73.
    
    DrawListItem("Vector3s", 7);
  8. In the Project tab, expand HeroKit > Hero Engine > Framework > 1. Hero Objects > Editor > Hero Kit Editor.
  9. Open the C# file called HeroKitEditor.
  10. Add the following code after line 305 (variable list).
    
    case 7:
        Vector3ListBlock.Block(heroObject);
        break;
  11. Add the following code after line 339 (global list).
    
    case 7:
        Vector3ListBlock.Block(heroObject, true);
        break;
  12. Add the following code after line 416 (hero properties list).
    
    case 7:
        Vector3ListBlock.Block(heroKitProperty);
        break;

Step 6: Add the variable to hero action

Spoiler

You've successfully created a new variable type. Now you need to find a way to use it with hero actions.

  1. In the Project tab, expand HeroKit > Hero Engine > Framework > 1. Hero Objects > Data > Hero States > Stat3e > Block > Action.
  2. Open the C# file called HeroActionField.
  3. Add the following code after line 53. 
    
    /// <summary>
    /// The vector3s used by the field.
    /// </summary>
    public List<Vector3> vector3s = new List<Vector3>();

     

Step 7: Add a layout for your variable field in an action.

Spoiler

You need to decide what you want your variable field to look like inside an action. In this tutorial, we're going to create a layout for the Vector3 variable.

  1. In the Project tab, expand HeroKit > Hero Engine > Simple GUI > Editor > Fields.
  2. Open the C# script called SimpleGUI.
  3. Add this code after line 610.
    
    /// <summary>
    /// A field that can contain a Vector3.
    /// </summary>
    public static Vector3 Vector3Field(Vector3 fieldValue, int fieldWidth = 100)
    {
        int height = 20;
        Vector3 result = EditorGUILayout.Vector3Field("", fieldValue, GUILayout.Width(fieldWidth), GUILayout.Height(height));
        return result;
    }
     

  Step 8: Add a list that can be populated with your variable values.

Spoiler

You need a way to add your list of variables into a drop-down field in an action. In this example, we are going to create a drop-down list for your Vector3 variables.

  1. In the Project tab, expand HeroKit > Hero Engine > Framework > 3. Hero Actions > Editor > Fields > Drop Down Fields > List Fields.
  2. Right-click on the Hero Variables folder and choose Create > C# Script.
  3. Name your script (ex. Vector3ListField).
  4. Open the script and delete the contents.
  5. Copy and paste the code below into the script. Save your work.
    Spoiler
    
    
    // --------------------------------------------------------------
    // Copyright (c) 2016-2017 Aveyond Studios. 
    // All Rights Reserved.
    // --------------------------------------------------------------
    using HeroKit.Scene;
    using SimpleGUI;
    using System.Collections.Generic;
    using UnityEngine;
    
    namespace HeroKit.Editor.HeroField
    {
        /// <summary>
        /// Drop down list. Get a list of Vector3 fields.
        /// </summary>
        internal static class Vector3ListField
        {
            // create field
            public static SimpleGUI.Fields.DropDownValues field = new SimpleGUI.Fields.DropDownValues();
    
            // assign values to the field [change string values]
            public static void PopulateField( List<Vector3Field> list)
            {
                string name = "Vector3s";
                string[] items = SimpleGUICommon.PopulateDropDownField<Vector3Field, Vector3>(list, "V3:");
                if (items.Length > 0)
                    field.setValues(name, items);
                else
                    field.clearValues();
            }
    
            // pass field into a drop down list [change first value in DropDownList]
            public static int SetValues(List<Vector3Field> list, int theValue, int titleWidth)
            {
                PopulateField(list);   
                int result = SimpleLayout.DropDownList(theValue, field, titleWidth);
                result = (result == 0 && list != null && list.Count != 0) ? 1 : result;
                return result;
            }
    
        }
    }

     


      

  Step 9: Add an action form field for the variable

Spoiler

You've successfully created a new variable. Now you need to find a way to change a value assigned this variable. You need to create form field that can be used in hero actions.

  1. In the Project tab, expand HeroKit > Hero Engine > Framework > 3. Hero Actions > Editor > Fields > Other Fields.
  2. Right-click on the Hero Variables folder and choose Create > C# Script.
  3. Name your script (ex. GetVector3Field).
  4. Open the script and delete the contents.
  5. Copy and paste the code below into the script. Save your work.
    Spoiler
    
    
    // --------------------------------------------------------------
    // Copyright (c) 2016-2017 Aveyond Studios. 
    // All Rights Reserved.
    // --------------------------------------------------------------
    using UnityEngine;
    using HeroKit.Scene;
    using SimpleGUI;
    using System.Collections.Generic;
    using HeroKit.Editor.ActionBlockFields;
    
    namespace HeroKit.Editor.ActionField
    {
        /// <summary>
        /// Action field for the hero kit editor. Work with Vector3 fields.
        /// </summary>
        public static class GetVector3Field
        {
            // --------------------------------------------------------------
            // Action Fields
            // --------------------------------------------------------------
    
            /// <summary>
            /// Get a value from a Vector3 field.
            /// This is for a field that contains Value, Variable, Property, Global.
            /// </summary>
            /// <param name="title">Title for action field.</param>
            /// <param name="actionParams">Action field parameters.</param>
            /// <param name="actionField">Action field.</param>
            /// <param name="titleToLeft">Show the title on the left?</param>
            public static void BuildFieldA(string title, HeroActionParams actionParams, HeroActionField actionField, bool titleToLeft = false, SliderData sliderData = new SliderData())
            {
                // create the fields
                Vector3FieldData data = CreateFieldData(title, actionField, actionParams.heroObject);
    
                //-----------------------------------------
                // Display this title above the field
                //-----------------------------------------
                if (data.title != "" && !titleToLeft) SimpleLayout.Label(data.title);
                SimpleLayout.BeginHorizontal();
                if (data.title != "" && titleToLeft) SimpleLayout.Label(data.title);
    
                //-----------------------------------------
                // Get the type of field you want to work with.
                //-----------------------------------------
                data.fieldType = new HeroField.ValueTypeField().SetValues(data.fieldType, 0);
    
                //-----------------------------------------
                // Get the type of game object we are working with 
                // Option 1: This game object (game object that this hero object is attached to)
                // Option 2: Another game object (another game object in the scene that has a hero object attached to it)
                //-----------------------------------------
                if (data.fieldType == 2 || data.fieldType == 3)
                    data = ActionCommon.GetTargetHeroObject(data);
    
                //-----------------------------------------
                // Get the Vector3 list you want to work with.
                // The Vector3 list is in hero object editor > Variables
                //-----------------------------------------
                
                // if this is a field, draw field (1=number)
                if (data.fieldType == 1)
                {
                    data.fieldValue = SimpleLayout.Vector3Field(data.fieldValue, 149);
                }
    
                // if this is a list, draw vector3s (2=vector3s, 3=properties)
                if (data.fieldType != 1)
                {
                    List<Vector3Field> items = GetItemsFromList(data, -1);
                    data = BuildItemFieldList(data, items);
                }
    
    
                //-----------------------------------------
                // assign values back to hero object fields
                //-----------------------------------------
                actionField.ints[0] = data.objectType;
                actionField.ints[1] = data.objectID;
                actionField.ints[2] = data.fieldID;
                actionField.ints[3] = data.fieldType;
                actionField.ints[4] = data.heroGUID;
                actionField.heroObjects[0] = data.targetHeroObject;
                actionField.strings[0] = data.objectName;
                actionField.vector3s[0] = data.fieldValue;
    
                //-----------------------------------------
                // Visual stuff
                //-----------------------------------------
                SimpleLayout.Space();
                SimpleLayout.EndHorizontal();
            }
    
            /// <summary>
            /// Get a value from a Vector3 field.
            /// This is for a field that contains Variable, Property, Global.
            /// </summary>
            /// <param name="title">Title for action field.</param>
            /// <param name="actionParams">Action field parameters.</param>
            /// <param name="actionField">Action field.</param>
            /// <param name="titleToLeft">Show the title on the left?</param>
            public static void BuildFieldB(string title, HeroActionParams actionParams, HeroActionField actionField, bool titleToLeft = false)
            {
                Vector3FieldData data = CreateFieldData(title, actionField, actionParams.heroObject);
    
                //-----------------------------------------
                // Display this title above the field
                //-----------------------------------------
                if (data.title != "" && !titleToLeft) SimpleLayout.Label(data.title);
                SimpleLayout.BeginHorizontal();
                if (data.title != "" && titleToLeft) SimpleLayout.Label(data.title);
    
                //-----------------------------------------
                // Get the type of field you want to work with.
                //-----------------------------------------
                data.fieldType = new HeroField.ValueTypeFieldB().SetValues(data.fieldType, 0);
    
                //-----------------------------------------
                // Get the type of game object we are working with 
                // Option 1: This game object 
                // Option 2: Another game object in the Game Object list attached to this game object
                // Option 3: Another game object in the scene
                //-----------------------------------------  
                if (data.fieldType == 1 || data.fieldType == 2)
                    data = ActionCommon.GetTargetHeroObject(data);
    
                //-----------------------------------------
                // Get the Vector3 list you want to work with.
                // The Vector3 list is in hero object editor > Variables
                //-----------------------------------------
                List<Vector3Field> items = GetItemsFromList(data);
                data = BuildItemFieldList(data, items);
    
                //-----------------------------------------
                // assign values back to hero object fields
                //-----------------------------------------
                actionField.heroObjects[0] = data.targetHeroObject;
                actionField.ints[0] = data.objectType;
                actionField.ints[1] = data.objectID;
                actionField.ints[2] = data.fieldID;
                actionField.ints[3] = data.fieldType;
                actionField.ints[4] = data.heroGUID;            
                actionField.strings[0] = data.objectName;
                actionField.vector3s[0] = data.fieldValue;
    
                //-----------------------------------------
                // Visual stuff
                //-----------------------------------------
                SimpleLayout.Space();
                SimpleLayout.EndHorizontal();
            }
    
            /// <summary>
            /// Get a value from a Vector3 field in a hero object template.
            /// This is for a field that contains Variable, Property, Global.
            /// </summary>
            /// <param name="title">Title for action field.</param>
            /// <param name="actionParams">Action field parameters.</param>
            /// <param name="actionField">Action field.</param>
            /// <param name="heroObject">Hero object that is the target of this action.</param>
            /// <param name="titleToLeft">Show the title on the left?</param>
            public static void BuildFieldC(string title, HeroActionParams actionParams, HeroActionField actionField, HeroObject heroObject, bool titleToLeft = false)
            {
                Vector3FieldData data = CreateFieldData(title, actionField, actionParams.heroObject);
    
                //-----------------------------------------
                // Display this title above the field
                //-----------------------------------------
                if (data.title != "" && !titleToLeft) SimpleLayout.Label(data.title);
                SimpleLayout.BeginHorizontal();
                if (data.title != "" && titleToLeft) SimpleLayout.Label(data.title);
    
                //-----------------------------------------
                // Get the type of field you want to work with.
                //-----------------------------------------
                data.fieldType = new HeroField.ValueTypeFieldB().SetValues(data.fieldType, 0);
    
                //-----------------------------------------
                // Get the type of game object we are working with 
                // Option 1: This game object 
                // Option 2: Another game object in the Game Object list attached to this game object
                // Option 3: Another game object in the scene
                //-----------------------------------------          
                data.targetHeroObject = heroObject;
    
                //-----------------------------------------
                // Get the Vector3 list you want to work with.
                // The Vector3 list is in hero object editor > Variables
                //-----------------------------------------
                List<Vector3Field> items = GetItemsFromList(data);
                data = BuildItemFieldList(data, items);
    
                //-----------------------------------------
                // assign values back to hero object fields
                //-----------------------------------------
                actionField.heroObjects[0] = data.targetHeroObject;
                actionField.ints[0] = data.objectType;
                actionField.ints[1] = data.objectID;
                actionField.ints[2] = data.fieldID;
                actionField.ints[3] = data.fieldType;
                actionField.ints[4] = data.heroGUID;
                actionField.strings[0] = data.objectName;
                actionField.vector3s[0] = data.fieldValue;
    
                //-----------------------------------------
                // Visual stuff
                //-----------------------------------------
                SimpleLayout.Space();
                SimpleLayout.EndHorizontal();
            }
    
            // --------------------------------------------------------------
            // Helpers
            // --------------------------------------------------------------
    
            /// <summary>
            /// Get a list of Vector3 fields.
            /// </summary>
            /// <param name="data">Current data for this action field.</param>
            /// <param name="indexShift">Make sure we are using the correct field type.</param>
            /// <returns>A list of Vector3 fields.</returns>
            private static List<Vector3Field> GetItemsFromList(Vector3FieldData data, int indexShift=0)
            {
                List<Vector3Field> items = new List<Vector3Field>();
                int fieldType = data.fieldType + indexShift;
    
                // Local Variable
                if (fieldType == 1 && data.targetHeroObject != null)
                {
                    items = data.targetHeroObject.lists.vector3s.items;
                }
    
                // Property
                else if (fieldType == 2 && data.targetHeroObject != null)
                {
                    items = data.targetHeroObject.properties.itemProperties.vector3s.items;
                }
    
                // Global Variable
                else if (fieldType == 3)
                {
                    items = HeroKitCommon.GetGlobals().globals.vector3s.items;
                }
    
                return items;
            }
    
            /// <summary>
            /// Create a drop-down list of Vector3 fields in the action field.
            /// </summary>
            /// <param name="data">Current data for this action field.</param>
            /// <param name="items">A list of Vector3 fields.</param>
            /// <returns>The data for this action field.</returns>
            private static Vector3FieldData BuildItemFieldList(Vector3FieldData data, List<Vector3Field> items)
            {
                bool drawValues = ActionCommon.InitItemFieldList(ref data, items, "vector3s");
    
                if (drawValues)
                    data.fieldID = HeroField.Vector3ListField.SetValues(items, data.fieldID, 0);
    
                return data;
            }
    
            // --------------------------------------------------------------
            // Initialize Action Field
            // --------------------------------------------------------------
    
            /// <summary>
            /// Create the subfields that we need for this action field.
            /// </summary>
            /// <param name="title">The title of the action.</param>
            /// <param name="actionField">The action field.</param>
            /// <param name="heroObject">The hero object that contains this action field.</param>
            /// <returns>The data for this action field.</returns>
            private static Vector3FieldData CreateFieldData(string title, HeroActionField actionField, HeroObject heroObject)
            {
                Vector3FieldData data = new Vector3FieldData();
                data.Init(ref actionField);
                data.title = title;
                data.heroObject = heroObject;
                data.targetHeroObject = actionField.heroObjects[0];
                data.objectType = actionField.ints[0];
                data.objectID = actionField.ints[1];
                data.fieldID = actionField.ints[2];
                data.fieldType = actionField.ints[3];
                data.heroGUID = actionField.ints[4];
                data.objectName = actionField.strings[0];
                data.fieldValue = actionField.vector3s[0];
    
                return data;
            }
        }
    
        /// <summary>
        /// Data needed to use GetVector3Field.
        /// </summary>
        public struct Vector3FieldData : ITargetHeroObject, ITitle
        {
            public void Init(ref HeroActionField actionField)
            {
                ActionCommon.CreateActionField(ref actionField.ints, 7, 0);
                ActionCommon.CreateActionField(ref actionField.heroObjects, 1, null);
                ActionCommon.CreateActionField(ref actionField.strings, 1, "");
                ActionCommon.CreateActionField(ref actionField.bools, 1, false);
                ActionCommon.CreateActionField(ref actionField.vector3s, 1, new Vector3());
            }
    
            public string title { get; set; }
            public HeroObject heroObject { get; set; }
            public HeroObject targetHeroObject { get; set; }
            public int objectType { get; set; }
            public int objectID { get; set; }
            public int fieldType;
            public int fieldID { get; set; }
            public Vector3 fieldValue;
    
            // for a game object in a scene
            public int heroGUID { get; set; }
            public string objectName { get; set; }
            public GameObject gameObject { get; set; }
        }
    }

     

     

  Step 10: Add event that uses data from action form field while game is playing

Spoiler

You've successfully created a variable field that appears inside an action form. Now you need to find a way to use the data inside that form while the game is playing. In this tutorial we create a script that manages this for a Vector3.

  1. In the Project tab, expand HeroKit > Hero Engine > Framework > 3. Hero Actions > Scene > Fields.
  2. Right-click on the Hero Variables folder and choose Create > C# Script.
  3. Name your script (ex. Vector3FieldValue).
  4. Open the script and delete the contents.
  5. Copy and paste the code below into the script. Save your work.
    Spoiler

    // --------------------------------------------------------------
    // Copyright (c) 2016-2017 Aveyond Studios. 
    // All Rights Reserved.
    // --------------------------------------------------------------
    using UnityEngine;

    namespace HeroKit.Scene.ActionField
    {
        /// <summary>
        /// Get or set a value in a Vector3 field.
        /// </summary>
        public static class Vector3FieldValue
        {
            /// <summary>
            /// Get a value from a Vector3 field.
            /// This is for a field that contains Value, Variable, Property, Global.
            /// </summary>
            /// <param name="heroKitObject">The hero kit object that contains the data for this action.</param>
            /// <param name="actionFieldID">ID assigned to action field A.</param>
            /// <returns>The value from a Vector3 field.</returns>
            public static Vector3 GetValueA(HeroKitObject heroKitObject, int actionFieldID)
            {
                // Get the action
                HeroAction action = heroKitObject.heroState.heroEvent[heroKitObject.heroStateData.eventBlock].actions[heroKitObject.heroStateData.action];

                // Get the Vector3 type
                int itemType = action.actionFields[actionFieldID].ints[3];
                Vector3 itemValue = new Vector3();

                // don't get item. Item type was never specified
                if (itemType == 0)
                {
                    Debug.LogError("Vector3 type was never specified for " + action.actionTemplate.name + " " + HeroKitCommonRuntime.GetHeroDebugInfo(heroKitObject));
                    return new Vector3();
                }
                // get Vector3 from field
                else if (itemType == 1)
                {
                    itemValue = action.actionFields[actionFieldID].vector3s[0];
                }
                // get Vector3 from Vector3 field or property field
                else if (itemType == 2 || itemType == 3)
                {
                    // Get the hero kit object
                    HeroKitObject targetHKO = HeroObjectFieldValue.GetTargetHeroObject(heroKitObject, actionFieldID);
                    if (targetHKO == null)
                    {
                        Debug.LogError(HeroKitCommonRuntime.NoHeroKitObjectDebugInfo(action.actionTemplate.name, 0, heroKitObject));
                        return new Vector3();
                    }

                    // Get the slot in the list that contains the Vector3
                    int slotID = action.actionFields[actionFieldID].ints[2] - 1;

                    // Get the Vector3 from Vector3 list
                    if (itemType == 2)
                    {
                        if (targetHKO.heroList.vector3s.items.Count <= slotID)
                        {
                            Debug.LogError(HeroKitCommonRuntime.NoVariableDebugInfo(action.actionTemplate.name, targetHKO.heroObject.name, "Variables", "Vector3", slotID, 0, heroKitObject));
                            return new Vector3();
                        }
                        itemValue = targetHKO.heroList.vector3s.items[slotID].value;
                    }

                    // Get the Vector3 from property list
                    if (itemType == 3)
                    {
                        if (targetHKO.heroProperties.itemProperties.ints.items.Count <= slotID)
                        {
                            Debug.LogError(HeroKitCommonRuntime.NoVariableDebugInfo(action.actionTemplate.name, targetHKO.heroObject.name, "Properties", "Vector3", slotID, 0, heroKitObject));
                            return new Vector3();
                        }
                        itemValue = targetHKO.heroProperties.itemProperties.vector3s.items[slotID].value;
                    }

                }
                // get Vector3 from global field
                else if (itemType == 4)
                {
                    // Get the slot in the list that contains the Vector3
                    int slotID = action.actionFields[actionFieldID].ints[2] - 1;

                    if (HeroKitDatabase.GetGlobals().vector3s.items.Count <= slotID || slotID < 0)
                    {
                        Debug.LogError(HeroKitCommonRuntime.NoVariableDebugInfo(action.actionTemplate.name, "n/a", "Globals", "Vector3", slotID, 0, heroKitObject));
                        return new Vector3();
                    }
                    itemValue = HeroKitDatabase.GetGlobals().vector3s.items[slotID].value;
                }

                // Return the Vector3
                return itemValue;
            }

            /// <summary>
            /// Get a value from a Vector3 field.
            /// This is for a field that contains Variable, Property, Global.
            /// </summary>
            /// <param name="heroKitObject">The hero kit object that contains the data for this action.</param>
            /// <param name="actionFieldID">ID assigned to the action field.</param>
            /// <returns>The value from a Vector3 field.</returns>
            public static Vector3 GetValueB(HeroKitObject heroKitObject, int actionFieldID)
            {
                // Get the action
                HeroAction action = heroKitObject.heroState.heroEvent[heroKitObject.heroStateData.eventBlock].actions[heroKitObject.heroStateData.action];

                // Get the Vector3 type
                int itemType = action.actionFields[actionFieldID].ints[3];
                Vector3 itemValue = new Vector3();

                // don't get item. Item type was never specified
                if (itemType == 0)
                {
                    Debug.LogError("Vector3 type was never specified for " + action.actionTemplate.name + " " + HeroKitCommonRuntime.GetHeroDebugInfo(heroKitObject));
                    return new Vector3();
                }
                // get item from variable or property list
                else if (itemType == 1 || itemType == 2)
                {
                    // Get the hero kit object
                    HeroKitObject targetHKO = HeroObjectFieldValue.GetTargetHeroObject(heroKitObject, actionFieldID);
                    if (targetHKO == null)
                    {
                        Debug.LogError(HeroKitCommonRuntime.NoHeroKitObjectDebugInfo(action.actionTemplate.name, 0, heroKitObject));
                        return new Vector3();
                    }

                    // Get the slot in the list that contains the Vector3
                    int slotID = action.actionFields[actionFieldID].ints[2] - 1;

                    // Get the Vector3 from Vector3 list
                    if (itemType == 1)
                    {
                        if (targetHKO.heroList.vector3s.items.Count <= slotID)
                        {
                            Debug.LogError(HeroKitCommonRuntime.NoVariableDebugInfo(action.actionTemplate.name, targetHKO.heroObject.name, "Variables", "Vector3", slotID, 0, heroKitObject));
                            return new Vector3();
                        }
                        itemValue = targetHKO.heroList.vector3s.items[slotID].value;
                    }

                    // Get the Vector3 from property list
                    if (itemType == 2)
                    {
                        if (targetHKO.heroProperties.itemProperties.ints.items.Count <= slotID)
                        {
                            Debug.LogError(HeroKitCommonRuntime.NoVariableDebugInfo(action.actionTemplate.name, targetHKO.heroObject.name, "Properties", "Vector3", slotID, 0, heroKitObject));
                            return new Vector3();
                        }
                        itemValue = targetHKO.heroProperties.itemProperties.vector3s.items[slotID].value;
                    }
                }
                // get Vector3 from globals
                else if (itemType == 3)
                {
                    // Get the slot in the list that contains the bool
                    int slotID = action.actionFields[actionFieldID].ints[2] - 1;

                    if (HeroKitDatabase.GetGlobals().vector3s.items.Count <= slotID || slotID < 0)
                    {
                        Debug.LogError(HeroKitCommonRuntime.NoVariableDebugInfo(action.actionTemplate.name, "n/a", "Globals", "Vector3", slotID, 0, heroKitObject));
                        return new Vector3();
                    }
                    itemValue = HeroKitDatabase.GetGlobals().vector3s.items[slotID].value;
                }

                // Return the Vector3
                return itemValue;
            }

            /// <summary>
            /// Get a value from a Vector3 field in a hero object template.
            /// This is for a field that contains Variable, Property, Global.
            /// </summary>
            /// <param name="heroKitObject">The hero kit object that contains the data for this action.</param>
            /// <param name="actionFieldID">ID assigned to the action field.</param>
            /// <returns>The value from a Vector3 field.</returns>
            public static Vector3 GetValueC(HeroKitObject heroKitObject, int actionFieldID, HeroObject heroObject)
            {
                // Get the action
                HeroAction action = heroKitObject.heroState.heroEvent[heroKitObject.heroStateData.eventBlock].actions[heroKitObject.heroStateData.action];

                // exit early if object does not exist
                if (heroObject == null)
                {
                    Debug.LogError(HeroKitCommonRuntime.NoHeroObjectDebugInfo(action.actionTemplate.name, 0, heroKitObject));
                    return new Vector3();
                }

                // Get the item type
                int itemType = action.actionFields[actionFieldID].ints[3];
                Vector3 itemValue = new Vector3();

                // Get the slot in the list that contains the item
                int slotID = action.actionFields[actionFieldID].ints[2] - 1;

                // Get the lists
                Vector3List targetList = null;
                string itemTypeName = "";
                string heroName = "";
                if (itemType == 0)
                {
                    Debug.LogError("Vector3 type was never specified for " + action.actionTemplate.name + " " + HeroKitCommonRuntime.GetHeroDebugInfo(heroKitObject));
                    return new Vector3();
                }
                else if (itemType == 1)
                {
                    heroName = heroObject.name;
                    itemTypeName = "Variables";
                    targetList = heroObject.lists.vector3s;
                }
                else if (itemType == 2)
                {
                    heroName = heroObject.name;
                    itemTypeName = "Properties";
                    targetList = heroObject.properties.itemProperties.vector3s;
                }
                else if (itemType == 3)
                {
                    heroName = "n/a";
                    itemTypeName = "Globals";
                    targetList = HeroKitDatabase.GetGlobals().vector3s;
                }

                // exit early if the slot in the list does not exist
                if (targetList.items.Count <= slotID || slotID < 0)
                {
                    Debug.LogError(HeroKitCommonRuntime.NoVariableDebugInfo(action.actionTemplate.name, heroName, itemTypeName, "Vector3", slotID, 0, heroKitObject));
                    return new Vector3();
                }

                // get the item in the list slot
                itemValue = targetList.items[slotID].value;

                // Return the item
                return itemValue;
            }

            /// <summary>
            /// Set the value for a Vector3 in a Vector3 field. 
            /// This is for a field that contains Variable, Property, Global.
            /// </summary>
            /// <param name="heroKitObject">The hero kit object that contains the data for this action.</param>
            /// <param name="actionFieldID">ID assigned to the action field.</param>
            /// <param name="newValue">The new value for a Vector3 field.</param>
            public static void SetValueB(HeroKitObject heroKitObject, int actionFieldID, Vector3 newValue)
            {
                // Get the action
                HeroAction action = heroKitObject.heroState.heroEvent[heroKitObject.heroStateData.eventBlock].actions[heroKitObject.heroStateData.action];

                // Get the Vector3 type
                int itemType = action.actionFields[actionFieldID].ints[3];

                // don't get item. Item type was never specified
                if (itemType == 0)
                {
                    Debug.LogError("Vector3 type was never specified for " + action.actionTemplate.name + " " + HeroKitCommonRuntime.GetHeroDebugInfo(heroKitObject));
                    return;
                }
                // set item in variable or property list
                else if (itemType == 1 || itemType == 2)
                {
                    // Get the hero kit object
                    HeroKitObject[] targetHKO = HeroObjectFieldValue.GetTargetHeroObjects(heroKitObject, actionFieldID);
                    if (targetHKO == null)
                    {
                        Debug.LogError(HeroKitCommonRuntime.NoHeroKitObjectDebugInfo(action.actionTemplate.name, 0, heroKitObject));
                        return;
                    }

                    // Get the slot in the list that contains the Vector3
                    int slotID = action.actionFields[actionFieldID].ints[2] - 1;

                    // Get the Vector3 from the Vector3 list
                    if (itemType == 1)
                    {
                        for (int i = 0; i < targetHKO.Length; i++)
                        {
                            if (targetHKO.heroList.vector3s.items.Count <= slotID)
                            {
                                Debug.LogError("a Vector3 slot assigned to this action no longer exists." + HeroKitCommonRuntime.GetHeroDebugInfo(heroKitObject));
                            }

                            // Set the Vector3
                            targetHKO.heroList.vector3s.items[slotID].value = newValue;
                        }
                    }

                    // Get the Vector3 from the property list
                    if (itemType == 2)
                    {
                        for (int i = 0; i < targetHKO.Length; i++)
                        {
                            if (targetHKO.heroProperties.itemProperties.vector3s.items.Count <= slotID)
                            {
                                Debug.LogError("An property slot assigned to this action no longer exists." + HeroKitCommonRuntime.GetHeroDebugInfo(heroKitObject));
                            }

                            // Set the Vector3
                            targetHKO.heroProperties.itemProperties.vector3s.items[slotID].value = newValue;
                        }
                    }
                }
                // set item in global list
                if (itemType == 3)
                {
                    // Get the slot in the list that contains the item
                    int slotID = action.actionFields[actionFieldID].ints[2] - 1;

                    if (HeroKitDatabase.GetGlobals().vector3s.items.Count <= slotID || slotID < 0)
                    {
                        Debug.LogError(HeroKitCommonRuntime.NoVariableDebugInfo(action.actionTemplate.name, "n/a", "Globals", "Vector3", slotID, 0, heroKitObject));
                        return;
                    }
                    HeroKitDatabase.GetGlobals().vector3s.items[slotID].value = newValue;
                }
            }
        }
    }

      

Step 11: Create an action called Change Vector3

Spoiler

Creating an action is a tutorial of it's own. I've attached a finished action that you can use to change a Vector3. Study the files to understand what is in them. Unzip this anywhere in your project.

Change Vector3.zip

 

Share this post


Link to post
Share on other sites
Sign in to follow this  

×