Instrucciones de codificaciónCoding guidelines

En este documento se describen los principios y convenciones de codificación que se deben seguir al contribuir a MRTK.This document outlines coding principles and conventions to follow when contributing to MRTK.


FilosofíaPhilosophy

Sea conciso y esfuérzate por la simplicidadBe concise and strive for simplicity

La solución más sencilla suele ser la mejor.The simplest solution is often the best. Este es un objetivo reemplazable de estas directrices y debe ser el objetivo de toda la actividad de codificación.This is an overriding aim of these guidelines and should be the goal of all coding activity. Parte de ser simple es ser conciso y coherente con el código existente.Part of being simple is being concise, and consistent with existing code. Intente que el código sea sencillo.Try to keep your code simple.

Los lectores solo deben encontrar artefactos que proporcionen información útil.Readers should only encounter artifacts that provide useful information. Por ejemplo, los comentarios que restablecen lo obvio no proporcionan información adicional y aumentan la proporción de ruido y señal.For example, comments that restate what is obvious provide no extra information and increase the noise to signal ratio.

Mantenga la lógica de código simple.Keep code logic simple. Tenga en cuenta que no se trata de una instrucción sobre cómo usar el menor número de líneas, minimizar el tamaño de los nombres de identificador o el estilo de llaves, sino reducir el número de conceptos y maximizar la visibilidad de las líneas a través de patrones conocidos.Note that this is not a statement about using the fewest number of lines, minimizing the size of identifier names or brace style, but about reducing the number of concepts and maximizing the visibility of those through familiar patterns.

Generar código coherente y legibleProduce consistent, readable code

La legibilidad del código se correlaciona con tasas de defectos bajas.Code readability is correlated with low defect rates. Esfuérzse por crear código que sea fácil de leer.Strive to create code that is easy to read. Esfuérzate por crear código que tenga una lógica simple y vuelva a usar los componentes existentes, ya que también ayudará a garantizar la corrección.Strive to create code that has simple logic and re-uses existing components as it will also help ensure correctness.

Todos los detalles del código que se generan importan, desde los detalles más básicos de la corrección hasta el estilo y el formato coherentes.All details of the code you produce matter, from the most basic detail of correctness to consistent style and formatting. Mantenga el estilo de codificación coherente con lo que ya existe, incluso si no coincide con sus preferencias.Keep your coding style consistent with what already exists, even if it is not matching your preference. Esto aumenta la legibilidad del código base general.This increases the readability of the overall codebase.

Compatibilidad con la configuración de componentes en el editor y en tiempo de ejecuciónSupport configuring components both in editor and at run-time

MRTK admite un conjunto diverso de usuarios: personas que prefieren configurar componentes en el editor de Unity y cargar elementos prefijos, y personas que necesitan crear instancias y configurar objetos en tiempo de ejecución.MRTK supports a diverse set of users – people who prefer to configure components in the Unity editor and load prefabs, and people who need to instantiate and configure objects at run-time.

Todo el código debe funcionar agregando un componente a un GameObject en una escena guardada y mediante la creación de instancias de ese componente en el código.All your code should work by BOTH adding a component to a GameObject in a saved scene, and by instantiating that component in code. Las pruebas deben incluir un caso de prueba tanto para crear instancias previas como para crear instancias, y configurar el componente en tiempo de ejecución.Tests should include a test case both for instantiating prefabs and instantiating, configuring the component at runtime.

Play-in-editor es la primera plataforma de destino principalPlay-in-editor is your first and primary target platform

Play-In-Editor es la manera más rápida de iterar en Unity.Play-In-Editor is the fastest way to iterate in Unity. Proporcionar maneras a nuestros clientes de iterar rápidamente les permite desarrollar soluciones más rápidamente y probar más ideas.Providing ways for our customers to iterate quickly allows them to both develop solutions more quickly and try out more ideas. En otras palabras, maximizar la velocidad de iteración permite a nuestros clientes lograr más.In other words, maximizing the speed of iteration empowers our customers to achieve more.

Haga que todo funcione en el editor y, a continuación, haga que funcione en cualquier otra plataforma.Make everything work in editor, then make it work on any other platform. Siga funcionando en el editor.Keep it working in the editor. Es fácil agregar una nueva plataforma a Play-In-Editor.It is easy to add a new platform to Play-In-Editor. Es muy difícil hacer que Play-In-Editor funcione si la aplicación solo funciona en un dispositivo.It is very difficult to get Play-In-Editor working if your app only works on a device.

Agregar nuevos campos públicos, propiedades, métodos y campos privados serializados con cuidadoAdd new public fields, properties, methods and serialized private fields with care

