Skip to content

simple-works/unity-script-generator

Repository files navigation

🧬 Unity Script Generator

Unity C#

Script Generator is a simple Unity package that allows you to generate script files from custom class template files.

It just uses casual C# and Unity API. No mind-blowing external tools or fancy libraries 😁.
You can use this for simple and small script generation, not for sophisticated complex cases.

Installation

  1. Open Unity Package Manager from the main menu under Window > Package Manager.
  2. Open the add + menu in the Package Manager’s toolbar. A menu of options for adding packages should appear.
  3. Select "Add package from git URL". A text box and an Add button should appear.
  4. Enter the Git URL of this repository in the text box and click Add.

💡 How to Install any Unity package from a Git repo URL

Usage

  1. Create an empty C# script file with a name ending with the extension .template.cs. For example MyScript.template.cs.

    💡 If you create a C# script file from Unity's project window, just add .template to the end of its name. Unity will automatically add .cs.

  2. Copy this starter code inside it:

#if false
//----------------------------------------------------------------------------------------------------
// <auto-generated>
//  This code was auto-generated.
//  Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
// </auto-generated>
//----------------------------------------------------------------------------------------------------
using UnityEngine;
namespace MyNamespace
{
    public class MyClass : MonoBehaviour
    {
        //Properties//
        private void MyMethod()
        {
            //MyMethodBody//
        }
    }
}
#endif
//----------------------------------------------------------------------------------------------------
using Ambratolm.ScriptGenerator;
using Ambratolm.ScriptGenerator.Utilities;
using System;
namespace MyNamespace
{
    public class MyClassTemplate : ClassTemplate
    {
        public MyClassTemplate(string text) : base(text)
        {
            for (int i = 0; i < 3; i++)
                AppendLine("//Properties//", $"public string myProperty{i} {{ get; private set; }}");

            AppendLine("//MyMethodBody//", "UnityEngine.Debug("\MyMethod Executed!"\)");  
        }
    }
}
  1. Edit the template and save your changes.

    💡 You can replace #if false with #if true to comfortably edit the template (Visual Studio code editing features enabled) then set it back to #if false when you're done editing it.

    Check the next sections of this document to learn about the class template.

  2. In Unity's project window, right-click on the C# script template file you just created and edited (script with the .template.cs extension) and choose "Generate C# Class" from the contextual menu. A c# script with the same name (but without .template) will be created in the same folder. For example, if you have MyScript.template.cs you will get MyScript.cs in the same folder.

Class-Template File

The class-template file is the file ending with .template.cs. It should contain 2 essential parts:

  1. The class-template code:

    • It is contained between the #if false and #endif lines.
    • It should contain tokens to be replaced with actual code.
    • It is recommended to name tokens like this //MyToken//.
  2. The class-template class definition:

    • It is a class that derives from the type ClassTemplate.
    • It must define a constructor that inherits from the base constructor that requires a string parameter.
    • The constructor body should contain all code responsible for replacing the tokens referenced in the template code.

Class-Template Code

The class-template code should be contained between the #if false and #endif lines:

#if false
// Class-Template Code Here...
#endif

These are just C# preprocessor directives that will prevent the template code from being compiled, as we don't want it to compile and eventually raise errors, but we just use it as a template to generate the actual code we want and want to be able to edit inside Visual Studio so we can benefit from the code editing features rather than having to edit it inside a notepad 😅.

As Visual Studio will grey out the code between #if false and #endif indicating that this code will never be compiled and also disable all code editing features on it (like syntax-highlight and auto-completion, ...etc), You can temporarily replace #if false with #if true to comfortably edit the template then set it back to #if false when you're done with it.

The class-template code should contain tokens to be replaced with actual code. It is recommended to name tokens like this //MyToken//. It's just a fancy comment, you can choose anything to be a token, it doesn't matter, it's just for good practice. As the generation is just a string replacement process where a string (our token) will be replaced with another (our code).

  • Example:

Say we want to generate an Abilities component class that will allow us to access all components of type Ability attached to a game object.

We create our Abilities.template.cs class template file.

