Jump to content
Unity Insider Forum
  • Announcements

    • Lars

      Allgemeine Forenregeln   03/13/2017

      Forenregeln Nimm dir bitte einen Moment um die nachfolgenden Regeln durchzulesen. Wenn du diese Regeln akzeptierst und die Registration fortsetzen willst, klick einfach auf den "Mit der Registrierung fortfahren"-Button. Um diese Registration abzubrechen, klick bitte einfach auf den "Zurück" Button deines Browsers. Wir garantieren nicht für die Richtigkeit, Vollständigkeit und Brauchbarkeit der Nachrichten und sind auch nicht dafür verantwortlich. Die Beiträge drücken die Meinung des Autors des Beitrags aus, nicht zwangsläufig das, wofür die Forensoftware steht. Jeder Nutzer, der denkt, dass ein veröffentlichter Beitrag unzulässig bzw. störend ist, ist aufgefordert uns unverzüglich per E-Mail zu kontaktieren. Wir haben das Recht störende Beiträge zu löschen und bemühen uns, das in einem realistischem Zeitraum zu erledigen (sofern wir beschlossen haben, dass die Löschung notwendig ist). Du akzeptierst, durchgehend während der Nutzung dieses Services, dass du dieses Forum nicht dazu missbrauchen wirst, Inhalte zu veröffentlichen, welche bewusst falsch und/oder verleumderisch, ungenau, beleidigend, vulgär, hasserfüllt, belästigend, obszön, sexuell belästigend, bedrohlich, die Privatsphäre einer Person verletzend oder in irgend einer Art und Weise das Gesetz verletzen. Des Weiteren akzeptierst du, dass du keine urheberrechtlich geschützte Inhalte ohne Erlaubnis des Besitzers in diesem Forum veröffentlichst. Mit dem Klick auf den "Mit der Registrierung fortfahren"-Button, akzeptierst du zudem unsere Datenschutzerklärung und stimmst der Speicherung deiner IP-Adresse und personenbezogenen Daten zu, die dafür benötigt werden, um dich im Falle einer rechtswidrigen Tat zurückverfolgen zu können bzw. permanent oder temporär aus dem Forum ausschließen zu können. Es besteht keine Pflicht zur Abgabe der Einwilligung, dies erfolgt alles auf freiwilliger Basis.   Zusatzinformationen Der Forenbetreiber hat das Recht, Nutzer ohne Angabe von Gründen permanent aus dem Forum auszuschließen. Des Weiteren hat er das Recht, Beiträge, Dateianhänge, Umfrage, Blogeinträge, Galleriebilder oder Signaturen ohne Angabe von Gründen zu entfernen. Mit der Registrierung verzichtest du auf alle Rechte an den von dir erstellten Inhalten, bzw. treten diese an das Unity-Insider.de und Unity-Community.de ab. Dies bedeutet im Klartext, dass das Unity-Insider.de und Unity-Community.de frei über deine Texte verfügen kann, sofern diese nicht wiederum die Rechte anderer verletzen. Es besteht weiterhin kein Anspruch von registrierten Nutzern bzw. ehemaligen registrierten Nutzern darauf, dass erstellte Inhalte und/oder die Mitgliedschaft (User) wieder gelöscht werden (Erhaltung der Konsistenz dieses Forums).   Einwilligungserklärung Wenn du mit der Speicherung deiner personenbezogenen Daten sowie den vorstehenden Regeln und Bestimmungen einverstanden bist, kannst du mit einem Klick auf den Mit der Registrierung fortfahren-Button unten fortfahren. Ansonsten drücke bitte Zurück. Stand: 07.03.2011
Sign in to follow this  
Hellhound

Position in RenderTexture auf Objektbasis ermitteln?

Recommended Posts

Hallo zusammen,

aktuell render ich ein 3D Objekt in eine Textur (2048x1600) um es als UI Element anzeigen zu können. Hierfür habe ich ein UI Panel (1400x286) an Position 0,0 mit Pivot 0,0 und mit einem RawImage (2048x1600)  als Kind an Position 653,153 mit einem center Pivot (0.5,0.5) . Sowohl das Panel als auch das RawImage haben Ihren Anchor links unten. Soweit so gut, das Objekt wird wie gewünscht, als UI Element mittig auf dem Bildshirm gerendert. Nun besitzt das 3D Objekt diverse leere Objekte als Transformationspunkte um Mountpoints zu definieren. Meine Ziel ist es nun in der UI auf der angezeigten Textur an der entsprechenden Stelle des Mountpoints kleine Sprites anzuzeigen um diesen zu visualisieren.