Cada vez que se agrega un método público, un campo o una propiedad, se convierte en parte de la superficie de API pública de MRTK.Every time you add a public method, field, property, it becomes part of MRTK’s public API surface. Los campos privados marcados con [SerializeField] también exponen campos al editor y forman parte de la superficie de API pública.Private fields marked with [SerializeField] also expose fields to the editor and are part of the public API surface. Otras personas pueden usar ese método público, configurar elementos prefab personalizados con el campo público y tomar una dependencia de él.Other people might use that public method, configure custom prefabs with your public field, and take a dependency on it.

Los nuevos miembros públicos deben examinarse detenidamente.New public members should be carefully examined. Cualquier campo público tendrá que mantenerse en el futuro.Any public field will need to be maintained in the future. Recuerde que si el tipo de un campo público (o campo privado serializado) cambia o se quita de un monobehaviour, esto podría interrumpir a otras personas.Remember that if the type of a public field (or serialized private field) changes or gets removed from a MonoBehaviour, that could break other people. El campo deberá estar en desuso para una versión y es necesario proporcionar código para migrar los cambios de las personas que han tomado dependencias.The field will need to first be deprecated for a release, and code to migrate changes for people that have taken dependencies would need to be provided.

Priorizar la escritura de pruebasPrioritize writing tests

MRTK es un proyecto de la comunidad, modificado por una amplia gama de colaboradores.MRTK is a community project, modified by a diverse range of contributors. Es posible que estos colaboradores no conozcan los detalles de la corrección o característica de errores y que la característica se rompa accidentalmente.These contributors may not know the details of your bug fix / feature, and accidentally break your feature. MRTK ejecuta pruebas de integración continuas antes de completar todas las solicitudes de incorporación de extracción.MRTK runs continuous integration tests before completing every pull request. Los cambios que interrumpirán las pruebas no se pueden comprobar.Changes that break tests cannot be checked in. Por lo tanto, las pruebas son la mejor manera de asegurarse de que otras personas no interrumpirán la característica.Therefore, tests are the best way to ensure that other people do not break your feature.

Cuando corrija un error, escriba una prueba para asegurarse de que no se revierte en el futuro.When you fix a bug, write a test to ensure it does not regress in the future. Si agrega una característica, escriba pruebas que comprueben que la característica funciona.If adding a feature, write tests that verify your feature works. Esto es necesario para todas las características de la experiencia de usuario, excepto las características experimentales.This is required for all UX features except experimental features.

Convenciones de codificación de C#C# Coding conventions

Script de encabezados de información de licenciaScript license information headers

Todos los empleados de Microsoft que contribuyen a nuevos archivos deben agregar el siguiente encabezado de licencia estándar en la parte superior de los archivos nuevos, exactamente como se muestra a continuación:All Microsoft employees contributing new files should add the following standard License header at the top of any new files, exactly as shown below:

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

Encabezados de resumen de función/métodoFunction / method summary headers

Todas las clases públicas, structs, enumeraciones, funciones, propiedades, campos publicados en MRTK deben describirse como su propósito y uso, exactamente como se muestra a continuación:All public classes, structs, enums, functions, properties, fields posted to the MRTK should be described as to its purpose and use, exactly as shown below:

/// <summary>
/// The Controller definition defines the Controller as defined by the SDK / Unity.
/// </summary>
public struct Controller
{
    /// <summary>
    /// The ID assigned to the Controller
    /// </summary>
    public string ID;
}

Esto garantiza que la documentación se genera y se propaga correctamente para todas las clases, métodos y propiedades.This ensures documentation is properly generated and disseminated for all all classes, methods, and properties.

Se rechazarán los archivos de script enviados sin las etiquetas de resumen adecuadas.Any script files submitted without proper summary tags will be rejected.

Reglas de espacio de nombres de MRTKMRTK namespace rules

El Mixed Reality Toolkit un modelo de espacio de nombres basado en características, donde todos los espacios de nombres fundamentales comienzan por "Microsoft.MixedReality. Toolkit".The Mixed Reality Toolkit uses a feature based namespace model, where all foundational namespaces begin with "Microsoft.MixedReality.Toolkit". En general, no es necesario especificar la capa del kit de herramientas (por ejemplo, Core, Providers, Services) en los espacios de nombres.In general, you need not specify the toolkit layer (ex: Core, Providers, Services) in your namespaces.

