19

I just found Unity's script template for C# scripts. To get the script name you write #SCRIPTNAME# so it looks like this:

using UnityEngine; using System.Collections; public class #SCRIPTNAME# : MonoBehaviour { void Start () { } void Update () { } } 

Then it would create the script with the right name, but is there something like #FOLDERNAME# so that I can put it in the right namespace directly when creating the script?

6 Answers 6

18

There is no built-in template variables like #FOLDERNAME#.

According to this post, there are only 3 magic variables.

  • "#NAME#"
  • "#SCRIPTNAME#"
  • "#SCRIPTNAME_LOWER#"

But you can always hook into the creation process of a script and append the namespace yourself using AssetModificationProcessor.

Here is an example that adds some custom data to the created script.

//Assets/Editor/KeywordReplace.cs using UnityEngine; using UnityEditor; using System.Collections; public class KeywordReplace : UnityEditor.AssetModificationProcessor { public static void OnWillCreateAsset ( string path ) { path = path.Replace( ".meta", "" ); int index = path.LastIndexOf( "." ); string file = path.Substring( index ); if ( file != ".cs" && file != ".js" && file != ".boo" ) return; index = Application.dataPath.LastIndexOf( "Assets" ); path = Application.dataPath.Substring( 0, index ) + path; file = System.IO.File.ReadAllText( path ); file = file.Replace( "#CREATIONDATE#", System.DateTime.Now + "" ); file = file.Replace( "#PROJECTNAME#", PlayerSettings.productName ); file = file.Replace( "#SMARTDEVELOPERS#", PlayerSettings.companyName ); System.IO.File.WriteAllText( path, file ); AssetDatabase.Refresh(); } } 
Sign up to request clarification or add additional context in comments.

2 Comments

Inside the 2017 Unity C# template, there is also #NOTRIM#. What is for?
@AlanMattano #NOTRIM# indicates that that line should be left as a blank line when the template is used. 'No Trim', meaning do not trim this blank line.
13

I know it's and old question but in newer versions of Unity you can define a root namespace to be used in the project. You can define the namespace in Edit > Project Settings > Editor > Root Namespace

Doing this will add the defined namespace on newly created scripts.

1 Comment

You can also add the namespace to the assembly you want to use, and all newly created files inside this assembly will have the assembly namespace
8

Using zwcloud's answer and some other resources I was able to generate a namespace on my script files:

First step, navigate:

Unity's default templates can be found under your Unity installation's directory in Editor\Data\Resources\ScriptTemplates for Windows and /Contents/Resources/ScriptTemplates for OSX.

And open the file 81-C# Script-NewBehaviourScript.cs.txt

And make the following change:

namespace #NAMESPACE# { 

At the top and

} 

At the bottom. Indent the rest so that the whitespace is as desired. Don't save this just yet. If you wish, you can make other changes to the template, such as removing the default comments, making Update() and Start() private, or even removing them entirely.

Again, do not save this file yet or Unity will throw an error on the next step. If you saved, just hit ctrl-Z to undo and then resave, then ctrl-Y to re-apply the changes.

Now create a new script inside an Editor folder inside your Unity Assets directory and call it AddNameSpace. Replace the contents with this:

using UnityEngine; using UnityEditor; public class AddNameSpace : UnityEditor.AssetModificationProcessor { public static void OnWillCreateAsset(string path) { path = path.Replace(".meta", ""); int index = path.LastIndexOf("."); if(index < 0) return; string file = path.Substring(index); if(file != ".cs" && file != ".js" && file != ".boo") return; index = Application.dataPath.LastIndexOf("Assets"); path = Application.dataPath.Substring(0, index) + path; file = System.IO.File.ReadAllText(path); string lastPart = path.Substring(path.IndexOf("Assets")); string _namespace = lastPart.Substring(0, lastPart.LastIndexOf('/')); _namespace = _namespace.Replace('/', '.'); file = file.Replace("#NAMESPACE#", _namespace); System.IO.File.WriteAllText(path, file); AssetDatabase.Refresh(); } } 

Save this script as well as saving the changes to 81-C# Script-NewBehaviourScript.cs.txt

And you're done! You can test it by creating a new C# script inside any series of folders inside Assets and it will generate the new namespace definition we created.

Comments

6

I'm well aware that this question has been answered by the awesome people (zwcloud, Darco18 and Alexey). However, since my namespace organization follows the folder structure in the project, I've put together in a jiffy some minor modification to the code, and I'm sharing it here in case someone needs it and has the same organizational methodology which I'm following.

