Runtime Editor

Runtime Editor is the set of scripts and prefabs which help you to create scene editor, game level editor or build your own modeling application. It supports drag & drop, undo & redo and selectionapi. To implement user interface and core functions runtime editor use transform-handles, gizmos, save load subsystem and three controls: menu, virtualizing tree view and dock panels.

Out of the box it has six Views:

  • Scene View to manipulate objects in the scene.
  • Hierarchy View for displaying and manipulating the object tree.
  • Project View to manage assets and scenes.
  • Inspector View to display and edit object properties.
  • Console View to display information, warnings and errors.
  • Game View for the game.
  • Add More…

The Runtime Editor has many ready-to-use property and component editors and it is relatively easy to create new ones. “Add Component” drop-down button allows you to add components at runtime. There are also several important dialogs included:

  • Save Scene Dialog.
  • Object Picker.
  • Color Picker.
  • Asset Bundles and Libraries Importer.
  • Manage Projects Dialog.

List of Features

  • Position, Rotation, Scale Handles.
  • Grid, Box Selection, Scene Gizmo.
  • Transform Handles mobile & Google AR Core support.
  • Global & Local coordinates, Local & Center pivot point modes, Vertex & Grid snapping.
  • Gizmos for Colliders, Lights and Audio Sources.
  • Scene navigation, Orthographic & Perspective view.
  • Undo & Redo API.
  • Object selection API.
  • Object life-cycle Events.
  • Play & Edit mode.
  • Configurable Inspector.
  • Component & Material editors.
  • 16 Built-in property editors.
  • Add Component control.
  • Multiple Scenes and Cameras support.
  • Dock Panels & Windows Management.
  • Dialogs, Message Boxes, Confirmations.
  • Easy to extend with new windows.
  • Configurable Main & Context menu.
  • Fast Virtualizing Tree View for Hierarchy and Project windows.
  • Configurable Save & Load subsystem (almost no coding is required).
  • Easy to use Project API.
  • Static Assets, Asset Bundles and Dynamic Assets support.
  • Load assets on demand.
  • Multiple Projects support.

Documentation

Getting started:

Roadmap:

  • HDRP/LWRP support
  • ARCore support
  • Multiple components editing
  • OBJ, PNG Importer
  • Animation Recorder
  • Nodes Editor
  • Object Placement API
12 Likes

This is one of the best unsung tools in the asset store. If promoted heavier, its success would probably skyrocket.

3 Likes

Great tool.

1 Like

Hi Vadim,
yeah finally a support Thread in the Unity Forums :slight_smile:

My question:
I asked some time ago if its possible to save Scenes as Unitypackages or scene Files with your RuntimeEditor to be able to work on the scenes in the Unity Editor, after gamers created own levels with your RuntimeEditor.

Our scenario:
We want gamers to create their own dungeons and levels with your Tool but before adding the created Levels by the Community to the final game, our team should review them in the Unity Editor. After a Review from the Team the levels / scenes are added manually to the officiall game.

I saw that you improved the saving a lot in 1.3. Is this now possible or is only save to file / text still supported?

Cheers
Ronny

Yes it is possible in version 1.3.2

Regards,
Vadim

3064524--230330--LoadScene.png

1 Like

Hi Vadim,

Very good idea this forum

As you did for the 1.2 to 1.3, it would be nice if you put the various improvements between the versions

Good continuation

Jean Michel

1 Like

Hiya, I’ve used this a while back before RTSaveLoad was added and I remember it being pretty useful.

However, since the “Build Resource Map” has been added, this is completely useless to me now. As far as I can tell, build resource map creates an asset in the Resources folder with a reference to every single asset in the entire unity project. Meaning if you’ve got say, a couple of texture libraries or sound effect libraries in your project, they will ALL get included in the build. Or more realistically in my case… unity won’t even let you build, it’ll just crash out.

Oh, and when I click the play button, unity will lock up for a few minutes, climb to about 10gb of ram use, and eventually unfreeze. In an empty scene, with just RuntimeEditor in.

Oh, and if I even select the ResourceMap file in Assets\Battlehub\RTSaveLoad\ResourceMaps, unity will lock up for a few minutes.

Is there a way to use this without RTSaveLoad? Adding a single asset via the “expose to editor” seems to force the whole resource map to be generated, with a counter value in the 6 digit ranges ._.

This is painfully designed - I get the idea behind it, but I don’t think the average user will realise the implications of having a reference held in the Resources folder to every single asset in the project, and for large projects, this causes serious issues

EDIT: Seems there’s a solution to my issues! See Vadim’s reply below, thanks Vadim <3

1 Like

Yep, this is clearly a dealbreaker. Vadim, please confirm if there is a workaround to go without the resource map.