Los espacios de nombres definidos actualmente son:The currently defined namespaces are:

  • Microsoft.MixedReality. ToolkitMicrosoft.MixedReality.Toolkit
  • Microsoft.MixedReality. Toolkit. LímiteMicrosoft.MixedReality.Toolkit.Boundary
  • Microsoft.MixedReality. Toolkit. DiagnósticoMicrosoft.MixedReality.Toolkit.Diagnostics
  • Microsoft.MixedReality. Toolkit. EditorMicrosoft.MixedReality.Toolkit.Editor
  • Microsoft.MixedReality. Toolkit. EntradaMicrosoft.MixedReality.Toolkit.Input
  • Microsoft.MixedReality. Toolkit. SpatialAwarenessMicrosoft.MixedReality.Toolkit.SpatialAwareness
  • Microsoft.MixedReality. Toolkit. TeleportMicrosoft.MixedReality.Toolkit.Teleport
  • Microsoft.MixedReality. Toolkit. UtilidadesMicrosoft.MixedReality.Toolkit.Utilities

En el caso de los espacios de nombres con una gran cantidad de tipos, es aceptable crear un número limitado de subparátipos de nombres para ayudar a limitar el uso del ámbito.For namespaces with a large amount of types, it is acceptable to create a limited number of sub-namespaces to aid in scoping usage.

Si se omite el espacio de nombres de una interfaz, una clase o un tipo de datos, se bloqueará el cambio.Omitting the namespace for an interface, class or data type will cause your change to be blocked.

Adición de nuevos scripts de MonoBehaviourAdding new MonoBehaviour scripts

Al agregar nuevos scripts MonoBehaviour con una solicitud de incorporación de cambios, asegúrese de que el atributo se aplica a AddComponentMenu todos los archivos aplicables.When adding new MonoBehaviour scripts with a pull request, ensure the AddComponentMenu attribute is applied to all applicable files. Esto garantiza que el componente se pueda detectar fácilmente en el editor en el botón Agregar componente.This ensures the component is easily discoverable in the editor under the Add Component button. La marca de atributo no es necesaria si el componente no se puede mostrar en el editor, como una clase abstracta.The attribute flag is not necessary if the component cannot show up in editor such as an abstract class.

En el ejemplo siguiente, el paquete debe rellenarse con la ubicación del paquete del componente.In the example below, the Package here should be filled with the package location of the component. Si coloca un elemento en la carpeta MRTK/SDK, el paquete será SDK.If placing an item in MRTK/SDK folder, then the package will be SDK.

[AddComponentMenu("Scripts/MRTK/{Package here}/MyNewComponent")]
public class MyNewComponent : MonoBehaviour

Adición de nuevos scripts de inspector de UnityAdding new Unity inspector scripts

En general, intente evitar la creación de scripts de inspector personalizados para los componentes de MRTK.In general, try to avoid creating custom inspector scripts for MRTK components. Agrega sobrecarga adicional y administración del código base que podría controlar el motor de Unity.It adds additional overhead and management of the codebase that could be handled by the Unity engine.

Si se necesita una clase inspectora, intente usar el elemento de DrawDefaultInspector() Unity.If an inspector class is necessary, try to use Unity's DrawDefaultInspector(). Esto simplifica de nuevo la clase inspector y deja gran parte del trabajo a Unity.This again simplifies the inspector class and leaves much of the work to Unity.

public override void OnInspectorGUI()
{
    // Do some custom calculations or checks
    // ....
    DrawDefaultInspector();
}

Si se requiere representación personalizada en la clase inspector, intente utilizar SerializedProperty y EditorGUILayout.PropertyField .If custom rendering is required in the inspector class, try to utilize SerializedProperty and EditorGUILayout.PropertyField. Esto garantizará que Unity controla correctamente la representación de elementos prefabs anidados y valores modificados.This will ensure Unity correctly handles rendering nested prefabs and modified values.

Si no se puede usar debido a un requisito en la lógica personalizada, asegúrese de que todo EditorGUILayout.PropertyField el uso se ajusta alrededor de EditorGUI.PropertyScope .If EditorGUILayout.PropertyField cannot be used due to a requirement in custom logic, ensure all usage is wrapped around a EditorGUI.PropertyScope. Esto garantizará que Unity represente el inspector correctamente para los elementos prefab anidados y los valores modificados con la propiedad dada.This will ensure Unity renders the inspector correctly for nested prefabs and modified values with the given property.

