Eğitim
Öğrenme yolu
Use advance techniques in canvas apps to perform custom updates and optimization - Training
Use advance techniques in canvas apps to perform custom updates and optimization
Bu tarayıcı artık desteklenmiyor.
En son özelliklerden, güvenlik güncelleştirmelerinden ve teknik destekten faydalanmak için Microsoft Edge’e yükseltin.
Bu belgede MRTK'ya katkıda bulunurken izleyebileceğiniz kodlama ilkeleri ve kuralları özetlenmiştir.
En basit çözüm genellikle en iyisidir. Bu, bu yönergeleri geçersiz kılma amaçlıdır ve tüm kodlama etkinliklerinin hedefi olmalıdır. Basit olmanın bir parçası da kısa ve mevcut kodla tutarlı olmaktır. Kodunuzu basit tutmaya çalışın.
Okuyucular yalnızca yararlı bilgiler sağlayan yapıtlarla karşılaşmalıdır. Örneğin, bariz olan şeyleri yeniden ifade eden yorumlar ek bilgi sağlamaz ve gürültü ile sinyal oranını artırır.
Kod mantığını basit tutun. Bunun en az sayıda satır kullanma, tanımlayıcı adlarının veya küme ayracı stilinin boyutunu en aza indirmeyle ilgili bir ifade olmadığını, kavramların sayısını azaltma ve tanıdık desenler aracılığıyla bunların görünürlüğünü en üst düzeye çıkarma hakkında bir ifade olduğunu unutmayın.
Kod okunabilirliği düşük hata oranlarıyla ilişkilendirilir. Okuması kolay bir kod oluşturmaya çabalayın. Basit mantığa sahip olan ve mevcut bileşenleri yeniden kullanan bir kod oluşturmaya çabalayın, bu da doğruluğun sağlanmasına yardımcı olur.
En temel doğruluk ayrıntısından tutarlı stil ve biçimlendirmeye kadar, ürettiğiniz kodun tüm ayrıntıları. Tercihinize uygun olmasa bile kodlama stilinizi mevcut olanlarla tutarlı tutun. Bu, genel kod tabanının okunabilirliğini artırır.
MRTK, Unity düzenleyicisinde bileşenleri yapılandırmayı ve önkoşulları yüklemeyi tercih eden ve çalışma zamanında nesnelerin örneğini oluşturması ve yapılandırması gereken kişiler olmak üzere çok çeşitli kullanıcıları destekler.
Tüm kodunuz, kaydedilmiş bir sahnede GameObject'e bileşen ekleyerek ve bu bileşeni kodda başlatarak çalışmalıdır. Testler hem prefab örneği oluşturmak hem de örneği oluşturmak ve bileşeni çalışma zamanında yapılandırmak için bir test çalışması içermelidir.
Düzenleyicide Oynat, Unity'de yinelemenin en hızlı yoludur. Müşterilerimizin hızlı bir şekilde yinelemesi için yollar sağlamak, hem daha hızlı çözüm geliştirmelerine hem de daha fazla fikir denemelerine olanak tanır. Başka bir deyişle yineleme hızını en üst düzeye çıkarmak müşterilerimizin daha fazlasını başarmalarına yardımcı olur.
Her şeyin düzenleyicide çalışmasını sağlayın, ardından başka bir platformda çalışmasını sağlayın. Düzenleyicide çalışmaya devam edin. Play-In-Editor'a yeni bir platform eklemek kolaydır. Uygulamanız yalnızca bir cihazda çalışıyorsa, Düzenleyicide Oynat'ın çalışmasını sağlamak çok zordur.
Genel bir yöntem, alan, özellik eklediğinizde mrtk'nin genel API yüzeyinin bir parçası olur. ile [SerializeField]
işaretlenen özel alanlar da alanları düzenleyicide kullanıma sunar ve genel API yüzeyinin bir parçasıdır. Diğer kişiler bu ortak yöntemi kullanabilir, genel alanınızla özel önkoşullar yapılandırabilir ve bu yönteme bir bağımlılık alabilir.
Yeni genel üyeler dikkatle incelenmelidir. Gelecekte tüm ortak alanlara bakım yapılması gerekir. Bir ortak alanın (veya seri hale getirilmiş özel alanın) türü değişirse veya MonoBehaviour'dan kaldırılırsa, bunun diğer kişileri kırabileceğini unutmayın. Alanın önce bir sürüm için kullanım dışı bırakılması ve bağımlılıkları alan kişiler için değişiklikleri geçirme kodunun sağlanması gerekir.
MRTK, çeşitli katkıda bulunanlar tarafından değiştirilen bir topluluk projesidir. Bu katkıda bulunanlar hata düzeltmenizin / özelliğinizin ayrıntılarını bilmeyebilir ve özelliğinizi yanlışlıkla bozabilir. MRTK, her çekme isteğini tamamlamadan önce sürekli tümleştirme testleri çalıştırır. Testleri bozan değişiklikler iade edilemez. Bu nedenle testler, diğer kişilerin özelliğinizi bozmamasını sağlamanın en iyi yoludur.
Bir hatayı düzelttiğinizde, gelecekte gerilemediğinden emin olmak için bir test yazın. Özellik ekliyorsanız, özelliğinizin çalıştığını doğrulayan testler yazın. Bu, deneysel özellikler dışındaki tüm UX özellikleri için gereklidir.
Yeni dosyalara katkıda bulunan tüm Microsoft çalışanları, tam olarak aşağıda gösterildiği gibi yeni dosyaların en üstüne aşağıdaki standart Lisans üst bilgisini eklemelidir:
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
MRTK'ya gönderilen tüm genel sınıflar, yapılar, sabit listeleri, işlevler, özellikler, alanlar, aşağıda gösterildiği gibi amacı ve kullanımı olarak açıklanmalıdır:
/// <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;
}
Bu, belgelerin tüm sınıflar, yöntemler ve özellikler için düzgün bir şekilde oluşturulmasını ve dağıtılmasını sağlar.
Düzgün özet etiketleri olmadan gönderilen tüm betik dosyaları reddedilir.
Karma Gerçeklik Araç Seti, tüm temel ad alanlarının "Microsoft.MixedReality.Toolkit" ile başladığı özellik tabanlı bir ad alanı modeli kullanır. Genel olarak, ad alanlarınızda araç seti katmanını (ör. Çekirdek, Sağlayıcılar, Hizmetler) belirtmeniz gerekmez.
Şu anda tanımlanmış olan ad alanları şunlardır:
Büyük miktarda türü olan ad alanları için, kapsam belirleme kullanımına yardımcı olmak için sınırlı sayıda alt ad alanı oluşturmak kabul edilebilir.
Bir arabirim, sınıf veya veri türü için ad alanının atlanması, değişikliğinizin engellenmesine neden olur.
Çekme isteğiyle yeni MonoBehaviour betikleri eklerken özniteliğin tüm geçerli dosyalara uygulandığından AddComponentMenu
emin olun. Bu, bileşen ekle düğmesinin altındaki düzenleyicide kolayca bulunabilir olmasını sağlar. Bileşen bir soyut sınıf gibi düzenleyicide gösterilemiyorsa öznitelik bayrağı gerekli değildir.
Aşağıdaki örnekte , buradaki Paket bileşenin paket konumuyla doldurulmalıdır. BIR öğe MRTK/SDK klasörüne yerleştirilecekse paket SDK olacaktır.
[AddComponentMenu("Scripts/MRTK/{Package here}/MyNewComponent")]
public class MyNewComponent : MonoBehaviour
Genel olarak, MRTK bileşenleri için özel denetçi betikleri oluşturmaktan kaçınmaya çalışın. Unity altyapısı tarafından işlenebilen kod tabanının ek yükünü ve yönetimini ekler.
Bir denetçi sınıfı gerekiyorsa Unity'nin DrawDefaultInspector()
öğesini kullanmayı deneyin. Bu da denetçi sınıfını basitleştirir ve işin büyük kısmını Unity'ye bırakır.
public override void OnInspectorGUI()
{
// Do some custom calculations or checks
// ....
DrawDefaultInspector();
}
Denetçi sınıfında özel işleme gerekiyorsa ve EditorGUILayout.PropertyField
kullanmayı SerializedProperty
deneyin. Bu, Unity'nin iç içe yerleştirilmiş önkoşulları ve değiştirilmiş değerleri işlemeyi doğru şekilde işlemesini sağlar.
Özel mantıktaki bir gereksinim nedeniyle kullanılamıyorsa EditorGUILayout.PropertyField
, tüm kullanımın çevresinde EditorGUI.PropertyScope
sarmalandığından emin olun. Bu, Unity'nin verilen özellik ile iç içe yerleştirilmiş prefablar ve değiştirilmiş değerler için denetçiyi doğru şekilde işlemesini sağlar.
Ayrıca, özel denetçi sınıfını ile CanEditMultipleObjects
süslemeyi deneyin. Bu etiket, sahnede bu bileşene sahip birden çok nesnenin birlikte seçilip değiştirilebilmesini sağlar. Tüm yeni denetçi sınıfları, kodlarının sahnede bu durumda çalışıp çalışmadığını test etmelidir.
// 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;
});
}
}
}
Yeni ScriptableObject betikleri eklerken, özniteliğin CreateAssetMenu
tüm geçerli dosyalara uygulandığından emin olun. Bu, bileşenin varlık oluşturma menüleri aracılığıyla düzenleyicide kolayca bulunabilmesini sağlar. Bileşen bir soyut sınıf gibi düzenleyicide gösterilemiyorsa öznitelik bayrağı gerekli değildir.
Aşağıdaki örnekte, varsa Alt klasör MRTK alt klasörüyle doldurulmalıdır. BIR öğe MRTK/Providers klasörüne yerleştirilecekse paket Sağlayıcılar olacaktır. MRTK/Core klasörüne bir öğe yerleştiriyorsa, bunu "Profiller" olarak ayarlayın.
Aşağıdaki örnekte MyNewService | MyNewProvider , varsa yeni sınıfınızın adıyla doldurulmalıdır. Bir öğeyi MixedRealityToolkit klasörüne yerleştiriyorsa, bu dizeyi dışarıda bırakın.
[CreateAssetMenu(fileName = "MyNewProfile", menuName = "Mixed Reality Toolkit/{Subfolder}/{MyNewService | MyNewProvider}/MyNewProfile")]
public class MyNewProfile : ScriptableObject
Yeni özellikler eklerken veya mevcut özellikleri güncelleştirirken, gelecekte hata ayıklama için yararlı olabilecek ilginç kodlara DebugUtilities.LogVerbose günlükleri eklemeyi göz önünde bulundurun. Burada günlüğe kaydetme ile eklenen kirlilik ile yeterli günlük kaydı olmaması (tanılamayı zorlaştırır) arasında bir denge vardır.
Günlüğe kaydetmenin yararlı olduğu ilginç bir örnek (ilginç yükle birlikte):
DebugUtilities.LogVerboseFormat("RaiseSourceDetected: Source ID: {0}, Source Type: {1}", source.SourceId, source.SourceType);
Bu günlük türü, eşleşmeyen kaynak algılanan ve kaynak kaybı olaylarından kaynaklanan gibi https://github.com/microsoft/MixedRealityToolkit-Unity/issues/8016sorunların yakalanmasına yardımcı olabilir.
Her karede gerçekleşen veriler ve olaylar için günlük eklemekten kaçının; ideal olarak günlük kaydı, ayrı kullanıcı girişleri tarafından yönetilen "ilginç" olayları kapsamalıdır (örneğin, bir kullanıcı tarafından "tıklama" ve günlüğe kaydetmesi ilginç olan değişiklikler ve olaylar kümesi). Her karenin günlüğe kaydedildiği "kullanıcı hala bir hareket tutuyor" durumunun devam ediyor olması ilginç değildir ve günlükleri bunaltacaktır.
Bu ayrıntılı günlüğün varsayılan olarak açık olmadığını unutmayın ( Tanılama Sistemi ayarlarında etkinleştirilmesi gerekir)
Bu projeye katkıda bulunurken sekmeler yerine 4 boşluk kullandığınızdan emin olun.
Köşeli ayraçlar ve parantezler arasına ek boşluk eklemeyin:
private Foo()
{
int[ ] var = new int [ 9 ];
Vector2 vector = new Vector2 ( 0f, 10f );
}
private Foo()
{
int[] var = new int[9];
Vector2 vector = new Vector2(0f, 10f);
}
Özellikler için her zaman kullanın PascalCase
. camelCase
ve const
alanları dışında çoğu alan için static readonly
kullanınPascalCase
. Bunun tek istisnası, alanların tarafından serileştirilmesini gerektiren veri yapılarıdır JsonUtility
.
public string myProperty; // <- Starts with a lowercase letter
private string MyField; // <- Starts with an uppercase letter
public string MyProperty;
protected string MyProperty;
private static readonly string MyField;
private string myField;
Tüm alanlar, özellikler ve yöntemler için her zaman bir erişim değiştiricisi bildirin.
Türetilmiş bir sınıfta geçersiz kılmanız gerekmediği sürece tüm Unity API Yöntemleri varsayılan olarak olmalıdır private
. Bu durumda protected
kullanılmalıdır.
Alanlar her zaman private
veya protected
özellik erişimcileri ile olmalıdırpublic
.
İfade gövdeli üyeleri ve mümkün olduğunda otomatik özellikleri kullanma
// 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() { }
public int MyVariable { get; protected set; } = 0;
private void Foo() { }
public void Bar() { }
protected virtual void FooBar() { }
Her deyim bloğundan sonra her zaman ayraç kullanın ve bunları bir sonraki satıra yerleştirin.
private Foo()
{
if (Bar==null) // <- missing braces surrounding if action
DoThing();
else
DoTheOtherThing();
}
private Foo() { // <- Open bracket on same line
if (Bar==null) DoThing(); <- if action on same line with no surrounding brackets
else DoTheOtherThing();
}
private Foo()
{
if (Bar==true)
{
DoThing();
}
else
{
DoTheOtherThing();
}
}
Sınıf, yapı veya sabit listesi özel hale getirilebiliyorsa, aynı dosyaya dahil edilebilir. Bu, Unity ile derleme sorunlarını önler ve uygun kod soyutlamanın oluşmasını sağlar, ayrıca kodun değiştirilmesi gerektiğinde çakışmaları ve hataya neden olan değişiklikleri azaltır.
public class MyClass
{
public struct MyStruct() { }
public enum MyEnumType() { }
public class MyNestedClass() { }
}
// Private references for use inside the class only
public class MyClass
{
private struct MyStruct() { }
private enum MyEnumType() { }
private class MyNestedClass() { }
}
MyStruct.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.cs
public enum MuEnumType
{
Value1,
Value2 // <- note, no "," on last value to denote end of list.
}
MyClass.cs
public class MyClass
{
private MyStruct myStructReference;
private MyEnumType myEnumReference;
}
.NET, 0'dan başlayarak tüm sabit listelerinin doğru şekilde başlatıldığından emin olmak için, yalnızca ilk (starter) değeri ekleyerek sabit listesi otomatik olarak başlatmanız için düzenli bir kısayol sağlar. (örneğin, Değer 1 = 0 Kalan değerler gerekli değildir)
public enum Value
{
Value1, <- no initializer
Value2,
Value3
}
public enum ValueType
{
Value1 = 0,
Value2,
Value3
}
Bir Sabit Listesi'nin gelecekte genişletilme olasılığı varsa, varsayılan değerleri Enum'un en üstünde sıralamak için, bu durum Enum dizinlerinin yeni eklemelerden etkilenmemesini sağlar.
public enum SDKType
{
WindowsMR,
OpenVR,
OpenXR,
None, <- default value not at start
Other <- anonymous value left to end of enum
}
/// <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
}
Bir sabit listesi için değer olarak birden çok durum gerektirebilir; örneğin, Elle Kullanım = Sol & Sağ. Ardından Enum'un doğru şekilde kullanılmasını sağlamak için BitFlags ile doğru şekilde dekore edilmesi gerekir
Handedness.cs dosyasında bunun için somut bir uygulama var
public enum Handedness
{
None,
Left,
Right
}
[Flags]
public enum Handedness
{
None = 0 << 0,
Left = 1 << 0,
Right = 1 << 1,
Both = Left | Right
}
Dize dosyası yolları oluştururken ve özellikle sabit kodlanmış dize yolları yazarken aşağıdakileri yapın:
Path.GetFullPath
gibi Path.Combine
mümkün olduğunca C#'nin API'leriniPath
kullanın.Path.DirectorySeparatorChar
\\ yerine / veya kullanın.Bu adımlar MRTK'nin hem Windows hem de Unix tabanlı sistemlerde çalışmasını sağlar.
private const string FilePath = "MyPath\\to\\a\\file.txt";
private const string OtherFilePath = "MyPath\to\a\file.txt";
string filePath = myVarRootPath + myRelativePath;
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);
Bu projenin hedef platformlarından bazılarının performansı dikkate alması gerekir. Bunu göz önünde bulundurarak, sık çağrılan koddaki belleği sıkı güncelleştirme döngülerinde veya algoritmalarda ayırırken her zaman dikkatli olun.
Sınıf veya yapı dışından alana erişim gerekiyorsa her zaman özel alanları ve genel özellikleri kullanın. Özel alanı ve ortak özelliği birlikte bulmayı unutmayın. Bu, özelliği neyin yedeklediğini ve alanın betik tarafından değiştirilebilir olduğunu bir bakışta görmeyi kolaylaştırır.
Not
Bunun tek istisnası, alanların tarafından JsonUtility
seri hale getirilmesini gerektiren veri yapılarıdır. Burada, serileştirmenin çalışması için tüm genel alanlara sahip olmak için bir veri sınıfı gerekir.
private float myValue1;
private float myValue2;
public float MyValue1
{
get{ return myValue1; }
set{ myValue1 = value }
}
public float MyValue2
{
get{ return myValue2; }
set{ myValue2 = value }
}
// 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
}
}
HoloLens'i göz önünde bulundurarak, çalışma zamanı bellek ayırmalarını sınırlamak için sahnedeki veya ön bellekteki performans ve önbellek başvurularını iyileştirmek en iyisidir.
void Update()
{
gameObject.GetComponent<Renderer>().Foo(Bar);
}
[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);
}
Unity her ".material" kullandığınızda yeni bir malzeme oluşturur ve bu da düzgün temizlenmediği takdirde bellek sızıntısına neden olur.
public class MyClass
{
void Update()
{
Material myMaterial = GetComponent<Renderer>().material;
myMaterial.SetColor("_Color", Color.White);
}
}
// 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);
}
}
Not
Alternatif olarak, Unity'nin her başvuruda yeni bir malzeme oluşturmayan "SharedMaterial" özelliğini kullanın.
WINDOWS_UWP
. Bu, düzenleyicide veya desteklenmeyen platformlarda çalışmaya çalışmalarını engeller. Bu eşdeğerdir UNITY_WSA && !UNITY_EDITOR
ve lehine kullanılmalıdır.UnityEngine.XR.WSA
kullanmak için kullanınUNITY_WSA
. Platform UWP olarak ayarlandığında ve yerleşik UWP uygulamalarında düzenleyicide bu işlem çalıştırılır.Bu grafik, kullanım örneklerinize ve beklediğiniz derleme ayarlarına bağlı olarak hangisini #if
kullanacağınıza karar vermenize yardımcı olabilir.
Platform | UWP IL2CPP | UWP .NET | Düzenleyici |
---|---|---|---|
UNITY_EDITOR |
Yanlış | Yanlış | Doğru |
UNITY_WSA |
Doğru | Doğru | Doğru |
WINDOWS_UWP |
Doğru | Doğru | Yanlış |
UNITY_WSA && !UNITY_EDITOR |
Doğru | Doğru | Yanlış |
ENABLE_WINMD_SUPPORT |
Doğru | Doğru | Yanlış |
NETFX_CORE |
Yanlış | Doğru | Yanlış |
DateTime.UtcNow, DateTime.Now değerinden daha hızlıdır. Önceki performans araştırmalarında DateTime.Now kullanmanın özellikle Update() döngüsünde kullanıldığında önemli ek yük eklediğini tespit ettik. Diğerleri de aynı soruna çarptı.
Yerelleştirilmiş saatlere gerçekten ihtiyacınız yoksa DateTime.UtcNow kullanmayı tercih edin (geçerli saati kullanıcının saat diliminde göstermek istemeniz geçerli bir neden olabilir). Göreli sürelerle (yani son güncelleştirme ile şimdi arasındaki değişim) ilgileniyorsanız, saat dilimi dönüştürmeleri yapmanın ek yükünü önlemek için DateTime.UtcNow kullanmanız en iyisidir.
MRTK kod tabanının bir alt kümesi, işlem hattı altyapısı ve çeşitli betikler ve yardımcı programlar için PowerShell kullanır. Yeni PowerShell kodu PoshCode stiline uygun olmalıdır.
Eğitim
Öğrenme yolu
Use advance techniques in canvas apps to perform custom updates and optimization - Training
Use advance techniques in canvas apps to perform custom updates and optimization
Belgeler
MRTK ve yönetilen kod çıkarma - MRTK 2
MRTK ve Unity'de Kod Çıkarma
Unity ile yönetilen hata ayıklama - Mixed Reality
Bu makalede, Unity IL2CPP UWP projenizde yönetilen hata ayıklayıcı çalıştırma işlemi anlatılır.
Tanılama sistemini yapılandırma - MRTK 2
MRTK'da tanılamayı yapılandırma belgeleri