Wie mache ich das am besten? Üblicherweise kann ich ja eine Position in der Textur per Raycast ermitteln, wenn ich aus der UI komme, z.B. um eine Kollison mit einem Klick zu ermitteln. Nur wie bestimme ich die Position in der Textur auf Basis des Objektes unter Berücksichtigung der UI-Parent Elemente?  Zunächst habe ich folgendes ausprobiert:

public Vector3 GetUIPosition(Vector3 mountpoint)
{
    RectTransform rect = this.GetComponentInParent<RectTransform>();
    Debug.Log("Preview Rectangle " + rect.sizeDelta.ToString());                                                                       

    Vector2 viewPos = camera.WorldToViewportPoint(mountpoint);
    Debug.Log("Viewport pos : " + viewPos.ToString());

    Vector2 localPos = new Vector2(viewPos.x * rect.sizeDelta.x, viewPos.y * rect.sizeDelta.y);
    Debug.Log("Viewport pos local : " + localPos.ToString());
      
    return new Vector3(localPos.x, localPos.y, 1.0f);
}

Das liefert mir jedoch viel zu große Werte. Irgendwie stehe ich grade auf dem Schlauch und bin dankbar für jede Anregung.

Viele Grüße

Hellhound

Share this post


Link to post
Share on other sites

Also nach meinen Erfahrungen mit der Unity-UI, kann ich nicht empfehlen, die UI und 3D-Objekte innerhalb der Texturen zu mixen. Was ein gangbarer Weg ist, ist die Kopplung eines 3D-Objektes und eines Canvas als Ganzes. Alles andere wird spätestens zu diversen Problemen führen, wenn sich die Auflösung des Spiels verändert (dabei schlägt nämlich der Canvasscaler wieder zu und er verschiebt die Auflösung und die Proportionen seiner UI-Elemente). Dabei ändert sich meist auch die Auflösung und die Proportionen des Canvas in Relation zum Screen. Das führt vermutlich wiederum dazu, daß Ankerpunkte in Relation zu einer Textur des Canvas unterschiedlich berechnet werden müssen und eine korrekte Positionierung aus den Positionen der Objekte der 3D-Szene wird nahezu rechnerisch unmöglich (da man hier nachvollziehen müsste, was der Canvasscaler in Unity intern alles so treibt).

Share this post


Link to post
Share on other sites

Danke für Deine ausführliche Antwort. Könntest Du mir bitte einmal näher erklären was Du mit Kopplung des 3D Objektes und dem Canvas meinst? Irgendwie hast Du mich da grad gewaltig abgehängt ;)

P.S. Letztendlich möchte ich so etwas realisieren: 

Weapon UI

Share this post


Link to post
Share on other sites

Bedeutet eigentlich nur, daß ich empfehle für die Ankerpunkte an der Waffe jeweils ein eigenes WorldSpace-Canvas zu verwenden. Das Canvas wird dabei einfach an die Position des 3D-Modell ausgerichtet und nicht UI-Elemente innerhalb des Canvas.
Die andere Variante wäre ein Overlay-Canvas  und dann versuchen die Panels an die betreffenden Positionen zu setzen, aber hier muss man eben auf die aktuelle Größe des Canvas achten und dann relativ zu den Canvas Koordinaten berechnen. Gleichzeitig muss man natürlich auch die Screenkoordinaten als Relativkoordinaten bestimmen und dann ins Verhältnis zum Canvas setzen. Nachteil der 1. Variante ist, daß wenn man nicht aufpasst natürlich die UI verdeckt werden kann.
 

 

Share this post


Link to post
Share on other sites

Habe die Worldspace-Canvas Variante ausprobiert. Leider kann ich diese nicht nutzen, da das Objekt das in die Textur gerendert wird, rotiert werden kann. Somit kollidiert es ab einem bestimmten Winkel mit dem Objekt und wird dann wie Du schon vermutet hast, vom Objekt verdeckt. Bleibt somit nur Variante zwei, die habe ich jedoch noch nicht ganz verstanden. Sobald ich ein Overlay-Canvas erstelle wird dieses an den kompletten Camera Viewport angepasst nun verstehe ich nicht ganz, wie ich darin die Panels ausrichten soll, relativ zum Objekt ...

Share this post


Link to post
Share on other sites