Además, intente decorar la clase de inspector personalizado con CanEditMultipleObjects un .Furthermore, try to decorate the custom inspector class with a CanEditMultipleObjects. Esta etiqueta garantiza que se pueden seleccionar y modificar juntos varios objetos con este componente en la escena.This tag ensure multiple objects with this component in the scene can be selected and modified together. Las nuevas clases de inspector deben probar que su código funciona en esta situación en la escena.Any new inspector classes should test that their code works in this situation in the scene.

    // Example inspector class demonstrating usage of SerializedProperty & EditorGUILayout.PropertyField
    // as well as use of EditorGUI.PropertyScope for custom property logic
    [CustomEditor(typeof(MyComponent))]
    public class MyComponentInspector : UnityEditor.Editor
    {
        private SerializedProperty myProperty;
        private SerializedProperty handedness;

        protected virtual void OnEnable()
        {
            myProperty = serializedObject.FindProperty("myProperty");
            handedness = serializedObject.FindProperty("handedness");
        }

        public override void OnInspectorGUI()
        {
            EditorGUILayout.PropertyField(destroyOnSourceLost);

            Rect position = EditorGUILayout.GetControlRect();
            var label = new GUIContent(handedness.displayName);
            using (new EditorGUI.PropertyScope(position, label, handedness))
            {
                var currentHandedness = (Handedness)handedness.enumValueIndex;

                handedness.enumValueIndex = (int)(Handedness)EditorGUI.EnumPopup(
                    position,
                    label,
                    currentHandedness,
                    (value) => {
                        // This function is executed by Unity to determine if a possible enum value
                        // is valid for selection in the editor view
                        // In this case, only Handedness.Left and Handedness.Right can be selected
                        return (Handedness)value == Handedness.Left
                        || (Handedness)value == Handedness.Right;
                    });
            }
        }
    }

Adición de nuevos objetos ScriptableObjectsAdding new ScriptableObjects

Al agregar nuevos scripts ScriptableObject, asegúrese de CreateAssetMenu que el atributo se aplica a todos los archivos aplicables.When adding new ScriptableObject scripts, ensure the CreateAssetMenu attribute is applied to all applicable files. Esto garantiza que el componente se pueda detectar fácilmente en el editor a través de los menús de creación de recursos.This ensures the component is easily discoverable in the editor via the asset creation menus. La marca de atributo no es necesaria si el componente no se puede mostrar en el editor, como una clase abstracta.The attribute flag is not necessary if the component cannot show up in editor such as an abstract class.

En el ejemplo siguiente, la subcarpeta debe rellenarse con la subcarpeta MRTK, si procede.In the example below, the Subfolder should be filled with the MRTK subfolder, if applicable. Si coloca un elemento en la carpeta MRTK/Providers, el paquete será Providers.If placing an item in MRTK/Providers folder, then the package will be Providers. Si coloca un elemento en la carpeta MRTK/Core, establezca esta opción en "Perfiles".If placing an item in the MRTK/Core folder, set this to "Profiles".

En el ejemplo siguiente, el | MyNewProvider debe rellenarse con el nombre de la nueva clase, si procede.In the example below, the MyNewService | MyNewProvider should be filled with the your new class' name, if applicable. Si coloca un elemento en la carpeta MixedRealityToolkit, deje esta cadena fuera.If placing an item in the MixedRealityToolkit folder, leave this string out.

[CreateAssetMenu(fileName = "MyNewProfile", menuName = "Mixed Reality Toolkit/{Subfolder}/{MyNewService | MyNewProvider}/MyNewProfile")]
public class MyNewProfile : ScriptableObject

RegistroLogging

Al agregar nuevas características o actualizar las características existentes, considere la posibilidad de agregar registros DebugUtilities.LogVerbose a código interesante que puede ser útil para la depuración futura.When adding new features or updating existing features, consider adding DebugUtilities.LogVerbose logs to interesting code that may be useful for future debugging. Aquí hay un equilibrio entre agregar registro y el ruido agregado y no hay suficiente registro (lo que dificulta el diagnóstico).There's a tradeoff here between adding logging and the added noise and not enough logging (which makes diagnosis difficult).

Un ejemplo interesante en el que el registro es útil (junto con una carga útil interesante):An interesting example where having logging is useful (along with interesting payload):

DebugUtilities.LogVerboseFormat("RaiseSourceDetected: Source ID: {0}, Source Type: {1}", source.SourceId, source.SourceType);

Este tipo de registro puede ayudar a detectar problemas como , causados por eventos de origen no https://github.com/microsoft/MixedRealityToolkit-Unity/issues/8016 coincidentes detectados y de pérdida de origen.This type of logging can help catch issues like https://github.com/microsoft/MixedRealityToolkit-Unity/issues/8016, which were caused by mismatched source detected and source lost events.

