9
votes

Unity3d, construire PNG du panneau d'une unité.UI?

Pensez à n'importe quel Unity.UI Canvas Vous pourriez avoir.

Imaginez un panneau typique sur cette toile. Dis que cela arrive à contenir des images, peut-être du texte et ainsi de suite.

Ce serait très pratique si vous pouviez transformer ce panneau (uniquement le panneau) dans une capture d'écran: une texture2D ou PNG.

La seule chose que je peux penser consiste à utiliser Readpixels et à déterminer la zone du panneau en question sur l'écran (et réellement assez délicat); et cela ne fonctionne que si le panneau se trouve être carré et non pivoté à un angle.

Vous penseriez, il devrait y avoir un moyen de rendant un panneau, au moins une toile entière? Je ne peux rien trouver.

 Entrez la description de l'image ici

 Entrez la description de l'image ici

Dans l'exemple, faites un panneau rose une image PNG. Ouch.

(Évidemment, si quelqu'un a une solution qui ne fait que "toute la toile", plutôt qu'un panneau, bien sûr, même cela est admirable.)


6 commentaires

Cela semble réellement compliqué. Prendre la capture d'écran est une chose que la capture d'écran d'un panel est une autre histoire. Lorsque votre SAite Capture d'écran d'un panneau, voulez-vous dire UI qui est un enfant du panneau?


Voulez-vous dire TOUT UI dans le panneau.?


Droit - un panneau, c'est-à-dire un CanvasRenderer , connu sous le nom de "Panneau" lorsque vous en faites une utilisation du menu ou du menu contextuel "Créer -> UI" .... image ajoutée!


Ah d'accord. Je verrai si je peux retirer ça.


Il suffit de poster ma solution avec un exemple de travail. Cela fait du travail. Je passe du temps à essayer de supprimer des bugs. Si vous trouvez un bogue, vous pouvez corriger et mettre à jour ma réponse.Votre travail est maintenant d'optimiser ....


@Programmer incroyable, je vérifie maintenant !!!


3 Réponses :


1
votes

Ceci est juste un petit coup de poing car je ne trouve aucun moyen officiel facile de le faire.

Je n'ai aucune idée de la performance intensif que ce serait depuis que je ne l'ai pas essayé.

Ajoutez une caméra, pointée sur le panneau d'interface utilisateur pour obtenir un coup droit. Rendez la caméra à une texture, avec seulement ce panneau étant rendu sur la caméra, détruisez la caméra.

puis coder la texture à un PNG .

  1. Cela pourrait être horriblement chère.
  2. Cela rendrait également le reste de l'écran à moins que vous saze. appareil photo sur le panneau, et même si le panneau n'est pas un carré ou Rectangle, vous aurez une partie du jeu / Skybox / Couleur de fond dans le coup.
  3. Cela pourrait tout simplement pas fonctionner

0 commentaires

1
votes

Je n'ai pas examiné profondément, mais je suppose qu'il est impossible de rendre un panneau sans rendre sa toile mère. Je suppose que vous ne voulez pas faire toutes les images, mais seulement à certaines occasions.

Dans ce contexte, voici ce que je voudrais essayer:

  • Avoir une seconde toile avec RenderMode « l'espace de l'écran - appareil photo ». Cela vous permet de spécifier la caméra utilisée pour rendre cette toile.
  • Avoir un appareil photo dédié à rendre votre deuxième toile.
  • Donne la caméra un script qui gère OnPreCull et OnPostRender
  • OnPreCull, fixer le panneau cible sur votre toile secondaire. OnPostRender, rattachez à l'endroit où il était avant (je suis si désolé ...)
  • Laissez le rendre appareil photo secondaire sur un RenderTexture
  • ReadPixels, Appliquer, EncodeToPNG, le tour est joué

    Bien sûr, il y a beaucoup de détails non spécifiés, comme la taille et les positions et tout. Mais après avoir consacré toile et appareil photo devrait permettre tout cela à compris et correctement configuré sans substance chambouler.


11 commentaires

"Mais seulement à des occasions spécifiques.", juste certainement - seulement comme un off. Je vais étudier votre méthode!


Oh, il serait peut-être que surprendender est déjà trop tard pour que le panel soit en réalité inclus dans le rendu. Je vais changer ma réponse pour suggérer surprecull.


