
Ceci est la première partie de l'histoire (mélangée à l'histoire de mes erreurs et de leurs solutions) sur la façon dont j'ai (environ deux ans dans mon temps libre) développé une application mobile pour iOS et Android qui motiverait ma fille à résoudre des exemples mathématiques afin qu'elle automatisme atteint dans les bases de l'arithmétique (entrepôt numéro 10 ou plaque multiplicatrice). En conséquence, il s'est avéré une application qui permet à un enfant de gagner de l'argent avec son esprit.
J'ai utilisé le moteur Unity et le langage C #, ainsi qu'un ensemble supplémentaire de logiciels comme le Photohsop obligatoire ou Audacity (pour créer des sons).
Le plan de l'histoire (première partie)
- Contexte
- À propos de la monétisation
- Pourquoi l'unité
- A propos des objets scriptables
- À propos du plugin Anima2D
- À propos de la localisation Lean
- À propos d'iTween
- À propos d'Unity Analitics
- À propos de Visual Studio
- Les références
Contexte et coléoptères du Colorado
Mon expérience précédente a été plusieurs années en 3D et, plus récemment, le développement de plusieurs jeux indépendants avec un programmeur, où j'ai principalement agi en tant que designer et artiste (écrivant très rarement des scripts élémentaires en C #). Bien que je sois familier avec la programmation de première main (j'avais l'habitude de frapper Basic à l'école et de me familiariser avec C / C ++ à l'université).
Toute cette épopée a commencé avec un problème. J'ai vu que lors de la résolution de problèmes scolaires, ma fille «cale» et se trompe, non pas sur quelque chose de compliqué, mais sur la base. J'ai décidé que ce serait amusant si je lui écrivais une application amusante où elle résoudrait des exemples sous forme de jeu (gagner de l'expérience de cette manière et atteindre l'automatisme). Et pour la motiver encore plus, j'ai fait en sorte qu'elle reçoive de l'argent pour la bonne décision des exemples (le montant a été calculé par l'application en fonction du nombre de bonnes réponses, puis j'ai déduit le montant nécessaire, en payant ma fille en liquide).
Bien que ... cette histoire a commencé encore plus tôt. Tout d'abord, j'ai fait une demande à ma fille qui a payé de l'argent pour apprendre des mots anglais. Mais cette application s'est avérée beaucoup plus difficile à mettre en œuvre, de sorte qu'elle est devenue pratique non seulement pour moi (le développeur) et ma fille, mais aussi pour d'autres parents. Par conséquent, l'application anglaise est toujours un développement interne.
J'ai choisi l'argent comme motivation, car c'était le plus simple à mettre en œuvre. Et aussi à cause des souvenirs d'enfance: j'adorais tout faire pour de l'argent. Même si c'était un travail très fastidieux, comme ramasser des coléoptères du Colorado. Je me souviens avoir récupéré leur pot d'un demi-litre (mes parents m'ont payé 1 kopeck pour chaque bug). J'ai donc pensé que depuis ma fille (je n'ai pas vérifié, mais j'en suis presque sûre), alors elle devrait aimer. Bon, au final je n'ai pas perdu.
Ma femme est contre l'encouragement des enfants à faire quelque chose pour de l'argent. Mais mon argument l'a un peu convaincue: dans le cas de cette demande, l'enfant reçoit de l'argent non pas pour ce qu'il doit faire (comme les devoirs), mais pour le fait qu'il pratique en plus les mathématiques pendant son temps libre.
La deuxième raison pour laquelle j'ai commencé à développer était parce que je voulais pratiquer la programmation. «Devenir programmeur» est mon rêve chéri depuis les premières années de l'école (juste après le rêve de «devenir scientifique», mais avant le rêve de «faire des dessins animés»).
Monétisation et plaisir
Au départ, j'ai fait cette application (le nom de travail était Math4Ami) exclusivement pour l'iPod touch 5 de ma fille. Je n'ai même pas pensé à rendre l'application disponible sur tous les appareils iOS ou à la publier pour tout le monde et, surtout, je n'ai pas pensé à la publier pour la plate-forme Android (j'ai entendu beaucoup d'histoires effrayantes de développeurs iOS en plus, je n'ai rien pour tester la version Android).
Il y a quelque temps, j'ai été tenté de la publier sur l'AppStore (j'étais très attiré par l'idée que j'aurais ma propre application dans l'Apple Store et que tout le monde pourrait la voir).
Je pensais que dans un mois je réussirai. Après tout, toutes les fonctionnalités étaient prêtes, il ne restait plus qu'à la faire fonctionner pour tous les proportions de l'écran et compréhensible non seulement pour moi, mais aussi pour les autres parents. Et maintenant, six mois plus tard, je l'ai publié sur l'AppStore et Google Play.
J'ai d'abord décidé de rendre Math4Ami totalement gratuit sans un soupçon de monétisation. Il y a plusieurs raisons à cette décision.
Le premier. Comme vous l'avez déjà compris, je l'ai d'abord rendu gratuit pour ma fille et je ne voulais rien foutre en "fin" de développement.
Le deuxième. J'ai décidé que ce serait un développement pour mon propre plaisir. J'ai déjà une expérience similaire - je fais un blog pour le plaisir (qui ne mangeait initialement que de l'argent: de l'argent pour l'hébergement et un nom de domaine, du temps pour écrire des articles et leur promotion). Ma logique était la suivante: si je paie de l'argent pour visiter le parc aquatique, acheter un livre ou une glace pour m'amuser, alors pourquoi ne puis-je pas me permettre de payer de l'argent pour l'hébergement, un nom de domaine ou l'adhésion au programme pour développeurs Apple, si cela me fait aussi plaisir.
Le troisième - pour un public plus large, qui serait considérablement réduit, rendant l'application payante (comme le font de nombreux développeurs d'applications pour enfants). J'ai rejeté d'autres types de monétisation pour les raisons décrites ci-dessous.
Je ne supporte pas la publicité dans le jeu - je n'aime pas quand la conception de l'application est défigurée par des messages publicitaires (sauf pour la publicité sous forme de vues vidéo à volonté , et non lorsque la vidéo apparaît au coin de la rue). De plus, pour participer aux programmes "Made for kids" d'Apple et "Designed for Families" de Google, vous devez filtrer strictement les publicités affichées pour les enfants.
Les achats dans le jeu, moi-même, en tant que parent, bloquent sur tous les appareils et les enfants, lorsqu'ils téléchargent des applications eux-mêmes, ne peuvent tout simplement pas acheter quoi que ce soit à l'intérieur de l'application. Une autre chose est lorsque le parent lui-même achète initialement la demande pour l'enfant (mais je l'ai déjà dit ci-dessus).
Pourquoi l'unité et comment
J'ai choisi Unity parce que j'y travaillais auparavant et je l'ai aimé. J'avais aussi un bon ami en tant que programmeur C # et j'espérais qu'il m'aiderait avec la programmation, si cela. Unity possède également une communauté magnifique et il est très facile de trouver des réponses dans Google pour presque toutes les questions concernant la mise en œuvre de quelque chose sur C # + Unity.
J'ai également travaillé avec Unreal (en tant qu'artiste 3D), mais je ne comprenais ni les fonctionnalités C ++ ni 2D.
Initialement, Math4Ami était "nuageux", bien qu'il soit dit haut et fort. Toutes les données ont été stockées sur mon eVPS (Elastic Virtual Private Server) et j'ai utilisé FTP pour transférer des fichiers TXT avec des données et des paramètres d'application (mes mains n'ont pas atteint la base de données, bien que j'aie écrit les premières étapes de l'écriture de mon serveur sur node.js entrepris). Pour travailler avec ftp, j'ai attaché à Unity la classe FTP simple C # facile à utiliser.
Puis, quand j'ai décidé de rendre l'application publique, j'ai abandonné le côté serveur.
D'une part, ce serait trop confus: faire l'authentification (les utilisateurs n'aiment pas cela) ou enregistrer l'identifiant de session dans iCloud à l'aide de NSUbiquitousKeyValueStore (cela identifierait automatiquement l'utilisateur entre la désinstallation et la réinstallation de l'application), mais je ne l'ai toujours pas compris avec cela (peut-être que l'article que j'ai correctement écrit le plugin Unity m'aiderait . Partie 1: iOS , mais ce n'était pas encore le cas).
D'un autre côté, les données de cette application ne sont pas si importantes qu'elles doivent être stockées sur le serveur.
D'un autre côté, la synchronisation du serveur n'était pas nécessaire. Ici pour ma demande d'enseignement de l'anglais - oui là, une synchronisation était nécessaire. Puisque le parent ajoute de nouveaux mots dans la demande parentale, et l'enfant les enseigne dans la demande enfantine (bien que je sois peut-être un amateur pour compliquer les choses).
En conséquence, je me suis assuré que tout était stocké localement (sur l'appareil), mais pas au format txt, mais au format JSON.
ScriptableObject et réponses correctes
Le format JSON en collaboration avec ScriptableObject s'est avéré être une magnifique trouvaille. J'ai utilisé les méthodes natives d'UnityEngine pour sérialiser des objets dans json - JsonUtility (puis j'ai enregistré les fichiers texte json localement sur l'appareil dans le dossier Application.persistentDataPath ).
ScriptableObject (SO) est un sujet de conversation distinct, mais j'y reviendrai. Je ne peux même pas imaginer comment je vivais sans SO.
Tout ce que j'utilise dans mon travail, j'ai obtenu de ces deux vidéos très utiles sur les principes de travail avec SO (et le code d'accompagnement sur GitHub et Bitbucket):
Personnellement, j'ai utilisé SO à de telles fins:
- Pour stocker des données (afin que vous n'ayez pas à entrer dans le code à chaque fois pour ajouter de nouvelles fonctionnalités ou données):
- une variété d'exemples
- type de monnaie
- style de bouton (j'ai les mêmes boutons à de nombreux endroits et je crée juste des skins pour eux basés sur SO),
- valeur de récompense, etc.
- En tant que variables globales (visibles dans toutes les scènes):
- nombre de bonnes réponses
- montant d'argent gagné
- paramètres actuellement actifs
- type actuel d'exemple
- minuterie, meilleurs scores, etc.
- Pour stocker la logique (par exemple, s'abonner à l'événement de recevoir la bonne réponse).
Le seul inconvénient de SO pour travailler avec des données est que vous ne pouvez pas y stocker de données entre les sessions d'application: les actifs SO (après un démarrage à froid de l'application) contiendront toujours les données que vous y avez écrites dans l'éditeur. Par conséquent, la logique de mon travail est la suivante:
- Après avoir démarré l'application, je lis les fichiers json du disque et j'en charge les données dans les actifs SO (méthode FromJsonOverwrite).
- Pendant que l'application est en cours d'exécution et que j'ai besoin de performances maximales - je ne travaille qu'avec des actifs d'objets scriptables. Ces actifs stockent des données en permanence pendant que l'application est en cours d'exécution ou en arrière-plan.
- Lorsque vous devez enregistrer des données (par exemple, à la fin d'une application ou pendant que vous travaillez), je sérialise SO en json (méthode ToJson) et l'enregistre sur le disque.
Il y a un inconvénient (évident) à cette approche - vous ne pouvez pas enregistrer un seul paramètre modifié sur le disque (s'il y en a plusieurs dans SO), vous devez enregistrer tout le fichier texte json tout le temps.
Mais de nombreuses données n'ont pas besoin d'être enregistrées sur le disque (par exemple, le nombre actuel de réponses correctes), puis SO est un outil puissant qui me permet de simplifier considérablement le travail.
Dans la vidéo ci-dessous, je montre un exemple de mon implémentation de la prise en compte des réponses correctes et incorrectes à l'aide d'UnityEvent (événement - le nombre de réponses correctes a-t-il changé) + Listener (les auditeurs font un peu de travail s'ils entendent que la bonne réponse est reçue, et la logique des auditeurs abonnés à l'événement est également implémenté sur SO) + SO (garde une trace du nombre de bonnes réponses):
Ainsi, je peux non seulement entrer les réponses correctes et erronées avec mes mains, mais simplement en déplaçant le curseur, générer de nouveaux exemples et tester la logique de l'application.
Anima2D, personnages et sourire tremblant
La vidéo ci-dessus montre que lorsqu'un nouveau centime tombe, les autres centimes commencent à sourire largement et quand un caca tombe, les centimes sont horrifiés.
Pendant longtemps, je n'ai pas pu vaincre le pépin, lorsque lors du passage d'un type de sourire à un autre, le changement ne s'est pas produit instantanément, mais a cligné des yeux (d'un état à un autre) pendant un certain temps. De plus, je vais vous dire comment j'ai réalisé cela et comment j'ai vaincu ce problème.
Le changement des expressions faciales est implémenté à l'aide du script Sprite Mesh Animation, qui fait partie du puissant plugin Anima2D (que Unity a récemment acheté et rendu gratuit). Ce script change essentiellement les sprites pour la bouche (sourire, sourire ouvert, bouche effrayée) en utilisant le curseur Frame :

L'embuscade est que la valeur du curseur Frame ne peut pas être modifiée directement à partir des scripts, mais uniquement via un système d'animation. Par conséquent, j'ai créé une nouvelle couche d'animation OpenSmile (flèche 1 dans la figure ci-dessous) en mode de mélange additif avec un poids de Weight = 1 et y ai ajouté une animation d'horreur ( Coin_scared ) et un large sourire ( SmillingWide ).
Au fait, avez-vous remarqué quel mauvais exemple je donne, avec des noms d'animation? Je suis toujours en train d'apporter des noms à un seul style. Il serait correct de changer Coin_scared en A_CoinScared (pourquoi juste lire cela dans la section "Ce que je regrette").
J'ai créé un nouveau calque et je n'ai pas utilisé l'ancien, car je ne voulais pas écraser l' animation de la bouche. Tout ce que j'avais à faire était de changer le sprite de la bouche (du sourire au sourire large ou du sourire à l'horreur) et à ce que l' animation de la bouche reste de la couche de base. C'est pourquoi j'ai choisi le mode de mélange additif - en ajoutant une nouvelle animation à une animation existante (sans l'écraser).
À la base, les animations SmillingWide et Coin_scared ne sont que des animations du curseur Frame aux positions 1 et 2, respectivement.

Tout le problème était que la transition de n'importe quel état à l'état d'horreur (lorsque vous cliquez sur une transition (flèche 2 dans la figure ci-dessus), l'inspecteur ouvre les propriétés de cette transition (flèche 3 dans la figure ci-dessus)) ne s'est pas produite instantanément, mais en douceur sur pendant la durée de transition (flèche 4 dans la figure ci-dessus), qui n'était pas nulle par défaut. Ainsi, la valeur du curseur Frame n'a pas pu être modifiée correctement, car il n'y avait que des entiers, ce qui signifie qu'il n'y a pas de valeur intermédiaire entre 0 et 1. Par conséquent, afin de se débarrasser du problème clignotant, il était seulement nécessaire de réinitialiser la valeur de la durée de transition .
Eh bien, le déclencheur isScared (flèche 5 dans la figure ci-dessus) sert de condition pour entrer dans un état d'horreur. J'active ce déclencheur dans le code en utilisant l'appel suivant à l'objet sur lequel se bloque le composant Animator (avec le contrôleur, dont j'ai montré les couches ci-dessus):
...GetComponent<Animator>().SetTrigger("isScared");
Comment j'ai traduit l'application dans différentes langues
Quelque part ici, sur Habré, j'ai lu que vous devez penser à la localisation au début de la création de l'application et j'ai suivi ce conseil ... immédiatement ... après un an et demi de développement (dès que j'ai décidé que Math4Ami serait public).
Pourquoi j'ai choisi Lean Localization (sauf pour la raison pour laquelle le plugin est gratuit) Je ne me souviens pas, mais je me souviens que j'ai choisi pendant longtemps et dur.
Son utilisation s'est avérée très simple. Vous pouvez soit définir manuellement la langue, soit utiliser la détection automatique de la langue. Je me suis installé sur la détection automatique de la langue (en suivant l'exemple des autres applications pour enfants).
Le plugin traduit tout (du texte aux sons et aux images).
Mais j'ai quand même fait une erreur avec la localisation (même si je l'ai fait intentionnellement, car je voulais essayer différentes approches). L'erreur est que je n'ai pas mis toutes les phrases dans un fichier texte (à gauche dans la figure ci-dessous). Certaines phrases sont restées à l'intérieur du composant de localisation Lean (à droite dans la figure ci-dessous). Alors maintenant, quand je donne ce fichier à un traducteur japonais, je dois travailler manuellement (pour tout transférer dans un fichier texte).