Evite agregar registros para los datos y eventos que se producen en cada fotograma; idealmente, el registro debe cubrir eventos "interesantes" controlados por distintas entradas de usuario (es decir, un "clic" por parte de un usuario y el conjunto de cambios y eventos que proceden de que son interesantes de registrar).Avoid adding logs for data and events that are occurring on every frame - ideally logging should cover "interesting" events driven by distinct user inputs (i.e. a "click" by a user and the set of changes and events that come from that are interesting to log). El estado continuo de "el usuario sigue manteniendo un gesto" registrado en cada fotograma no es interesante y sobrecargará los registros.The ongoing state of "user is still holding a gesture" logged every frame is not interesting and will overwhelm the logs.

Tenga en cuenta que este registro detallado no está activado de forma predeterminada (debe estar habilitado en la configuración del sistema de diagnóstico).Note that this verbose logging is not turned on by default (it must be enabled in the Diagnostic System settings)

Espacios frente a pestañasSpaces vs tabs

Asegúrese de usar 4 espacios en lugar de pestañas al contribuir a este proyecto.Please be sure to use 4 spaces instead of tabs when contributing to this project.

EspaciadoSpacing

No agregue espacios adicionales entre corchetes y paréntesis:Do not to add additional spaces between square brackets and parenthesis:

Lo que debe evitar:Don't

private Foo()
{
    int[ ] var = new int [ 9 ];
    Vector2 vector = new Vector2 ( 0f, 10f );
}

Lo que es necesario hacer:Do

private Foo()
{
    int[] var = new int[9];
    Vector2 vector = new Vector2(0f, 10f);
}

Convenciones de nomenclaturaNaming conventions

Use siempre PascalCase para las propiedades.Always use PascalCase for properties. Se camelCase usa para la mayoría de los campos, excepto para los campos y PascalCase static readonly const .Use camelCase for most fields, except use PascalCase for static readonly and const fields. La única excepción a esto es para las estructuras de datos que requieren que los campos sean serializados por JsonUtility .The only exception to this is for data structures that require the fields to be serialized by the JsonUtility.

Lo que debe evitar:Don't

public string myProperty; // <- Starts with a lowercase letter
private string MyField; // <- Starts with an uppercase letter

Lo que es necesario hacer:Do

public string MyProperty;
protected string MyProperty;
private static readonly string MyField;
private string myField;

Modificadores de accesoAccess modifiers

Declare siempre un modificador de acceso para todos los campos, propiedades y métodos.Always declare an access modifier for all fields, properties and methods.

  • Todos los métodos de LA API de Unity deben ser de forma predeterminada, a menos que private tenga que invalidarlos en una clase derivada.All Unity API Methods should be private by default, unless you need to override them in a derived class. En este protected caso, se debe usar .In this case protected should be used.

  • Los campos siempre deben ser private , con public los protected accessors de propiedad o .Fields should always be private, with public or protected property accessors.

  • Usar miembros con forma de expresión y propiedades automáticas siempre que sea posibleUse expression-bodied members and auto properties where possible

Lo que debe evitar:Don't

// protected field should be private
protected int myVariable = 0;

// property should have protected setter
public int MyVariable => myVariable;

// No public / private access modifiers
void Foo() { }
void Bar() { }

Lo que es necesario hacer:Do

public int MyVariable { get; protected set; } = 0;

private void Foo() { }
public void Bar() { }
protected virtual void FooBar() { }

Usar llavesUse braces

Use siempre llaves después de cada bloque de instrucciones y colóctelas en la línea siguiente.Always use braces after each statement block, and place them on the next line.

Cosas que evitarDon't

private Foo()
{
    if (Bar==null) // <- missing braces surrounding if action
        DoThing();
    else
        DoTheOtherThing();
}

Lo que debe evitar:Don't

private Foo() { // <- Open bracket on same line
    if (Bar==null) DoThing(); <- if action on same line with no surrounding brackets
    else DoTheOtherThing();
}

Lo que es necesario hacer:Do

private Foo()
{
    if (Bar==true)
    {
        DoThing();
    }
    else
    {
        DoTheOtherThing();
    }
}

Las clases públicas, las estructuras y las enumeraciones deben ir en sus propios archivos.Public classes, structs, and enums should all go in their own files

Si la clase, la estructura o la enumeración se pueden convertir en privadas, es correcto que se incluyan en el mismo archivo.If the class, struct, or enum can be made private then it's okay to be included in the same file. Esto evita problemas de compilación con Unity y garantiza que se produce la abstracción de código adecuada, también reduce los conflictos y los cambios importantes cuando el código necesita cambiar.This avoids compilations issues with Unity and ensure that proper code abstraction occurs, it also reduces conflicts and breaking changes when code needs to change.

