I'm trying to use 2d Sprites inside a 3d world and having some problems getting them just right... I already tried 2 aproaches to have the Sprite inside the world correctly but both have their own problems.
I tried to rotate the Sprite on the x-axis just into the angle my camera is, this works nice and results in a pixel perfect sprite if camera is setup correctly... until you set something behind the character like in the picutre below... I tried to use the sortinglayer on the ground and sprite without any effects... so I went to another solution
Instead of rotating the sprite on the x-axis I used a scale of 1.1657f (dimetric angle...) on the y-axis resulting in everythin working as expected, expect the sprite starts to jiggle while moving the camera and its far away from beeing pixel perfect...
so i want to stick to methode 1. but I don't know how to prevent the sprite begin inside the stuff that is "behind" it...
Btw i know on both screenshots the red rectangular is not pixel perfect ^^
I am fairly certain this can be achieved using a custom projection matrix. You need your frustrum to be parallelepipedoidal. I find this question interesting and am trying to do that matrix in Unity. I'll post it here as an answer when I'm done if nobody else did.
Just to let you know: I posted my answer on saturday. It might eventually be approved by a moderator (probably tomorrow).
Answer by Bodrp
Apr 17 at 07:16 PM
What you want to achieve is doable using a custom projection matrix. The one we used must be parallelepipedoidal, as mentioned in my comment earlier. To picture it, first look at an orthogonal camera frustrum in Unity (that white box that appears in front of the camera when you select it and its projection setting is set to "orthogonal"). Now, imagine you take the far side of that box and drag it down. Here is a quick drawing illustrating the concept:
You have a 3d object (blue square) and a sprite (blue line) illustrated. The dotted grey lines are how vertices are projected upon the screen depending on if you use an orthogonal or custom projection matrix. As you can see, with an ortogonal matrix, you wouldn't see the floor at all, or any flat surface parallel with the X-Z plane. With the custom matrix, not only you can see those surfaces (notice how the 3d object is projected) but every vertical surface is still seen as vertical. This means that your world can be as it is supposed to be, without strange rotation hacks, and you can still see stuff as you want to see it.
The kind of result I got with three planes and a sprite (purposefully going through planes to show it has normal rotation values):
And this would be my projection matrix for the above screenshot:
0.18 0 0 0
0 0.1 0 0
0 -0.04 -0.02 0
0 0 0 1
You can instantiate a Matrix4x4, use SetRow(), SetColumn() or give your matrix the [SerializeField] attribute and assign it these values, then tweak them to get the intended result. Then you can assign that matrix to the projectionMatrix property of your camera.
The key value in the matrix is that -0.04. This is what allows for an isometric view with a perfectly horizontal camera. It's a way of using the Z value of a given point to affect the Y value where it will be projected.
I made these two simple files you could use when you are ready. The first one is to be put on your camera game object as a component. It exposes a matrix and updates the camera's projection matrix every frame.
public class ProjectionMatrixTester : MonoBehaviour
[SerializeField] Matrix4x4 matrix;
camera = GetComponent<Camera>();
camera.projectionMatrix = matrix;
matrix.SetRow(0, new Vector4(0.09f, 0, 0, 0));
matrix.SetRow(1, new Vector4(0, 0.05f, -0.02f, 0));
matrix.SetRow(2, new Vector4(0, 0, -0.02f, -1));
matrix.SetRow(3, new Vector4(0, 0, 0, 1));
This second file changes the way the matrix is shown in the inspector. It shows it as it is supposed to be. It has to be placed in a folder named Editor.
public class MatrixPropertyDrawer : PropertyDrawer
const float CELL_WIDTH = 48;
const float CELL_HEIGHT = 16;
public override void OnGUI(Rect pos, SerializedProperty prop, GUIContent lab)
position = pos;
property = prop;
label = lab;
EditorGUI.BeginProperty(position, label, property);
public override float GetPropertyHeight(SerializedProperty p, GUIContent l)
return 5 * CELL_HEIGHT;
EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);
position.y += CELL_HEIGHT;
EditorGUI.indentLevel = 0;
for (int r = 0; r < 4; r++)
for (int c = 0; c < 4; c++)
void DrawCell(int column, int row)
Vector2 cellPos = position.position;
cellPos.x += CELL_WIDTH * column;
cellPos.y += CELL_HEIGHT * row;
new Rect(cellPos, new Vector2(CELL_WIDTH, CELL_HEIGHT)),
property.FindPropertyRelative("e" + column + row),
Really nice answer and should be the way to go. In the end i did a dirty little camera hack and instead of using real isometric angles i moved the x angle of the camera to 25 instead of 30 while having the sprite in the same angle... and at least for the moment i have no clipping of sprites into 3d objects while still looking isometric-ish... good enough for a prototype :D But i will definitely try the projectionMatrix solution
Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.
The best place to ask and answer questions about development with Unity.
To help users navigate the site we have posted a site navigation guide.
If you are a new user to Unity Answers, check out our FAQ for more information.
Make sure to check out our Knowledge Base for commonly asked Unity questions.
If you are a moderator, see our Moderator Guidelines page.
We are making improvements to UA, see the list of changes.
Answers and Comments
5 People are following this question.
New sprites in 2D projects only? Cannot add in 3D project
How to make 3D colliders on sprites?
Isometric projectile collision 2D or 3D?
Looking for a simple way to Add an Image or text to a 3d Model
Sprites: Project Sprite to Mesh, allow for bending of sprites for 3d environments