Je pense que l'aperçu de la clé pourrait être que, essentiellement, vous avez besoin d'une autre caméra avec un duplicata du panneau en question (qui, après tout, n'est pas si difficile à organiser). C'est peut-être la solution de baiser.


@JoeBlow, j'ai travaillé sur cet hier, c'était la première idée qui s'est venue à ma tête. Le mien était légèrement différent. J'ai essayé de dupliquer le GameObject, créez une nouvelle caméra puis déplacez l'interface utilisateur et la caméra vers une autre position et prenez l'image. Cela n'a pas fonctionné parce que l'interface utilisateur déménageait mais la caméra a refusé de bouger avec l'interface utilisateur. J'ai essayé d'utiliser un masque de calque et d'abattage, mais il y avait trop de problèmes que j'ai rencontrés et vous devez créer une nouvelle couche de l'éditeur pour y travailler. Vous ne pouvez pas créer de calque à partir du code .... Je veux quelque chose de simple. Enfin je l'ai eu pour travailler. Je l'améliore avant de poster.


Bien que le code soit plus long que le code source Stackoverflow.


C'est une idée brillante d'utiliser couches Je ne l'ai tout simplement pas pensé. Je veux dire que c'est bien si vous "devez avoir" une couche dans le projet à cet effet, c'est génial. Grande pensée !!! @Programmeur


En fait, vous n'avez pas besoin de créer des couches du tout, une couche n'est rien de plus qu'une valeur pour le champ de couche de GameObject, comprise entre 0 et 31. Il suffit de la définir sur une valeur libre. Ensuite, définissez simplement la couche de fond de caméra sur 1 << (couche) et vous devriez être tout bon.


Lol je me souviens que cette balise est quelque chose que vous ne pouvez pas créer par code non calque. Ma faute. Il y a un problème avec l'interface utilisateur de l'unité. Le calque ne fonctionne pas avec elle à moins que vous ne changiez le mode de rendu de la toile. Cela signifie donc que vous devez faire boucler toutes les toiles activées dans la scène et modifier chaque mode de rendu, puis mettre la caméra principale dans la propriété « Render Camera » de chaque Canvas dans l'autre pour l'abattage. Jusqu'à ce que cela soit corrigé pour l'interface utilisateur, je ne pense pas que ce sera rapide.


Remarque .... la vitesse n'est pas une exigence ici. C'est très quelque chose comme, imaginez que l'utilisateur final peut assembler une petite image (peut-être avec du texte, etc.), puis cliquez sur "Générer PNG!" (Imaginez-vous dire le courriel pour elle-même). Donc, tout ce que vous avez, c'est génial!


@JoeBlow ne le savait pas. La vitesse de pensée est une exigence et devait supprimer mon premier code qui a fonctionné mais lent.


Hmm, vous devriez peut-être ramener cela aussi! :)



9
votes

Le code ci-dessous peut prendre une photo d'une toile. La toile doit être attachée à l'objet que vous y passez. La seule fonction à appeler est Void Demencreenshot (Canvas CanvaSpanel, CaptureHotType Screenshottype = Screenshottype.Image_and_text, Bool Creeenewinstance = true)

Screenshot_type.Image_and_text Paramètre prendra l'image de < Strong> images et textes .

screenshot_type.image_only Paramètre ne prendra que l'image de images . Chaque textes à l'écran sera exclu. Vous pouvez l'utiliser pour une raison de sécurité pour supprimer les textes et montrer uniquement des graphiques uniquement.

Screenshot_type.text_only Paramètre prendra une image de Textes seulement.

Comment utiliser. Créez un GAMEObject, joignez le script de Canvasscreenshot. Abonnez-vous à Canvasscreenshot.onpicTureakaken (Byte [] PNGARRAY) ;, puis appelle Capture d'écran.Takescreenshot (Canvastosreenshot, capture d'écran_type.Image_and_text, false);

< Strong> Code complet:

Votre Test.cs.CS Script: xxx

Le Canvasscreenshot. CS script: xxx


7 commentaires

Lorsque vous avez fini de tester, vous me laissez s'il y a un problème


Cela semble fonctionner très bien. Je ne pense pas que rien d'autre puisse être demandé! Superbes trucs!


Heureux que j'ai pu aider. En parlant de votre commentaire sur l'apport de l'ancien code, il est parti. Je l'ai sélectionnée et les a supprimés et a tout supprimé avec le code ci-dessus, après avoir pensé que la performance est une exigence. Je ne pense pas que je sois jamais capable de le récupérer car j'ai fermé le studio visuel et rouvert ce. Un-do est parti .....


Je sais que c'est vraiment vieux mais voilà - puisque vous passez toute la toile au script, comment enregistre-t-elle seulement une partie spécifique de la toile à l'image? En outre, j'ai essayé ce script et la capture d'écran qui est sauvée, a également un sprite qui fait partie de la scène mais pas sur la toile. J'utilise l'unité 5.3.2. Toute aide est vraiment appréciée car je me brise la tête à ce sujet longtemps.


@TheDevilsfire qui n'est pas un bug. Quand j'ai écrit cela, je voulais seulement exclure d'autres canevas d'interface utilisateur. Je n'ai pas fait exclure Sprite ou 3D Objets / Mesh Renderer, mais vous pouvez mettre en œuvre que ce code est de masquer d'autres objets, de prendre une photo, de les cacher, de les masquer, puis de renvoyer la photo prise. Vous pouvez l'étendre pour inclure Sprite et des objets 3D / Mesh Renderer.


@Programmer Travail - fera cela, mais l'autre problème est comment puis-je spécifier une partie de la toile qui doit être sauvegardée et ne pas sauvegarder l'ensemble de la toile?


@TheDevilsfire ceci a été fabriqué pour la toile. Donc, une toile au milieu ou le coin de l'écran peut avoir leur image prise sans autre interface utilisateur dans d'autres toiles. Pour faire ce que vous demandez, vous devrez ré-écrire tout le script. Vous pouvez le faire si vous comprenez comment cela fonctionne. Il cache une autre interface utilisateur d'autres toiles, prend une photo, les affiche et retourne la photo prise. Vous pouvez facilement mettre en œuvre cela pour vos besoins. Il existe de nombreuses fonctions importantes qui sont réutilisables dans mon code.