Lo que debe evitar:Don't

public class MyClass
{
    public struct MyStruct() { }
    public enum MyEnumType() { }
    public class MyNestedClass() { }
}

Lo que es necesario hacer:Do

 // Private references for use inside the class only
public class MyClass
{
    private struct MyStruct() { }
    private enum MyEnumType() { }
    private class MyNestedClass() { }
}

Cosas que hacerDo

MyStruct.csMyStruct.cs

// Public Struct / Enum definitions for use in your class.  Try to make them generic for reuse.
public struct MyStruct
{
    public string Var1;
    public string Var2;
}

MyEnumType.csMyEnumType.cs

public enum MuEnumType
{
    Value1,
    Value2 // <- note, no "," on last value to denote end of list.
}

MyClass.csMyClass.cs

public class MyClass
{
    private MyStruct myStructReference;
    private MyEnumType myEnumReference;
}

Inicialización de enumeracionesInitialize enums

Para asegurarse de que todas las enumeraciones se inicializan correctamente a partir de 0, .NET proporciona un acceso directo ordenado para inicializar automáticamente la enumeración agregando simplemente el primer valor (inicio).To ensure all enums are initialized correctly starting at 0, .NET gives you a tidy shortcut to automatically initialize the enum by just adding the first (starter) value. (Por ejemplo, valor 1 = 0 No se requieren valores restantes)(e.g Value 1 = 0 Remaining values are not required)

Lo que debe evitar:Don't

public enum Value
{
    Value1, <- no initializer
    Value2,
    Value3
}

Lo que es necesario hacer:Do

public enum ValueType
{
    Value1 = 0,
    Value2,
    Value3
}

Ordenación de enumeraciones para la extensión adecuadaOrder enums for appropriate extension

Es fundamental que, si es probable que una enumeración se pueda extender en el futuro, para ordenar los valores predeterminados en la parte superior de la enumeración, esto garantiza que los índices de enumeración no se ven afectados con nuevas adiciones.It is critical that if an Enum is likely to be extended in the future, to order defaults at the top of the Enum, this ensures Enum indexes are not affected with new additions.

Lo que debe evitar:Don't

public enum SDKType
{
    WindowsMR,
    OpenVR,
    OpenXR,
    None, <- default value not at start
    Other <- anonymous value left to end of enum
}

Lo que es necesario hacer:Do

/// <summary>
/// The SDKType lists the VR SDKs that are supported by the MRTK
/// Initially, this lists proposed SDKs, not all may be implemented at this time (please see ReleaseNotes for more details)
/// </summary>
public enum SDKType
{
    /// <summary>
    /// No specified type or Standalone / non-VR type
    /// </summary>
    None = 0,
    /// <summary>
    /// Undefined SDK.
    /// </summary>
    Other,
    /// <summary>
    /// The Windows 10 Mixed reality SDK provided by the Universal Windows Platform (UWP), for Immersive MR headsets and HoloLens.
    /// </summary>
    WindowsMR,
    /// <summary>
    /// The OpenVR platform provided by Unity (does not support the downloadable SteamVR SDK).
    /// </summary>
    OpenVR,
    /// <summary>
    /// The OpenXR platform. SDK to be determined once released.
    /// </summary>
    OpenXR
}

Revisión del uso de enumeración para campos de bitsReview enum use for bitfields

Si existe la posibilidad de que una enumeración requiera varios estados como valor, por ejemplo, Handedness = Left & Right.If there is a possibility for an enum to require multiple states as a value, e.g. Handedness = Left & Right. A continuación, la enumeración debe decorarse correctamente con BitFlags para que se pueda usar correctamente.Then the Enum needs to be decorated correctly with BitFlags to enable it to be used correctly

El archivo Handedness.cs tiene una implementación concreta para esto.The Handedness.cs file has a concrete implementation for this

Lo que debe evitar:Don't

public enum Handedness
{
    None,
    Left,
    Right
}

Lo que es necesario hacer:Do

[Flags]
public enum Handedness
{
    None = 0 << 0,
    Left = 1 << 0,
    Right = 1 << 1,
    Both = Left | Right
}

Rutas de acceso de archivo codificadas de forma fuerteHard-coded file paths