Du hattest bei deiner Lösung auf jeden Fall den Offset des Canvas nicht beachtet. Das Canvas hat seinen Koordinatenursprung in der Mitte, WorldToViewport() unten links.

Hier sind 2 Varianten, kannst du ja mal testen:

using UnityEngine;
 
 /// <summary>
 /// Place an UI element to a world position
 /// </summary>
 [RequireComponent(typeof(RectTransform))]
 public class PlaceUIElementAtWorldPosition : MonoBehaviour
 {
     private RectTransform rectTransform;
     private Vector2 uiOffset;
     
     /// <summary>
     /// Initiate
     /// </summary>
     void Start ()
     {
         // Get the rect transform
         this.rectTransform = GetComponent<RectTransform>();
 
         // Calculate the screen offset
         this.uiOffset = new Vector2((float)Canvas.sizeDelta.x / 2f, (float)Canvas.sizeDelta.y / 2f);
     }
 
     /// <summary>
     /// Move the UI element to the world position
     /// </summary>
     /// <param name="objectTransformPosition"></param>
     public void MoveToClickPoint(Vector3 objectTransformPosition)
     {
         // Get the position on the canvas
         Vector2 ViewportPosition = Camera.main.WorldToViewportPoint(objectTransformPosition);
         Vector2 proportionalPosition = new Vector2(ViewportPosition.x * Canvas.sizeDelta.x, ViewportPosition.y * Canvas.sizeDelta.y);
         
         // Set the position and remove the screen offset
         this.rectTransform.localPosition = proportionalPosition - uiOffset;
     }
 }

Variante 2:

 //this is your object that you want to have the UI element hovering over
 GameObject WorldObject;
 
 //this is the ui element
 RectTransform UI_Element;
 
 //first you need the RectTransform component of your canvas
 RectTransform CanvasRect=Canvas.GetComponent<RectTransform>();
 
 //then you calculate the position of the UI element
 //0,0 for the canvas is at the center of the screen, whereas WorldToViewPortPoint treats the lower left corner as 0,0. Because of this, you need to subtract the height / width of the canvas * 0.5 to get the correct position.
 
 Vector2 ViewportPosition=Cam.WorldToViewportPoint(WorldObject.transform.position);
 Vector2 WorldObject_ScreenPosition=new Vector2(
 ((ViewportPosition.x*CanvasRect.sizeDelta.x)-(CanvasRect.sizeDelta.x*0.5f)),
 ((ViewportPosition.y*CanvasRect.sizeDelta.y)-(CanvasRect.sizeDelta.y*0.5f)));
 
 //now you can set the position of the ui element
 UI_Element.anchoredPosition=WorldObject_ScreenPosition;

 

Share this post


Link to post
Share on other sites

Ich konnte das Problem lösen. Habe noch einmal auf Deinen ursprünglichen Vorschlag zurückgegriffen und die WorldSpace-Canvas Container genutzt, da ich es mit dem Overlay nicht lösen konnte. Habe im WorldSpace-Canvas für das Image ein Billboard-Rendering eingebaut und den Shader für das Image gemäss dieses Links angepasst. Und siehe da, es klappt. Auch wenn es jetzt organisatorisch etwas unschön ist, das UI-Elemente plötzlich am Objekt sind.

Mountpoints.JPG

Share this post


Link to post
Share on other sites

Ja, ist doch gut. Vielleicht noch drauf achten, das daß Mipmapping bei den Texturen deaktiviert ist (sollte es nicht von Haus aus schon als Sprite markiert sein, da hier denke ich MM bereits ausgestellt ist). Möchte man performancetechnisch den letzten Rest ausquetschen möchte, dann könnte man noch den Billboardrenderer mit einer Textur verwenden, aber das Handling ist etwas kompliziert. Hat den Vorteil das Billboard wird hier über den Shader gedreht und nicht mehr über ein Skript (ich glaube der Renderer selbst dreht das Billboard nicht, aber der Billboardshader ist in Unity verfügbar):
https://docs.unity3d.com/Manual/class-BillboardRenderer.html

Man weisst dem Billboardrenderer eine Wordposition und ein Asset zu. Das Asset enthält dabei die Definition für die Grafik und den Shader. Das Asset muss man über ein Skript erzeugen (ich habe Code dafür wenn es jemand mal brauchen sollte). Macht aber erst wirklich Sinn, wenn du relativ viel solche kleinen Billboardgrafiken darstellen musst, ansonsten lohnt der Aufwand denke ich nicht.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

×