Please keep in mind that you need to set the root namespace in your project settings in the C# project generation section. EDIT: I've adjusted the code a bit work with placement in the root folders of Scripts, Editor, etc..

public class NamespaceResolver : UnityEditor.AssetModificationProcessor { public static void OnWillCreateAsset(string metaFilePath) { var fileName = Path.GetFileNameWithoutExtension(metaFilePath); if (!fileName.EndsWith(".cs")) return; var actualFile = $"{Path.GetDirectoryName(metaFilePath)}\\{fileName}"; var segmentedPath = $"{Path.GetDirectoryName(metaFilePath)}".Split(new[] { '\\' }, StringSplitOptions.None); var generatedNamespace = ""; var finalNamespace = ""; // In case of placing the class at the root of a folder such as (Editor, Scripts, etc...) if (segmentedPath.Length <= 2) finalNamespace = EditorSettings.projectGenerationRootNamespace; else { // Skipping the Assets folder and a single subfolder (i.e. Scripts, Editor, Plugins, etc...) for (var i = 2; i < segmentedPath.Length; i++) { generatedNamespace += i == segmentedPath.Length - 1 ? segmentedPath[i] : segmentedPath[i] + "."; // Don't add '.' at the end of the namespace } finalNamespace = EditorSettings.projectGenerationRootNamespace + "." + generatedNamespace; } var content = File.ReadAllText(actualFile); var newContent = content.Replace("#NAMESPACE#", finalNamespace); if (content != newContent) { File.WriteAllText(actualFile, newContent); AssetDatabase.Refresh(); } } } 

Comments

3

OK, so this question was already answered by two wonderful people, zwcloud and Draco18s, and their solution works, I'm just showing another version of the same code that, I hope, will be a little more clear in terms of what exactly happening.

Quick notes:

  • Yes, in this method we are getting not the actual file path, but the path of its meta file as a parameter

  • No, you can not use AssetModificationProcessor without UnityEditor prefix, it is deprecated

  • OnWillCreateAsset method is not shown via Ctrl+Shift+M, 'override' typing or base class metadata

_

using UnityEditor; using System.IO; public class ScriptTemplateKeywordReplacer : UnityEditor.AssetModificationProcessor { //If there would be more than one keyword to replace, add a Dictionary public static void OnWillCreateAsset(string metaFilePath) { string fileName = Path.GetFileNameWithoutExtension(metaFilePath); if (!fileName.EndsWith(".cs")) return; string actualFilePath = $"{Path.GetDirectoryName(metaFilePath)}{Path.DirectorySeparatorChar}{fileName}"; string content = File.ReadAllText(actualFilePath); string newcontent = content.Replace("#PROJECTNAME#", PlayerSettings.productName); if (content != newcontent) { File.WriteAllText(actualFilePath, newcontent); AssetDatabase.Refresh(); } } } 

And this is the contents of my file c:\Program Files\Unity\Editor\Data\Resources\ScriptTemplates\81-C# Script-NewBehaviourScript.cs.txt

using UnityEngine; namespace #PROJECTNAME# { public class #SCRIPTNAME# : MonoBehaviour { // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { } } } 

Comments

0

Here is my solution, in my case Unity added the root namespace right before OnWillCreateAsset(), so I had to replace the root namespace in the script with the one I want.

Here is the code

public class AddNameSpace : UnityEditor.AssetModificationProcessor { public static void OnWillCreateAsset(string path) { var rootNamespace = string.IsNullOrWhiteSpace(EditorSettings.projectGenerationRootNamespace) ? string.Empty : $"{EditorSettings.projectGenerationRootNamespace}"; path = path.Replace(".meta", ""); int index = path.LastIndexOf("."); if (index < 0) return; string file = path.Substring(index); if (file != ".cs" && file != ".js" && file != ".boo") return; string formattedNamespace = GetNamespace(path, rootNamespace); file = System.IO.File.ReadAllText(path); if (file.Contains(formattedNamespace)) return; file = file.Replace(rootNamespace, formattedNamespace); System.IO.File.WriteAllText(path, file); AssetDatabase.Refresh(); } private static string GetNamespace(string filePath, string rootNamespace) { filePath = filePath.Replace("Assets/Scripts/", "/") .Replace('/', '.') .Replace(' '.ToString(), string.Empty); var splitPath = filePath.Split('.'); string pathWithoutFileName = string.Empty; for (int i = 1; i < splitPath.Length - 2; i++) { if (i == splitPath.Length - 3) { pathWithoutFileName += splitPath[i]; } else { pathWithoutFileName += splitPath[i] + '.'; } } return $"{rootNamespace}.{pathWithoutFileName}"; } 

}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.