What is the best way to display 3D models as UI elements?

Viewport mask problem might be caused by the shader. Only UI specified shader can apply the mask effect I think.

Just finished searching Google Images and YouTube to see the examples you mentioned and frankly I don’t see how you would come to the conclusion that they’re realtime rendered at all. One of the newest videos I watched is only nine hours old and the inventory is basically just static images.

Maybe my mistake. But from my experience of making gun mods, I don’t find a place to put the static preview pictures. I think those are rendered later in game using customized shader. However, one thing you are correct, because all those are static, render textures are ok to help. You don’t have to create too many cameras at the same time.

I’ve found a solution that doesn’t involve render textures nor World Space Canvas!
I had the same problem and came up with a ‘creative’ solution. I use a dual camera setup: One camera for my Canvas (which is set to Screen Space: Camera) and one camera for the rest of the game. Now follow these steps:

  • Make the 3D object a child of the canvas.
  • To deal with the anchoring, use a parent RectTransform above the 3D object.
  • The 3D object will look strange on the canvas, stretched near the edges of the screen. This is because of the perspective of the camera. I don’t want to use an orthographic camera, so I just reduced the FieldOfView attribute of my UI camera to 1.

Here’s a screenshot of the scene view of my inventory with a 3D cube in it:

4 Likes

Can the 3d objects be arranged correctly in a scroll view? Is this method “Mask-Friendly”?

Unfortunately, no. I want to do that too – but I have a backup plan!
Use another camera that will render all the content of the scroll view into a single render texture. A render texture is a flat image, and images are “Mask-Friendly”!
If you need to interact with the 3D objects (buttons), you can make all 3D objects invisible (by disabling their renderer) and draw the masked render texture on top of them.

Perfect, thanks a lot, just what I was Looking for :slight_smile:

Thanks for that, works perfectly

Hey guys,
I want to make something like Asset Forge object select menu as you see at left side of the screen.
There are too many objects and they are rotated around themself.
I want to use multiple camera and create RenderTexture and put it in RawImage but I think there is performance problem.
So I want to know what is your suggestion ? And it is really unoptimized to use multiple camera and RenderTexture ?

Well, unoptimized depends on how many objects you want to display and how big/crisp the render textures need to be. It can definitely perform quite badly when having multiple, larger render textures displayed at once.

So - what if you do want animating 3D objects in the UI? It’s 2020 after all :slight_smile:

Edit: I’ve got a UI camera, and a 3D object as a child of a canvas set to Screen Space-Camera.

It renders, however - for the object to be visible, the scale of the 3D object needs to be x1000 or something - is there any way to avoid the scale issue? It seems messy as hell.

I set up 3D objects in UIs that respect masking here. I have a ‘portal’ quad with a shader that sets a bit in the stencil buffer, then the 3D objects have another shader that only renders where that stencil bit is set.

IINM, this is what the UI shaders do already… I think they use the first bit of the buffer, but I haven’t had much luck making it work directly with UI mask objects. What I did instead was have my portal quad set the 2nd bit of the stencil buffer, and any 3D objects I want to mask to the portal use a portal-object shader that tests against the 2nd bit.

You also have to tinker around with the shader render queues a bit. It’s a bit fiddly so I don’t think I can be much more specific than this.

The advantage of this method is that it doesn’t use separate cameras or render textures. Back in KSP the parts menu used separate cameras and RTs, but this time I needed the menus to also be VR friendly, so the stencil buffer solution was a much better choice.

The rendering setup is largely unaffected, and the menu can also work in a worldspace canvas (the 3D elements are actually 3D, which looks neat in VR).

Cheers

1 Like

Upon scan target Image, I have to show the 3D Animation Model along with Information in Text format.
In this case I am trying to use the UI–>Panel to display 3D Animation along with Text information but 3D Animation model is not displaying and not working as expected n run time.

Could anyone guide me the right approach.

Cheers

Love the 2015 Karl Solution with the render texture, works nice – but still struggling when having multiple 3D objects (in a menu, for example). Do I have to create cameras and render textures for each 3D object? Or is there an more efficient way? (I tried to change the target texture of the camera by script and activating and deactivating the 3D object, but, oh well… I would not post here if this would have worked out)

Wow I can’t even remember creating that now :wink:
If you have multiple objects then it really depends on if the objects are animating. If they are static and not moving then rendering them to a texture once and using that should be all you need. If they are moving then you could setup a camera for each. I found this example that may help https://unity.grogansoft.com/in-game-security-camera-using-render-texture/

2 Likes

Thanks for your super fast reply! I did a setup with a camera for each object then. Works. Performance is also not much of an issue (it’s a menu scene anway, without gameplay). Thanks again!

1 Like

Hiya, is it possible to have a character animate in a pause menu? Getting the character in the UI isn’t the tough part in 2021 but how to you have it animated with timescale=0? Unscaled time? Think of recent titles like Surge 2 here, where you pause the game to bring up the Gear menu, with the animated 3d character.

I don’t know how much rewrite this would be, but I use a bool isPaused. Then only execute code based on this. Most of the update() don’t run and objects go static based on isPaused. I know dark souls keeps the game running in the menus.

I agree, timescale = 0 seems like an easy solution for a pause but can lead to a of problems. That aside and if you just want some animations: the unity Animator works with timescale = 0, just set the animation to “Unscaled Time”.

a few years late but i didnt seem to see anyone suggest how to go about this using render textures. So basically you will need to make a function that outputs a texture2d and to do this use the following code.

    public Texture2D IconGen(RenderTexture renderTexture)
    {
        Texture2D newTexture = new Texture2D(renderTexture.width, renderTexture.height, TextureFormat.RGBAFloat, false, true);
        RenderTexture.active = renderTexture;
        newTexture.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0);
        newTexture.Apply();

        return newTexture;
    }

What this will do is read the pixels from your render texture, you will need to instantiate your object in front of the camera and then it will make a new texture 2d from that render texture. Finally just return the new texture 2d and use the new texture for whatever your using it for. I suggest having a Ienumerator that yields for a frame in between instantiating the object and creating the texture otherwise you may just get a blank texture. Also you may want to implement a list of items to make textures for so that your not instantiating all your objects at one time otherwise youll be left with an icon thats just a mixture of gameobjects. I suggest at some point in your game running Resources.UnloadUnusedAssets() because even though you will be destroying your game objects for some reason they still are stored in memory and your ram usage will slowly begin to grow

1 Like