This is our class-template code contained in our Abilities.template.cs file:

#if false
using UnityEngine;

namespace Platformer2D
{
    public class Abilities : MonoBehaviour
    {
        //Properties//
        
        private void Awake()
        {
            //AwakeMethodBody//
        }
    }
}
#endif

We will replace the //Properties// token with the Ability components properties, to get this:

public MoveAbility MoveAbility { get; private set; }
public JumpAbility JumpAbility { get; private set; }
public DuckAbility DuckAbility { get; private set; }
public FireAbility FireAbility { get; private set; }

And, we will replace the //AwakeMethodBody// with the initialization of the Ability components properties (with GetComponent()), to get this:

MoveAbility = GetComponent<MoveAbility>();
JumpAbility = GetComponent<JumpAbility>();
DuckAbility = GetComponent<DuckAbility>();
FireAbility = GetComponent<FireAbility>();

Class-Template Class

A class-template class is a class (You don't say 😮) that derives from the ClassTemplate class.

It must define a constructor that inherits from the base constructor that requires a string parameter. The string parameter is the input class template code text that the ClassTemplate class will process to replace its token with the wanted code and generate the output class code, but you don't have to worry much about this parameter usage in your implementation of the class, just leave it like this:

public class MyClassTemplate : ClassTemplate
{
    public MyClassTemplate(string text) : base(text) 
    {
        // Class generation logic here...
    }
}

The constructor body should contain all code responsible for replacing the tokens referenced in the template code. You can of course define whatever you want inside the class like fields, properties and methods that you can reference inside the constructor.

  • Example:

We need to retrieve all types that derive from the Ability type. We can use TypeUtility.GetTypes() for that:

Type[] abilityTypes = TypeUtility.GetTypes(typeof(Ability), nameof(Platformer2D));

To build the string that will replace a token like //Properties// or //AwakeMethodBody//, we can use Append or AppendLine.

With AppendLine we can then create a property in every new line:

foreach (Type abilityType in abilityTypes)
    AppendLine("//Properties//", $"public {abilityType.Name} {abilityType.Name} {{ get; private set; }}");

And, an initialization in every new line inside the Awake method:

foreach (Type abilityType in abilityTypes)
    AppendLine("//AwakeMethodBody//", $"{abilityType.Name} = GetComponent<{abilityType.Name}>();");

This is our class-template class definition contained in our Abilities.template.cs file:

using Ambratolm.ScriptGenerator;
using Ambratolm.ScriptGenerator.Utilities;
using System;

namespace Platformer2D
{
    public class AbilitiesClassTemplate : ClassTemplate
    {
        public AbilitiesClassTemplate(string text) : base(text)
        {
            Type[] abilityTypes = TypeUtility.GetTypes(typeof(Ability), nameof(Platformer2D));

            foreach (Type abilityType in abilityTypes)
                AppendLine("//Properties//", $"public {abilityType.Name} {abilityType.Name} {{ get; private set; }}");

            foreach (Type abilityType in abilityTypes)
                AppendLine("//AwakeMethodBody//", $"{abilityType.Name} = GetComponent<{abilityType.Name}>();");
        }
    }
}

Generated Class

To generate a class file, go to the class template script file (.template.cs file) in Unity's project window and right-click on it, you should see an option in the contextual menu named "Generate C# Class", click it to generate. A c# script with the same name (but without .template) will be created in the same folder.

  • Example:

This is our Abilities generated class contained in the Abilities.cs file generated from our Abilities.template.cs file:

using UnityEngine;

namespace Platformer2D
{
    public class Abilities : MonoBehaviour
    {
        public MoveAbility MoveAbility { get; private set; }
        public JumpAbility JumpAbility { get; private set; }
        public DuckAbility DuckAbility { get; private set; }
        public FireAbility FireAbility { get; private set; }
        
        private void Awake()
        {
            MoveAbility = GetComponent<MoveAbility>();
            JumpAbility = GetComponent<JumpAbility>();
            DuckAbility = GetComponent<DuckAbility>();
            FireAbility = GetComponent<FireAbility>();
        }
    }
}

License

Licensed under MIT.