This document is about: QUANTUM 1
SWITCH TO

Creating Unity MonoBehaviours which bake out assets easily

Warning: Will require some custom work on your own end

The first one creates or returns and existing asset, but requires you to do this by hand. This makes the most sense when creating multiple assets as the result of a user setting many values on a single MonoBehaviour.

C#

using Photon.Deterministic;
using UnityEditor;
using UnityEngine;
using System.Reflection;

namespace Quantum
{
    /// <summary>
    /// A generic bakable class, which will be run at bake time
    /// </summary>
    public class QuantumBakable : MonoBehaviour
    {
        public bool baked = false;

    public T FindOrCreateAsset<T, U>( ref string Guid, string bakedAssetPath, bool createAsChild = false )
        where T : AssetBase
        where U : AssetObject, new()
    {
        T newAsset = null;
        if( Guid != null )
        {
            newAsset = UnityDB.FindAsset<T>( Guid );
        }
#if UNITY_EDITOR
        if( newAsset == null )
        {
            newAsset = ScriptableObject.CreateInstance<T>();
            var type = typeof( T );
            FieldInfo[] fieldInfos;
            fieldInfos = type.GetFields( BindingFlags.Public | BindingFlags.Instance );

            foreach( FieldInfo field in fieldInfos )
            {
                if( field.FieldType == typeof( U ) )
                {
                    object link = field.GetValue( newAsset );
                    field.SetValue( newAsset, new U() );
                    link = field.GetValue( newAsset );
                    var guidField = link.GetType().GetProperty( "Guid" );
                    guidField.SetValue( link, GUID.NewGUID() );
                }
            }

            if( createAsChild )
            {
                AssetDatabase.AddObjectToAsset( newAsset, bakedAssetPath );
            }
            else
            {
                AssetDatabase.CreateAsset( newAsset, bakedAssetPath );
            }
            Guid = newAsset.AssetObject.Guid;
        }
#endif
        return newAsset;
    }
        
    public virtual object OnBake( string folderPath, string sceneName, string assetName, UserMapData userMapData, string containerAsset = null )
        {
            baked = true;
            return null;
        }
    }
}

However, if you have a 1:1 Unity component : Quantum Asset relationship, something like this might be more useful:

C#

using Photon.Deterministic;
using UnityEditor;
using UnityEngine;
using System.Reflection;

namespace Quantum
{
    /// <summary>
    /// A specialized baking class that will produce an asset with an initialized Settings type
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <typeparam name="U"></typeparam>
    public class QuantumAssetBaker<T,U> : QuantumBakable
    where T : AssetBase
    where U : AssetObject, new()
    {
        // TODO: Make the backing fields automatic in editor
        //[HideInInspector]
        public U Settings;

        
        private T m_bakedAssetCache;
        public T FindOrCreateAsset(ref string Guid, string assetPath, bool createAsChild = false) {
            T asset = FindOrCreateAsset<T, U>(ref Guid, assetPath, createAsChild);
            m_bakedAssetCache = asset;
            return asset;
        }

        public string DefaultBakePath(string folderPath, string sceneName, string assetName, string objectName ) {
            string bakedAssetPath = System.IO.Path.Combine(folderPath, sceneName + "_" + assetName + "_" + objectName + ".asset");
            return bakedAssetPath;
        }
    }
}

Example Usage:

C#

using UnityEngine;
using Quantum;
using Photon.Deterministic;
using UnityEditor;

public class NetworkTerminalUnity : QuantumAssetBaker<NetworkTerminalAsset, NetworkTerminal>
{
    public NetworkTerminalLink Terminal;

    public FP radius;

    public override object OnBake( string folderPath, string sceneName, string assetName, UserMapData userMapData, string parentAssetPath = null )
    {
        base.OnBake( folderPath, sceneName, assetName, userMapData );

        string terminalPath = System.IO.Path.Combine( folderPath, sceneName + "_" + assetName + "_" + name + "_Terminal.asset" );

        var position = transform.TransformPoint(Vector3.zero);
        var rotation = transform.rotation.eulerAngles.z;
        NetworkTerminalAsset newTerminalAsset = FindOrCreateAsset(ref Terminal.Guid, parentAssetPath, true);

        newTerminalAsset.name = sceneName + "_" + assetName + "_" + name + "_Terminal";
        newTerminalAsset.Settings.Name = assetName;
        newTerminalAsset.Settings.Radius = radius;
        newTerminalAsset.Settings.Position = new FPVector2( FP.FromFloat_UNSAFE( position.x ), FP.FromFloat_UNSAFE( position.y ) );

        EditorUtility.SetDirty( newTerminalAsset );

        return newTerminalAsset;
    }

    public void OnDrawGizmosSelected()
    {
        Gizmos.DrawWireSphere( transform.position, radius.AsFloat );
    }
}
Back to top