@longroadhwy asked if the Asset Store had a “Design for sales and success: making integration easy with extensible unity assets” type of document. Since I’m not aware of any, I thought it might be helpful to crowdsource some unofficial suggestions.
I’m particularly interested in your thoughts on the Extensibility section. Frankly the rest is mostly window dressing, but extensibility is a fundamental design factor that has a big impact on how easily customers can integrate your code assets into their projects.
To kick it off:
Follow Unity’s Submission Guidelines for code assets. [hpjohn]
Documentation
Comment your code for automatic documentation generation using a tool such as Doxygen. MonoDevelop and Visual Studio make it easy. Just type “///” above a declaration, and the editor will paste in a template to fill in.
At the very least, declare each class in a separate file, and document the purpose of each one. Ideally, also add comments for each public class, property, and variable declaration.
If the purpose of a serialized variable is not obvious or has caveats, use the [tooltip] attribute for MonoBehaviours and ScriptableObjects that use the default inspector.
Document changes when updating. [hpjohn] Keep a running change log from the very first release of the product. API changes and feature deprecations in particular are critical. [longroadhwy] If upgrading requires the customer to take special steps, point those out in an upgrading document (e.g., upgrading.txt). [syscrusher]
Provide documentation in an open format such as PDF or text that customers can open easily on any platform. [syscrusher]
Offer local installation of documentation. Online documentation is useful but usually only reflects the most current version. If a customer’s project is locked to a particular version of product, the customer should have documentation that matches that version. [longroadhwy]
Explicitly list which platforms were tested with the code asset (e.g., tested with Windows, Mac OS/X, iOS, Android and Linux). Also include appropriate OS version numbers if required. [longroadhwy]
This post also has a good discussion on code asset documentation.
Folders & Files
Put your code asset entirely under one folder when possible. Some exceptions, such as gizmo icons and plugin DLLs, must be in other special folders. Consider putting your scripts in Plugins, or at least make sure they work correct if the user moves them intno Plugins. See Where to Install Your Assets for a comprehensive answer. [based on tips from hippocoder, guavaman, SonicBloomEric, makeshiftwings]
Avoid hard-coded paths whenever possible.
Keep your file metadata consistent. Avoid deleting files and re-adding them by dropping them into the Projects view; this will generate new metadata files.
Put example and supplemental files in a separate folder that customers can delete if they want to strip down their project. Don’t intersperse them with files that are necessary for your product to operate.
If providing precompiled DLLs with the option to import source code from a separate package, bear in mind that MonoBehaviour and ScriptableObject declarations will have different GUIDs in the DLL versus source code. Consider insulating the customer from these GUIDs with wrapper scripts so they can switch between DLL and source without losing script references.
Code Organization
Don’t Repeat Yourself. If you do the same thing twice or more, consider making a static method or class to do it for you. [LaneFox]
Use namespaces! [everyone :)]
Prevent other scripts from breaking your code asset by specifying namespaces explicitly when using common class names. Assume that the customer or another code asset may define a common class name in the global namespace. For example, your code may have a “using UnityEngine.UI” statement and then declare a Button variable that’s implicitly in the UnityEngine.UI namespace. However, if the customer defines a Button class in the global namespace, your code will break if it tries to reference the wrong Button type. New Unity users will often define their own classes with these names in the global namespace, which will break your asset unless you specify the correct namespace: Text, Button, Camera, Action.
If you don’t want to litter your code with explicit UnityEngine.UI.Button’s, declare it explicitly in your using section: “using Button = UnityEngine.UI.Button;”. [flaminghairball] Or put your using statements inside your namespace declaration. This will override any classes of the same name in the global namespace: [guavaman]
using UnityEngine;
namespace MyNamespace {
// These will take precedence over any global classes or any classes inside using statements that are outside the namespace declaration.
using MyOtherNamespace;
using UnityEngine.UI;
...
Consider providing helper classes to simplify the customer’s access to the API.
Don’t use shader keywords in shaders or materials unless you really, really need them, due to Unity’s hardcoded limit. [makeshiftwings]
And fix all compiler warnings. [makeshiftwings] Your asset should compile in all supported versions of Unity without any warnings.
Extensibility
Support extensibility without requiring the customer to directly modify source code, since changes will be lost when the customer updates to a new version of the code asset. (It can also be a support nightmare to provide technical support for scripts that customers have been forced to modify and possibly add unintentional side effects.)
Use UnityEvents or the Unity event system, virtual members, C# interfaces, and/or C# events and delegates to make your product extensible.
Consider making Awake, Start, OnEnable, OnDisable, and OnDestroy methods virtual so subclasses can do extra things in them.
Try to make modules as self-sustaining as possible. [LaneFox] This allows customers to re-use modules or use them in new ways without impacting other modules in your code asset.
Build your asset so it can handle alternative input systems (e.g. InControl, Rewired, etc.). [longroadhwy] It doesn’t have to provide support for these input systems; just don’t make it hard for customers to add support. For example, use a delegate or other kind of abstraction instead of calling Unity’s Input class directly.
Third Party Integration
If your code asset integrates with another product, specify which party maintains the integration and which versions of each are supported by the integration. [longroadhwy]
Debugging, Console, & Error Handling
Do not submit a product to the Asset Store that generates compile-time warnings.
Check Debug.isDebugBuild before logging any debug messages.
Provide an object reference as the second parameter to Debug.Log* methods to make it easier for the customer to identify the source of the message.
Consider adding ample verbose logging to help the customer debug issues and know what’s going on under the hood.
Consider providing an option to turn debug messages on and off, or to specify a desired verbosity level. Don’t clutter the console with info-level messages unless the customer has requested them.
Catch exceptions and handle or report them gracefully. [LaneFox]
Consider using unit testing. [LaneFox]
Coding Style
In the interest of avoiding a religious war, let’s tread lightly on this topic if at all. Please just be consistent within your own code, and be aware of the different styles adopted by Unity and Microsoft – e.g., Unity uses camelCase for public properties, Microsoft uses PascalCase.
Asset Store
As of June 20, 2016, the Asset Store no longer allows duplicate product names. Before submitting to the Asset Store, make sure your chosen name isn’t already taken.
Submit your asset in the right category. If you require a per-seat license, make sure it’s in Editor Extensions.
Only attach asset labels to assets in your package if you think they’ll be helpful to customers using your product. Asset labels are no longer used for searches in the Asset Store. Instead, set the product’s meta data on the publisher page. Here are notes about searches and meta data:
- You do not need to include plurals. They are automatically added to the extent that they are dictionary words.
- Package name is included as keywords.
- Package description is included as keywords.
- Category is included as keyword.
Make sure your support email and web page URL work.