Al generar rutas de acceso de archivo de cadena y, en particular, escribir rutas de acceso de cadena codificadas de forma fuerte, haga lo siguiente:When generating string file paths, and in particular writing hard-coded string paths, do the following:

  1. Use las API de C# Path siempre que sea posible, como Path.Combine o Path.GetFullPath .Use C#'s Path APIs whenever possible such as Path.Combine or Path.GetFullPath.
  2. Use / o Path.DirectorySeparatorChar en lugar de \ o \ \ .Use / or Path.DirectorySeparatorChar instead of \ or \\.

Estos pasos garantizan que MRTK funciona en sistemas basados Windows y Unix.These steps ensure that MRTK works on both Windows and Unix-based systems.

Lo que debe evitar:Don't

private const string FilePath = "MyPath\\to\\a\\file.txt";
private const string OtherFilePath = "MyPath\to\a\file.txt";

string filePath = myVarRootPath + myRelativePath;

Lo que es necesario hacer:Do

private const string FilePath = "MyPath/to/a/file.txt";
private const string OtherFilePath = "folder{Path.DirectorySeparatorChar}file.txt";

string filePath = Path.Combine(myVarRootPath,myRelativePath);

// Path.GetFullPath() will return the full length path of provided with correct system directory separators
string cleanedFilePath = Path.GetFullPath(unknownSourceFilePath);

Procedimientos recomendados, incluidas las recomendaciones de UnityBest practices, including Unity recommendations

Algunas de las plataformas de destino de este proyecto requieren tener en cuenta el rendimiento.Some of the target platforms of this project require to take performance into consideration. Con esto en mente, tenga siempre cuidado al asignar memoria en código con frecuencia llamado en bucles de actualización o algoritmos estrictos.With this in mind always be careful when allocating memory in frequently called code in tight update loops or algorithms.

EncapsulaciónEncapsulation

Use siempre campos privados y propiedades públicas si se necesita acceso al campo desde fuera de la clase o struct.Always use private fields and public properties if access to the field is needed from outside the class or struct. Asegúrese de colocar el campo privado y la propiedad pública.Be sure to co-locate the private field and the public property. Esto facilita ver, de un vistazo, lo que hace detrás de la propiedad y que el campo se puede modifica mediante script.This makes it easier to see, at a glance, what backs the property and that the field is modifiable by script.

Nota

La única excepción a esto es para las estructuras de datos que requieren que los campos sean serializados por , donde se requiere que una clase de datos tenga todos los campos públicos para que funcione JsonUtility la serialización.The only exception to this is for data structures that require the fields to be serialized by the JsonUtility, where a data class is required to have all public fields for the serialization to work.

Lo que debe evitar:Don't

private float myValue1;
private float myValue2;

public float MyValue1
{
    get{ return myValue1; }
    set{ myValue1 = value }
}

public float MyValue2
{
    get{ return myValue2; }
    set{ myValue2 = value }
}

Lo que es necesario hacer:Do

// Enable field to be configurable in the editor and available externally to other scripts (field is correctly serialized in Unity)
[SerializeField]
[ToolTip("If using a tooltip, the text should match the public property's summary documentation, if appropriate.")]
private float myValue; // <- Notice we co-located the backing field above our corresponding property.

/// <summary>
/// If using a tooltip, the text should match the public property's summary documentation, if appropriate.
/// </summary>
public float MyValue
{
    get => myValue;
    set => myValue = value;
}

/// <summary>
/// Getter/Setters not wrapping a value directly should contain documentation comments just as public functions would
/// </summary>
public float AbsMyValue
{
    get
    {
        if (MyValue < 0)
        {
            return -MyValue;
        }

        return MyValue
    }
}

Almacenar en caché valores y serializarlos en la escena o prefab siempre que sea posibleCache values and serialize them in the scene/prefab whenever possible

Con la HoloLens en mente, es mejor optimizar el rendimiento y las referencias de caché en la escena o prefab para limitar las asignaciones de memoria en tiempo de ejecución.With the HoloLens in mind, it's best to optimize for performance and cache references in the scene or prefab to limit runtime memory allocations.

Lo que debe evitar:Don't

void Update()
{
    gameObject.GetComponent<Renderer>().Foo(Bar);
}

Lo que es necesario hacer:Do

[SerializeField] // To enable setting the reference in the inspector.
private Renderer myRenderer;

private void Awake()
{
    // If you didn't set it in the inspector, then we cache it on awake.
    if (myRenderer == null)
    {
        myRenderer = gameObject.GetComponent<Renderer>();
    }
}

private void Update()
{
    myRenderer.Foo(Bar);
}

Almacenar en caché referencias a materiales, no llamar a ".material" cada vezCache references to materials, do not call the ".material" each time

Unity creará un nuevo material cada vez que use ".material", lo que provocará una pérdida de memoria si no se limpia correctamente.Unity will create a new material each time you use ".material", which will cause a memory leak if not cleaned up properly.

