Gamasutra is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Gamasutra: The Art & Business of Making Gamesspacer
View All     RSS
October 19, 2020
arrowPress Releases







If you enjoy reading this site, you might also want to check out these UBM Tech sites:


 

Light Baking Automation in Unity 5

by Tino van der Kraan on 11/05/15 01:38:00 pm   Featured Blogs

7 comments Share on Twitter    RSS

The following blog post, unless otherwise noted, was written by a member of Gamasutra’s community.
The thoughts and opinions expressed are those of the writer and not Gamasutra or its parent company.

 

[As posted http://sassybot.com/blog/light-baking-automation-in-unity-5/]

Hello! Let's talk about light baking in Unity 5 and automating the baking process.

We have all been there. Staring at a progress bar assuming that it must be done soon just to discover that it was nowhere near finished by the time that the process is finally done. You look at the clock and scold yourself for wasting time you could have spent catching up on sleep.

Light baking can take a lot of time. Generally these processes are offloaded using different computers or are done overnight but it usually requires someone to press a few buttons every now and then to move things along. In an attempt to get more baking done with less management, I created a simple script that takes care of this for any number of scenes you throw at it.

The idea is pretty simple. Tell Unity which scenes need to be baked and set it to bake. Below you can see an example of how it works.

The script takes care of pressing the bake button for every scene in the list you give it, and it will save the scene when done with the bake before moving to the next. While doing this, it reports on its progress with the amount of time taken per bake and at what time each bake finished.

1) Create an Editor folder at the root of your Unity project and create a new C# script called BakeScenes

2) Copy and paste the code below into the Bake Scenes script using a text editor of your choice

using System.IO;
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;

public class BakeScenes : EditorWindow
{
    // Array to store an Object array of the scenes
    public Object[] scenes;

    // Lists and string array for easier management
    List sceneList = new List();
    private int sceneIndex = 0;
    private string[] scenePath;

    // Editor text
    string bakeButton = "Bake";
    string status = "Idle...";
    System.DateTime timeStamp;

    // Menu entry
    [MenuItem("Tools/Bake Scenes")]
    public static void ShowWindow()
    {
        EditorWindow window = GetWindow(typeof(BakeScenes), false, "Bake Scenes");
        window.autoRepaintOnSceneChange = true;
    }

    // Refresh the editor text when in focus
    void OnFocus()
    {
        status = "Idle...";
        if (!Lightmapping.isRunning)
        {
            bakeButton = "Bake";
        }
    }

    void OnGUI()
    {
        // "target" can be any class derrived from ScriptableObject 
        // (could be EditorWindow, MonoBehaviour, etc)
        ScriptableObject target = this;
        SerializedObject so = new SerializedObject(target);
        SerializedProperty scenesProperty = so.FindProperty("scenes");

        EditorGUILayout.PropertyField(scenesProperty, true); // True means show children
        so.ApplyModifiedProperties(); // Remember to apply modified properties

        if (GUILayout.Button(bakeButton)) // Button to start bake process
        {
            InitializeBake();
        }
        EditorGUILayout.LabelField("Status: ", status);
        so.Update();
    }

    // If not baking, set delegates, set scenes, and start baking.
    // Otherwise, stop lightmapping and update editor text
    void InitializeBake()
    {
        if (!Lightmapping.isRunning)
        {
            Lightmapping.completed = null;
            Lightmapping.completed = SaveScene;
            Lightmapping.completed += BakeNewScene;
            SetScenes();
            BakeNewScene();
        }
        else
        {
            Lightmapping.Cancel();
            UpdateBakeProgress();
        }
    }

    // Create a string array of scenes to bake
    private bool SetScenes()
    {
        // Reset values
        sceneList.Clear();
        sceneIndex = 0;

        // Get paths for scenes and store in list
        if (scenes.Length == 0)
        {
            status = "No scenes found";
            bakeButton = "Bake";
            return false;
        }
        else
        {
            for (int i = 0; i < scenes.Length; i++)
            {
                sceneList.Add(AssetDatabase.GetAssetPath(scenes[i]));
            }

            // Sort and put scene paths in array
            scenePath = sceneList.ToArray();
            return true;
        }
    }

    // Loop through scenes to bake and update on progress
    private void BakeNewScene()
    {
        if (sceneIndex < scenes.Length)
        {
            EditorApplication.OpenScene(scenePath[sceneIndex]);
            timeStamp = System.DateTime.Now;
            Lightmapping.BakeAsync();
            UpdateBakeProgress();
            sceneIndex++;
        }
        else
        {
            DoneBaking("done");
        }
    }

    // Updates baking progress
    private void UpdateBakeProgress()
    {
        if (Lightmapping.isRunning)
        {
            status = "Baking " + (sceneIndex + 1).ToString() +
            " of " + scenes.Length.ToString();
            bakeButton = "Cancel";
        }
        else if (!Lightmapping.isRunning)
        {
            DoneBaking("cancel");
        }
    }

    // Saves the scene at the end of each bake before starting new bake
    private void SaveScene()
    {
        System.TimeSpan bakeSpan = System.DateTime.Now - timeStamp;
        string bakeTime = string.Format("{0:D2}:{1:D2}:{2:D2}",
            bakeSpan.Hours, bakeSpan.Minutes, bakeSpan.Seconds);
        Debug.Log("(" + sceneIndex.ToString() + "/" +
            scenes.Length.ToString() + ") " + "Done baking: " +
            EditorApplication.currentScene + " after " + bakeTime +
            " on " + System.DateTime.Now.ToString());
        EditorApplication.SaveScene();
    }

    // When done baking, update the editor text
    private void DoneBaking(string reason)
    {
        Lightmapping.completed = null;
        sceneList.Clear();
        sceneIndex = 0;

        if (reason == "done")
        {
            status = "Bake is done";
            bakeButton = "Bake";
        }
        else if (reason == "cancel")
        {
            status = "Canceled";
            bakeButton = "Bake";
        }
    }
}

You will now have a Tools menu entry, as can be seen in the first .gif, in the menu bar of Unity where you can open the Bake Scenes window. Just add your scenes, hit bake, and...

Extend your gratitude by giving me a shoutout on Twitter at @Tinovdk or sharing this blog on social media of  your choosing.

Thanks for reading all the way to the end! :)


Related Jobs

Johnson County Community College
Johnson County Community College — Overland Park, Kansas, United States
[10.19.20]

Assistant Professor, Game Development
Insomniac Games
Insomniac Games — Burbank, California, United States
[10.18.20]

Lead Gameplay Programmer
Insomniac Games
Insomniac Games — Burbank, California, United States
[10.18.20]

Lead Engine Programmer
Insomniac Games
Insomniac Games — Burbank, California, United States
[10.18.20]

Graphics Programmer





Loading Comments

loader image