It looks like should be possible to use it without the ResourceMap, but I can’t get it to work. If you delete the origianl ResourceMap, everything breaks. If you don’t add things to the resource map - things don’t seem to instantiate properly? Prefabs instantiated via the RTEditor are losing references to their meshes and stuff, can’t work out why!

Hi Jacob. Thank you for using Runtime Editor :slight_smile:

First of all I have a pretty simple solution for problem

  1. Please import attached package
  2. Open Battlehub\RTSaveLoad\Scripts\Implementation\ResourceMapGen.cs
  3. Add path to folders with objects you are planning to expose to editor. Only objects from these folders (and subfolders) will be added to ResourceMap.
public static readonly string[] AllowedPath = new string[]
{
    //"Assets/"
    "Assets/EditableObjects/"
}
  1. If you don’t want certain objects in scene to be affected by SaveLoad just add PersistentIgnore script to them
  2. Delete old ResourceMap and Build new one using menu
    3080411--231894--upload_2017-5-23_12-42-6.png
    6) Problem should be solved

Also let me explain why I implemented ResourceMap. Consider following script:

using UnityEngine;

public class Test : MonoBehaviour
{
    public Material MaterialReference;
    void Start ()
    {
        Debug.Log(MaterialReference.GetInstanceID());
    }

}
  1. Create Empty GameObject add attach Test script to it
  2. Create new material and drag it to MaterialReference field
    3080411--231895--upload_2017-5-23_12-56-28.png
  3. Enter play mode and check instance id written to console.
  4. Duplicate some prefab or material(I copied MyCube when testing it)
  5. Close and re-open unity editor
  6. Enter play mode again
  7. You should see that instance id written to console is different

At this point I realized that I need to store unique persistent identifiers which are not affected by any changes in project and will remain the same forever. This is why I implemented resource map. But there might be a better way of doing this.

Btw I think that it is possible to create ResourceMap manually just by creating prefab with ResourceGroups referencing required objects. But it is not very convenient…

If you want to get rid of SaveLoad subsystem and use your own implementation please do following:

  1. Remove everything from RTSaveLoad folder except Interface subfolder
    3080411--231902--upload_2017-5-23_13-10-2.png
  2. Comment //#define RT_USE_DEFAULT_IMPLEMENTATION in IProjectManager.cs and PersistentIgnore.cs
  3. Update Dependencies.cs like this:
using UnityEngine;
namespace Battlehub.RTSaveLoad
{
    public static class Dependencies
    {
        public static ISerializer Serializer
        {
            get { return null; }
        }
        public static IStorage Storage
        {
            get { return new FileSystemStorage(Application.persistentDataPath); }
        }
        public static IProject Project
        {
            get { return new Project(); }
        }
        public static IAssetBundleLoader BundleLoader
        {
            get { return new AssetBundleLoader(); }
        }
        public static IProjectManager ProjectManager
        {
            get { return null; }[
        }
        public static ISceneManager SceneManager
        {
           get { return null; }
        }
        public static IRuntimeShaderUtil ShaderUtil
        {
            get { return null; }
        }
    }
}
  1. Save&Load will be disabled and Project window will become invisible but RuntimeEditor should continue to work
  2. Now you could provide your own implementation of IProjectManager, ISceneManager, IRuntimeShaderUtil and ISerializer interfaces.

Also you could avoid using ResourceMap by using DynamicResources instead.
See http://battlehub.net/RuntimeEditorBasics/RuntimeEditorBasics.pdf section: 8.15 HowTo: Add Dynamic Resource.
But DynamicResources is little bit limited because only certain types of objects supported. For example Materials and GameObjects supported but ProceduralMaterial is not supported because it does not have public constructor.

I hope it will help :slight_smile:

Regards,
Vadim

3080411–231887–ResourceMapGen_AllowedPath_1_3_2.unitypackage (6.15 KB)

I get this error in the console when I click the save button in the Runtime Editor:

InvalidOperationException: Dynamic type is not a contract-type: MouseLook

Locate MouseLook type and find it’s usages (find fields in your scripts which have MouseLook type)

If MouseLook is not derived from MonoBehavior you could mark MouseLook as
[ProtoBuf.ProtoContract(ImplicitFields = ProtoBuf.ImplicitFields.AllPublic)]
public struct MouseLook {

If it is derived form MonoBehavior please look through fields of MouseLook and locate custom types and do the same
[ProtoBuf.ProtoContract(ImplicitFields = ProtoBuf.ImplicitFields.AllPublic)]
public class CustomType
{
}

Or ignore fields causing this error either by making them private or by marking them with SerializeIgnore attribute
public class TestScript : MonoBehaviour {
[Battlehub.SerializeIgnore]
public int Test;

Then click Tools->RTSaveLoad->Build Type Model

See http://battlehub.net/RuntimeEditorBasics/RuntimeEditorBasics.pdf page 59 add custom type

Jugged arrays looks like this int**[ ][ ]**. Serializer can’t serialize jugged arrays
To fix it please import attached package. It will ignore these field.
To ignore field manually you could do following:

[Battlehub.SerializeIgnore]
private someType[ ][ ] Array;

If you need to serialize jugged array you could do following:

[ProtoContract(AsReferenceDefault = true, ImplicitFields = ImplicitFields.AllFields)]
public class MyArray
{
public int[ ] Array;
}

public MyArray[ ] m_array;

3083686–232285–RT_Editor_1_3_2_SerializeIgnore.unitypackage (1.59 KB)

Vadim - Thanks a bunch! Looks like a good solution, I’ll give it a go!

An ideal solution would be a way to generate a ResourceMap for set objects and their dependencies easily, not sure how much work that would be to implement! (I probably also shouldn’t have entire sfx / texture libraries in my project that i’m only using a small amount of!)

But this all sounds very reasonably designed actually, thanks! Keep up the good work!

1 Like

Hi Vadim, i want move my objects without your handle, i want move the objects with a simple drag script and arrows key, it is posible to record undo&redo?,
I have tried moving an object via transform but undo&redo not work
thanks

Hi,
try to do following:

using UnityEngine;
using Battlehub.RTCommon;

public class MoveObject : MonoBehaviour
{
    public Transform Target;
    public KeyCode Key = KeyCode.UpArrow;
    void Update ()
    {
        if(Input.GetKeyDown(Key))
        {
            RuntimeUndo.RecordTransform(Target);
        }
        if(Input.GetKey(Key))
        {
            Target.position += Vector3.up * Time.deltaTime;
        }
        if (Input.GetKeyUp(Key))
        {
            RuntimeUndo.RecordTransform(Target);
        }
    }
}
1 Like

Hi Vadim
sorry for such newbie question: How can I adjust the color of the grid and the grid size?

Thank you for such a great asset.
Have you considered other use cases than a level editor e.g. kitchen /furniture planer?
Joerg

Wonderfull
Thanks!

1 Like

Hi Joerg
Right now color of gird is hardcoded,
but you could change it in DrawGrid method in RTHandles/Scripts/RuntimeHandles.cs

private static void DrawGrid(Vector3 cameraPosition, Vector3 gridOffset, float spacing, float alpha ,float fadeDisance)
{
....
            GridMaterial.SetFloat("_FadeDistance", fadeDisance);
            GridMaterial.SetPass(0);

            GL.Begin(GL.LINES);
            Color color = Color.white;
            color.a = 0.1f * alpha;
            GL.Color(color);
....

Grid size depends on camera distance.
To make lines looks bolder you could replace color.a = 0.1f * alpha with color.a = alpha

3089404--232905--upload_2017-5-31_10-26-50.png

I think that some users already use it as furniture planner

Regards,
Vadim

2 Likes

Hi Vadin, it is possible to set different clamps rotation per objects?, i have some object that rotate only 180Âş and others every 90Âş

can use Gizmos with different cameras? i want change from camera one to camera two.

Hi,
if I correctly understand question, here is how you can specify rotation clamps per object. Attach ClampAngles script to required objects and set Angle to desired angle

using Battlehub.RTCommon;
using Battlehub.RTEditor;
using Battlehub.RTHandles;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class ClampAngles : MonoBehaviour {

    public float Angle = 45;
    private const float DefaultAngle = 15;
    static ClampAngles()
    {
        RuntimeSelection.SelectionChanged += OnRuntimeSelectionChanged;
        RuntimeTools.ToolChanged += OnToolChanged;
    }

    private static void OnToolChanged()
    {
        TryUpdateRotationHandle();
    }

    private static void OnRuntimeSelectionChanged(Object[] unselectedObjects)
    {
        TryUpdateRotationHandle();
    }

    private static void TryUpdateRotationHandle()
    {
        if (RuntimeTools.Current != RuntimeTool.Rotate)
        {
            return;
        }

        RotationHandle rotationHandle = RuntimeEditor.Instance.SceneView.HandlesParent.GetComponentInChildren<RotationHandle>(true);
        IEnumerable<ClampAngles> clampAngles = RuntimeSelection.gameObjects.Select(go => go.GetComponent<ClampAngles>());
        if (clampAngles.Any())
        {
            rotationHandle.GridSize = clampAngles.Max(ca => ca.Angle);
        }
        else
        {
            rotationHandle.GridSize = DefaultAngle;
        }
    }
}

Which gizmos you are talking about?
To Draw gizmos with different cameras attach GLCamera script to required cameras

1 Like