Lo que debe evitar:Don't

public class MyClass
{
    void Update()
    {
        Material myMaterial = GetComponent<Renderer>().material;
        myMaterial.SetColor("_Color", Color.White);
    }
}

Lo que es necesario hacer:Do

// Private references for use inside the class only
public class MyClass
{
    private Material cachedMaterial;

    private void Awake()
    {
        cachedMaterial = GetComponent<Renderer>().material;
    }

    void Update()
    {
        cachedMaterial.SetColor("_Color", Color.White);
    }

    private void OnDestroy()
    {
        Destroy(cachedMaterial);
    }
}

Nota

Como alternativa, use la propiedad "SharedMaterial" de Unity, que no crea un nuevo material cada vez que se hace referencia a él.Alternatively, use Unity's "SharedMaterial" property which does not create a new material each time it is referenced.

Use la compilación dependiente de la plataforma para Toolkit no interrumpirá la compilación en otra plataforma.Use platform dependent compilation to ensure the Toolkit won't break the build on another platform

  • Use WINDOWS_UWP para usar API específicas de UWP que no son de Unity.Use WINDOWS_UWP in order to use UWP-specific, non-Unity APIs. Esto impedirá que intenten ejecutarse en el editor o en plataformas no admitidas.This will prevent them from trying to run in the Editor or on unsupported platforms. Esto es equivalente a UNITY_WSA && !UNITY_EDITOR y debe usarse en favor de .This is equivalent to UNITY_WSA && !UNITY_EDITOR and should be used in favor of.
  • Use UNITY_WSA para usar LAS API de Unity específicas de UWP, como el espacio de nombres UnityEngine.XR.WSA .Use UNITY_WSA to use UWP-specific Unity APIs, such as the UnityEngine.XR.WSA namespace. Esto se ejecutará en el Editor cuando la plataforma esté establecida en UWP, así como en aplicaciones para UWP integradas.This will run in the Editor when the platform is set to UWP, as well as in built UWP apps.

Este gráfico puede ayudarle a decidir qué usar, en función de los casos #if de uso y la configuración de compilación que espera.This chart can help you decide which #if to use, depending on your use cases and the build settings you expect.

PlataformaPlatform UWP IL2CPPUWP IL2CPP UWP .NETUWP .NET EditorEditor
UNITY_EDITOR FalsoFalse FalseFalse TrueTrue
UNITY_WSA TrueTrue TrueTrue TrueTrue
WINDOWS_UWP TrueTrue TrueTrue FalseFalse
UNITY_WSA && !UNITY_EDITOR TrueTrue TrueTrue FalseFalse
ENABLE_WINMD_SUPPORT TrueTrue TrueTrue FalsoFalse
NETFX_CORE FalseFalse TrueTrue FalsoFalse

Preferir DateTime.UtcNow en lugar de DateTime.NowPrefer DateTime.UtcNow over DateTime.Now

DateTime.UtcNow es más rápido que DateTime.Now.DateTime.UtcNow is faster than DateTime.Now. En investigaciones de rendimiento anteriores, hemos descubierto que el uso de DateTime.Now agrega una sobrecarga significativa especialmente cuando se usa en el bucle Update().In previous performance investigations we've found that using DateTime.Now adds significant overhead especially when used in the Update() loop. Otros han tenido el mismo problema.Others have hit the same issue.

Prefiere usar DateTime.UtcNow a menos que realmente necesite las horas localizadas (un motivo legítimo puede ser que quiera mostrar la hora actual en la zona horaria del usuario).Prefer using DateTime.UtcNow unless you actually need the localized times (a legitimate reason may be you wanting to show the current time in the user's time zone). Si está trabajando con horas relativas (es decir, la diferencia entre alguna última actualización y ahora), es mejor usar DateTime.UtcNow para evitar la sobrecarga de realizar conversiones de zona horaria.If you are dealing with relative times (i.e. the delta between some last update and now), it's best to use DateTime.UtcNow to avoid the overhead of doing timezone conversions.

Convenciones de codificación de PowerShellPowerShell coding conventions

Un subconjunto del código base de MRTK usa PowerShell para la infraestructura de canalización y varios scripts y utilidades.A subset of the MRTK codebase uses PowerShell for pipeline infrastructure and various scripts and utilities. El nuevo código de PowerShell debe seguir el estilo PoshCode.New PowerShell code should follow the PoshCode style.

Consulte tambiénSee also

Convenciones de codificación de C# de MSDNC# coding conventions from MSDN