Bien que certaines choses ne puissent pas être traduites avec un fichier texte (comme l'espace "", que j'ai utilisé comme séparateur entre des milliers) - vous devez toujours utiliser le composant.
Juicy iTween
Il était une fois j'ai regardé une magnifique vidéo de Juice it ou je l'ai perdu sur la façon dont toutes sortes de petites micromotion et nuances d'animation aident à faire une action à couper le souffle sur un jeu ennuyeux. Et même avant cela, une autre vidéo a coulé dans mon âme - L'art du screenshake , qui n'est en fait pas seulement et pas tellement sur le shake d'écran.
Pendant tout le temps que je créais Math4Ami, j'ai gardé à l'esprit les concepts des vidéos ci-dessus, ainsi que l'idée que toute cette animation supplémentaire devrait être aussi courte que possible et agir plus sur le subconscient que sur le conscient. Parfois, je passais plus de temps à ajouter du «juteux» qu'à ajouter des fonctionnalités utiles.
Un seul endroit me dérange beaucoup - le décompte final de l'argent gagné (vous pouvez voir ce moment à la fin de ma démo vidéo ci-dessus). Je l'ai raccourci dès que j'ai pu, mais cela prend encore un peu plus de 4 secondes (le clavier disparaît, l'inscription victoire apparaît, les kopecks comptent, la table des records est quittée, la plaque signalétique "New Recorder" est affichée, le bouton "Plus" est affiché).
La meilleure «source de jus» pour moi est le module complémentaire gratuit iTween . Je ne peux même pas imaginer comment sans Unity vous pouvez faire quoi que ce soit. Je l'utilise partout où au moins une sorte d'animation est nécessaire (que ce soit une animation d'un bouton ou l'apparence d'un élément de menu ou une animation de compter les cents).
J'ai essayé d'implémenter quelque chose de similaire par moi-même sur la base des coroutines et Mathf.Lerp ou Mathf.MoveTowards, mais ce n'était pas flexible et pas universel (et parfois cela fonctionnait différemment dans l'éditeur et sur l'appareil). Alors maintenant, je n'essaye pas de réinventer la roue, j'apprécie juste iTween.
Il y a des pièges dans ce système d'animation, avec lequel j'ai initialement mal combattu:
- Si pendant le travail d'iTween pour cacher un objet (via SetActive (false) , par exemple), puis le montrer à nouveau, iTween continuera à être exécuté à partir de l'endroit interrompu.
- Si pendant le fonctionnement d'un iTween vous en démarrez un autre (qui affecte les mêmes valeurs), alors à la fin de l'exécution des deux, l'objet peut ne pas revenir à sa position d'origine.
- Vous devez savoir sur quel GameObject lance iTween et sur quelle animation il fonctionne.
Par exemple (selon le dernier point), l'objet A démarre iTween pour qu'il fonctionne sur l'objet B. Pour arrêter l'animation iTween, vous ne pouvez pas simplement démarrer iTween.Stop () sur l'objet A. Vous devez démarrer iTween.Stop (objet B).
La force d'iTween est sa capacité à utiliser différents types d'assouplissement. Ising est un paramètre qui adoucit le mouvement (pour qu'il ne démarre pas saccadé et ne se termine pas bêtement).
Les types impressionnants de trouvailles sont pour moi:
- printemps
- aisanceOutBond
- easInBack
- aisanceOutÉlastique
Pour trouver le bon ising, j'utilise la démo visuelle Easing (j'ai besoin d'un flash). Et ici, je prends la documentation pour tous les types d'animations iTween .
Les statistiques d'Apple et de Google sont bonnes, mais Unity Analytics est mieux
Même grâce à l'expérience des jeux précédents, je savais qu'avoir ses propres statistiques était très cool. Au début, je voulais créer une sorte de système de journalisation, mais ensuite je me suis souvenu d' Unity Analitics . Et quelle a été ma surprise quand il s'est avéré que la version gratuite des fonctionnalités de mon boîtier n'est limitée par rien. J'aurais pire si j'avais une sorte de monétisation, alors les outils d'analyse ne sont disponibles que pour les abonnés Pro.
En intégrant simplement Analytics.CustomEvent au bon endroit dans le code, je peux suivre les exemples les plus populaires, le nombre d'enfants qui résolvent des exemples dans les premiers jours ou après un certain temps, etc.
Je peux comparer les données de différentes plateformes (iOS et Android) en un seul endroit.
Et combien de choses y sont intéressantes, ce que j'aimerais essayer, mais toutes les mains n'atteignent pas. Tapez Paramètres à distance (modification du contenu de l'application sans mise à jour) ou Test A / B ou Gestionnaire de didacticiels .
Visual Studio comme Sublime
Dans le passé, lorsque j'avais besoin de modifier du code (que ce soit python, html ou node.js), j'utilisais Notepad ++ (entièrement gratuit, mais uniquement sur Windows) et Sublime Text (payé pour tous les systèmes d'exploitation, mais vous pouvez l'essayer gratuitement )
Dans Unity, j'étais assis sur MonoDevelop, mais il en avait tellement marre de mes problèmes (comme l'impossibilité de basculer entre les mises en page ou de coller quelque chose copié en dehors de Mono) que j'ai décidé qu'il était temps de laisser tomber le navire en perdition et de grimper sur Visual Studio Community 2017 (bon, c'est gratuit pour les développeurs uniques comme moi).
Pour les développeurs sur Unity 2018, cela n'est pas pertinent pour le moment, car le code Visual Studio multiplateforme est inclus dans la version 2018. Mais je voulais que mon application fonctionne sous iOS 7 (puisque l'iPhone de ma fille est avec cet iOS), j'ai donc dû utiliser n'importe quelle version d'Unity antérieure à 2018.
Cela m'a aidé avec la transition vers VS video Comment configurer Visual Studio avec Unity .
De la boîte, VS n'a pas tous les trucs sympas auxquels je suis habitué dans d'autres éditeurs, donc j'ai simplifié ma vie:
- activé la mini-carte au lieu d'un simple défilement vertical:

- a ajouté l'extension SemanticColorizer , qui permet une personnalisation plus flexible des couleurs du code. Plus précisément, j'en avais besoin pour distinguer les variables globales des variables locales par couleur.
- installé l'extension Match Margin , qui sélectionne le mot sous le chariot et toutes ses copies en fonction du texte du code, et le fait également sur la minicarte. C'est très pratique pour une navigation rapide dans le code, pour trouver tous les endroits où une méthode ou une variable est utilisée:

- J'utilise Strip'em pour corriger automatiquement les fins de ligne.
Mes scripts pour cette application sont sur GitHub. Il n'y a que mes scripts , et pas l'ensemble du projet Unity - désolé, si cela les rend impossible à comprendre. Jusqu'au dernier moment, je n'avais pas prévu de donner un lien vers les sources, car je ne considère pas que mon code mérite qu'on s'y attarde. Mais il a ensuite changé d'avis en raison de la possibilité que des développeurs plus expérimentés puissent signaler mes erreurs.
C'est la fin de la première partie. Continuez à lire dans la deuxième partie , où je dirai:
- À propos de l'écriture de code
- À propos du contrôle de version
- À propos du doublage
- À propos de l'icône
- À propos d'Android Build
- À propos de la construction pour iOS
- À propos du titre et de la promotion
- Statistiques
- Ce que je regrette
- Ce qui a compris
Les références
Liste des liens du corps de l'article dans l'ordre de leur mention:
+
Classe FTP C # simple.+
ID de session pour iOS.+
Nous écrivons correctement le plugin pour Unity. Partie 1: iOS .
+
Méthodes de sérialisation des objets en JSON (aide officielle).
+
ScriptableObject (aide officielle).
+ Tutoriel
vidéo Architecture de jeu avec des objets scriptables (
code ).
+ Atelier
renversant la tyrannie MonoBehavior dans une révolution glorieuse d'objets scriptables (
code ).
+
Démonstration vidéo de mon application dans l'éditeur .
+
Plugin Anima2D gratuit
pour l'animation squelettique de personnages 2D .
+ Bibliothèque gratuite pour la localisation d'applications -
Localisation Lean.+ Vidéo sur les astuces qui améliorent la perception du jeu
Juice it or lost it .
+ Vidéo sur les techniques d'animation subliminales
L'art du shake .
+
Système d' animation
iTween gratuit mais puissant.
+
Démonstration visuelle
des types ising (besoin d'un flash).
+
iTween (aide officielle).
+
Unity Analitics .
+ Éditeurs de texte
Notepad ++ et
Sublime Text .
+
Visual Studio Community 2017 et
Visual Studio Code .
+ Tutoriel vidéo
Comment configurer Visual Studio avec Unity .
+ Plugin
SemanticColorizer (pour les paramètres de couleur du code).
+ Plugin
Match Margin (sélectionne le mot sous le chariot et toutes ses copies).
+ Plugin
Strip'em (auto-correction des fins de ligne).