[Unity] Force text re-serialization crash : La solution

Capture d'écran de la fenêtre de crash
Plantage de l’éditeur Unity sur la re-sérialisation en texte

Lorsque vous avez un gros projet Unity entre vos mains et que vous décidez de forcer la sérialisation en texte (Project Settings > Editor > Asset Serialization > Mode: Force Text), il se peut que vous rencontriez un problème de mémoire insuffisante qui fait crasher Unity. Lors du processus de « re-serialisation », Unity charge tous vos assets dans la RAM pour recréer les structures de données du format binaire vers le format texte. Puis arrive le moment tant redouté : l’éditeur n’arrive plus à allouer de la mémoire et crashe !

Ceci est dû pour l’une des deux raisons suivantes :

  1. l’incapacité d’Unity à allouer la mémoire nécessaire due à la limitation des applications 32-bit.
  2. si vous êtes sur Unity 5, bien que l’éditeur soit 64-bit, il n’y a pas assez de mémoire sur votre PC.

Quel que soit le cas, pas de panique ! Vos données n’ont pas été corrompues par le crash vu que le travail se faisait uniquement en RAM. Néanmoins, il se peut que vos derniers changements apportés au projet se soient évanouis dans la nature (parfois, il faut fermer l’éditeur proprement pour s’assurer que des changements sont sauvegardés sur le disque).

Comment remédier à ce problème ?

Pour ma part, la recherche de solution et la résolution m’ont pris un peu plus d’une heure. J’ai passé pas mal de temps sur les forums sans trouver de réelle réponse précise qui n’implique pas le devoir de redéfinir des valeurs et des références qui ont disparu lors de la conversion. Mais de mon côté, j’ai pu trouver une méthode qui permet de faire la conversion sans perte de valeurs et de références !

Je suis trop fort !

Voici donc mon pas à pas :

  1. Déjà, partez d’un projet stable, sans erreur. Corrigez vos bugs avant de convertir les assets en texte.
  2. Archivez votre projet quelque part. Ben oui, c’est important d’archiver avant de faire de opérations dangereuses.
  3. Dans l’éditeur, dans la fenêtre Project, sélectionnez tous vos assets puis exportez-les dans un unitypackage via Export Package…
    • L’export peut prendre plusieurs dizaines de secondes, voire minutes, selon la taille du projet (mon package faisait 750 Mo !)
  4. Mettez votre package pas trop loin, on va s’en resservir souvent pendant le processus.
  5. Supprimez tous vos assets dans Project ! Quand je vous disais d’archiver le projet, ce n’était pas pour rien…
  6. Définissez Project Settings > Editor > Asset Serialization > Mode: Force Text
  7. Double-cliquez sur votre unitypackage depuis l’explorateur et attendez le chargement qui peut prendre du temps.
  8. Désélectionnez tout puis sélectionnez uniquement une partie du package pour l’import.
    • Le but est d’importer petit à petit les assets. À chaque import, Unity va re-sérialiser en texte.
    • Si l’import plante (et donc que Unity crash pour out of memory), c’est parce que vous avez pris trop de fichiers d’un coup. Dans ce cas, réimportez à nouveau en prenant moins d’assets.
    • Vous constaterez très probablement que la console vous signale des erreurs pour classe manquante. Dans ce cas, identifiez un asset ou un groupe d’asset qui contient la classe manquante et importez-le. Très important : lorsque vous avez réglé les problèmes de classes manquantes, il faut réimporter tous les assets à partir desquels l’erreur est apparue dans la console, toujours petit à petit (avec les mêmes sélections), qui sont déjà importés pour recréer les variables et les références qui ont pu se briser.
    • Pour vous aider dans le processus, je vous conseille d’avoir la fenêtre du Gestionnaire des tâches pour voir la taille que prend une sélection d’assets en import pour mieux découper les imports.
  9. Une fois que tout est importé, faites un test. Il ne devrait rien manquer si vous avez tout bien importé / réimporté / réréimporté / …
    • Si vous avez des problèmes de NullPointerException ou des incohérences de comportement dans le test, identifiez l’asset qui lève cette exception ou l’incohérence puis réimportez-le. Ne faites surtout pas la réassignation vous-même, le réimport est censé corriger les problèmes de références manquantes (Missing) et les valeurs qui n’ont pas été bien importées.

Le plus long dans le processus a été, pour moi, d’attendre l’ouverture du unitypackage à chaque import. C’est pourquoi vous devez bien comprendre comment sont rangés vos assets pour bien découper vos imports. Je pense que le mieux est d’importer du plus générique au plus spécifique. Par exemple, importer les scripts des plugins sur lesquels s’appuie votre code, puis petit à petit, importer les prefabs et assets jusqu’à arriver à ceux utilisés dans les scènes. Les scènes doivent d’ailleurs être importés en dernier, il s’agit du bout de la chaîne.

Voilà, j’espère que ça servira à quelqu’un. De mon côté, ça m’a permis de travailler avec Mercurial.

ShellExecuteA n’ouvre pas d’URL sur Windows depuis un logiciel C++

Je viens de passer trente minutes à chercher la solution à un problème empêchant d’ouvrir le navigateur par défaut sur Windows depuis un logiciel C++ via ShellExecuteA(), en l’occurrence, le jeu Esteren : Les Griffes du Seigneur Sorcier dont le kickstarter est toujours en cours au moment où j’écris cet article. 😛

La solution dans mon cas a été de redéfinir le navigateur par défaut, par exemple en passant par Chrome puis en revenant à Firefox. Juste avec cette simple manipulation, le ShellExecuteA() a fonctionné de nouveau. C’est tout !

Et oui, rien à voir avec un bug de votre code, c’est probablement de la faute des autres qui ne font pas bien leur boulot !

Bit Bit Love sur iOS !

Je profite du fait que je sois connecté pour annoncer la sortie de Bit Bit Love sur iOS !

Surpris.

D’ailleurs on peut déjà faire une analyse rapide concernant la vente du jeu entre Play Store & Amazon App-shop des appareils Android et Appstore des appareils iOS.

Plateforme de vente Mise en ligne depuis Ventes réalisées Moyens de communication
Google Play Store 6 mois 46 Réseaux sociaux, contact presse, publicité (100€), amis
Amazon App-shop 6 mois 2 Réseaux sociaux, amis
Apple Appstore 7 jours 324 Amis

C’est triste à dire, mais les chiffres semblent confirmer l’impression générale concernant la différence entre les marchés Android et iOS : les utilisateurs d’Android sont plus sensibles au gratuit (et au piratage) alors que les utilisateurs iOS sont plus enclins à acheter des produits même s’ils sont inconnus. L’analyse peut sembler rapide et approximative mais les ventes sur Appstore en trois jours ont déjà dépassé les ventes totales faites sur Play Store en six mois.

Mon analyse personnelle est que sur Android, la plupart des ventes ont été réalisées grâce aux amis des développeurs et quelques rares exceptions de personnes hors des cercles des développeurs, d’où l’encéphalogramme plat des ventes actuelles sur Play Store.

Et pire, notre jeu n’était même pas visible sur les pages de garde sur iTunes en tant que nouveauté quand nous avions regardé chez nous, ce qui rend le résultat d’autant plus surprenant.

Kickstarter en cours ! Venez me soutenir ! :P

En-tête de la page kickstarter (staff pick!)
On est staff pick, les mecs !

Je voulais juste prévenir ceux qui sont de passage ici qu’un jeu sur lequel j’ai travaillé est en ce moment sur le kickstarter français !

Il s’agit d’une adaptation des Ombres d’Esteren sous la forme d’un jeu de réflexion pour mobile et PC. On va peut-être ajouter, je pense, des stretch goals car le projet est déjà financé à 100% à l’heure actuelle ! (merci à ceux qui ont permis ce résultat !)

En plus, on est staff pick. Je ne sais pas encore ce que cela représente concrètement, à part l’obtention du badge vert.

Lien vers la page : https://www.kickstarter.com/projects/agate/esteren-les-griffes-du-seigneur-sorcier

[C++] Ouvrir le navigateur depuis Cocos2d-x

Il fallait que j’intègre des boutons dans un projet cocos2d-x pour rediriger sur des pages de réseaux sociaux. Mais à mon grand regret, il n’existe pas de fonction préparée dans le framework de cocos2d-x (version 3.2) pour ouvrir une page de navigateur. Il m’a alors fallu l’implémenter moi-même.

Content.

Fort heureusement, des personnes se sont déjà penchées sur la question et une source m’a été particulièrement utile. Pour info, ce qui va suivre pourrait aussi servir à ouvrir des fichiers en local (file://) ou toute ressource pointable par un URI (tant qu’il y a un logiciel qui peut gérer cet URI, of course) ! Mes chers lecteurs francophones (parce qu’aucun anglophone ou autre ne viendrait ici huhu), voici un récapitulatif :

Partie Windows

  • cocos/platform/win32/CCApplication.h
    void Application::openURL(const char* url); // à ajouter parmi les membres publics
    
  • cocos/platform/win32/CCApplication.cpp
    /* Opens URL in browser. */
    void Application::openURL(const char* url)
    {
    	ShellExecuteA(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL);
    }
    

Partie Android

  • cocos/platform/android/CCApplication.h
    void Application::openURL(const char* url); // à ajouter parmi les membres publics
    
  • cocos/platform/android/CCApplication.cpp
    /* Opens URL in browser. */
    void Application::openURL(const char* url)
    {
    	JniMethodInfo minfo;
    
    	if (JniHelper::getStaticMethodInfo(minfo,
    		"org/cocos2dx/lib/Cocos2dxActivity",
    		"openURL",
    		"(Ljava/lang/String;)V"))
    	{
    		jstring StringArg1 = minfo.env->NewStringUTF(url);
    		minfo.env->CallStaticVoidMethod(minfo.classID, minfo.methodID, StringArg1);
    		minfo.env->DeleteLocalRef(StringArg1);
    		minfo.env->DeleteLocalRef(minfo.classID);
    	}
    }
    
  • cocos/platform/android/java/src/org/cocos2dx/lib/Cocos2dxActivity.java
    • À ajouter dans les imports si ce n’est pas déjà fait :
      import android.net.Uri;
      
    • À ajouter dans la classe Cocos2dxActivity :
      public static void openURL(String url) {
      	Intent i = new Intent(Intent.ACTION_VIEW);
      	i.setData(Uri.parse(url));
      	sContext.startActivity(i);
      }
      

Partie iOS (quand j’en aurai besoin :P)

Conclusion

Et voilà ! Désormais, pour ouvrir la page, appelez la méthode openUrl ainsi :

CCApplication::getInstance()->openUrl("http://www.example.com");

Générer un projet Visual Studio Community pour Windows XP

Alors que je devais préparer un exécutable d’un projet sur Visual Studio Community (VS2013), j’ai dû configurer le projet pour que l’exécutable puisse fonctionner sur Windows XP. Les paramètres par défaut provoquent une erreur de type « application win32 non valide ».

Pour corriger cela, il suffit d’aller dans les propriétés du projet et de définir Platform Toolset à Visual Studio 2013 – Windows XP (v120_xp). Ainsi, l’exécutable pourra fonctionner sur Windows XP si toutes les bibliothèques (dll) — telles que les pilotes et le package redistribuable Visual C++ 2013 — ont été installées.

Configuration de projet VS2013 pour Windows XP
Configuration de projet VS2013 pour Windows XP

[Android] .hgignore pour un projet Android Studio

Je mets le contenu du fichier .hgignore que j’utilise pour mes projets sur Android Studio. Je suis parti du .gitignore de base livré avec un nouveau projet dans Android Studio et je l’ai complété en m’inspirant de plusieurs réponses sur Stack Overflow.

À noter que la configuration suivante est réglée pour que le projet soit importé dans Android Studio (Import project (Eclipse ADT, Gradle, etc.)) juste après un clonage, et pas juste ouvert comme un projet existant. L’import créera les fichiers nécessaires tels que les *.iml et ceux du dossier .idea.

syntax: glob

# Android Studio / Gradle files
.gradle
local.properties
.idea
build/

# Built application files
*.apk
*.ap_

# Files for the dex VM
*.dex

# Java class files
*.class

# Generated files
bin/
gen/

# Windows thumbnail db
Thumbs.db

# OSX files
.DS_Store

# Mercurial .orig backups
*.orig

Petit script VB d’export de table Excel vers .txt

Vous avez besoin d’un petit script en Visual Basic pour faire un export simple d’un tableau Excel vers un fichier texte .txt ? Alors j’ai peut-être le script dont vous avez besoin !

Enthousiasmé

Je ne connais pas vraiment VB, mais une lecture rapide de quelques tutoriaux m’a permis de faire ce que je cherchais comme comportement. Ce script fonctionnerait uniquement sur Windows. Voici le résultat :

Sub ExportToTxt()
    Dim sheetName As String
    

    'Enregistrer le nom de la feuille actuelle
    startSheetName = ActiveSheet.Name
    
    
    'Exemples d'utilisation de la fonction WriteInTxtFile
    WriteInTxtFile "Enregistrables", "Registrables", 4
    WriteInTxtFile "Actions des séquences", "Actions", 4
    WriteInTxtFile "Dialogues réponses", "DialogAnswers", 4
    WriteInTxtFile "Localisation", "Localization", 3
    
    
    'Afficher de nouveau la feuille active au début de l'action
    Sheets(startSheetName).Activate
    
End Sub

Public Function WriteInTxtFile(sheetName As String, fileName As String, columnCount As Integer)
    Dim objStream As Object, i As Integer, s As String
    
    
    'Activer la feuille dont on va exporter le contenu
    Sheets(sheetName).Activate
    
    
    'Création de l'objet qui gère le stream de texte à exporter
    Set objStream = CreateObject("ADODB.Stream")
    
    
    'Initialisation
    objStream.Open
    
    
    'Redéfinir la position ainsi que l'encodage en UTF-8
    objStream.Position = 0
    objStream.Charset = "UTF-8"
    
    
    'Démarrer en ligne 2 (la première ligne étant un en-tête dans mon document Excel)
    For r = 2 To Range("A1048576").End(xlUp).Row
        s = ""
        c = 1

        'Construire la ligne sous forme de string
        While c <= columnCount
            s = s & Cells(r, c)
            
            If Not c = columnCount Then
                'Ajouter le contenu de la cellule au string ainsi que le séparateur de cellule (ici une tabulation)
                s = s & vbTab
            End If
            
            c = c + 1
        Wend
        
        'S'il n'y a pas que des cellules vides dans la ligne, ajouter cette ligne dans le stream
        If Not Len(s) = columnCount - 1 Then
            'Ajouter le carriage return (nouvelle ligne façon Windows)
            s = s & vbCr & vbLf
            
            
            'Écrire dans le stream
            objStream.WriteText s
        End If
    Next r
    
    
    'Enregistrer le fichier texte final à côté du document Excel ouvert
    objStream.SaveToFile ActiveWorkbook.Path & "/" & fileName & ".txt", 2
    
    objStream.Close
End Function

Il est probable que le code puisse être optimisé pour être exécuté plus rapidement. Néanmoins, il me suffit dans son état actuel pour exporter mes fichiers.

À noter que ce script s'exécute sans problème lorsque le document est ouvert dans LibreOffice Calc (toujours sur Windows).

Configuration de l’iPhone 3G pour la 3G et les MMS de Prixtel


Important : ces informations de configuration ne concernent pas les forfaits récents (datant de 2014 et suivants). Pour ces forfaits récents, les informations par défaut dans la puce SIM sont les bonnes.


Jusqu’à présent, je n’avais pas besoin de la 3G. Et je n’ai toujours pas besoin de la 3G. « Mais pourquoi aurais-je besoin de le configurer », me diriez-vous ? À cette question, je vous répondrais que ce n’était qu’un effet collatéral d’une autre recherche, celle de la configuration de la réception et de l’envoi de MMS.

Étonné

La configuration du réseau MMS et 3G pour l’opérateur Prixtel ne fut pas de tout repos. Au terme de longues heures de recherches, d’impasses de tutoriels et autres inexactitudes, je me permets de vous apporter la solution tout en espérant que vous n’avez pas perdu trop de temps à chercher l’information.

  1. Ouvrez l’application Réglages.
  2. Naviguez vers Général > Réseau.
  3. Désactivez les options Activer la 3G et Données cellulaires si vous ne voulez pas entamer votre consommation Internet tout de suite.
  4. Naviguez dans Réseau de données cellulaires.
  5. Indiquez ces paramètres dans les champs du panneau :
    Données cellulaires

    Nom du point d’accès internet69
    Nom d’utilisateur
    Mot de passe

    MMS

    Nom du point d’accès mms69
    Nom d’utilisateur
    Mot de passe
    MMSC http://mms69
    Proxy MMS 10.143.156.12:8080
    Taille max. des MMS 614400
    MMS UA Prof URL
  6. Redémarrez l’iPhone 3G.
  7. Si quelqu’un vous a envoyé un MMS récemment — il y a quelques minutes tout au plus —, vous devriez le recevoir assez rapidement. Si vous ne le recevez pas, il faut probablement activer le Service MMS qui se situe dans Réglages > Messages.

Ce qui est étonnant, c’est que pour recevoir les MMS sur mon iPhone 3G, il m’a fallu configurer la partie Données cellulaires alors que rien n’en indiquait le besoin.