• Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
2
Question by chrisWhyTea · Apr 13, 2017 at 07:49 PM · camera2dsprite3disometric

pixel perfect 2d Sprite in 3d world with isometric camera, how to do it right?

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.

  1. 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... alt text I tried to use the sortinglayer on the ground and sprite without any effects... so I went to another solution

  2. 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... alt text

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 ^^

unity-2017-04-09-22-59-17.png (34.7 kB)
unity-2017-04-09-23-02-53.png (34.5 kB)
Comment
Add comment · Show 2
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Bodrp · Apr 15, 2017 at 02:24 PM 2
Share

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.

avatar image Bodrp · Apr 17, 2017 at 02:13 PM 0
Share

Just to let you know: I posted my answer on saturday. It might eventually be approved by a moderator (probably tomorrow).

1 Reply

· Add your reply
  • Sort: 
avatar image
5
Best Answer

Answer by Bodrp · Apr 17, 2017 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:

orthogonal and custom projection

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):

projection test

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.

[EDIT]

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.

ProjectionMatrixTester.cs

 using UnityEngine;
 
 [RequireComponent(typeof(Camera))]
 public class ProjectionMatrixTester : MonoBehaviour
 {
     Camera camera;
     [SerializeField] Matrix4x4 matrix;
 
     void Start()
     {
         camera = GetComponent<Camera>();
         InitializeMatrix();
     }
 
     void Update()
     {
         camera.projectionMatrix = matrix;
     }
 
     void InitializeMatrix()
     {
         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.

MatrixPropertyDrawer.cs

 using UnityEngine;
 using UnityEditor;
 
 [CustomPropertyDrawer(typeof(Matrix4x4))]
 public class MatrixPropertyDrawer : PropertyDrawer
 {
     const float CELL_WIDTH = 48;
     const float CELL_HEIGHT = 16;
 
     Rect position;
     SerializedProperty property;
     GUIContent label;
 
     public override void OnGUI(Rect pos, SerializedProperty prop, GUIContent lab)
     {
         position = pos;
         property = prop;
         label = lab;
 
         EditorGUI.BeginProperty(position, label, property);
 
         DrawLabel();
         DrawMatrix();
 
         EditorGUI.EndProperty();
     }
 
     public override float GetPropertyHeight(SerializedProperty p, GUIContent l)
     {
         return 5 * CELL_HEIGHT;
     }
 
     void DrawLabel()
     {
         EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);
         position.y += CELL_HEIGHT;
         EditorGUI.indentLevel = 0;
     }
 
     void DrawMatrix()
     {
         for (int r = 0; r < 4; r++)
         {
             for (int c = 0; c < 4; c++)
             {
                 DrawCell(c, r);
             }
         }
     }
 
     void DrawCell(int column, int row)
     {
         Vector2 cellPos = position.position;
         cellPos.x += CELL_WIDTH * column;
         cellPos.y += CELL_HEIGHT * row;
         EditorGUI.PropertyField(
             new Rect(cellPos, new Vector2(CELL_WIDTH, CELL_HEIGHT)),
             property.FindPropertyRelative("e" + column + row),
             GUIContent.none
         );
     }
 }
 



projection.png (4.7 kB)
projection-test.png (31.1 kB)
Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image chrisWhyTea · Apr 18, 2017 at 11:03 PM 0
Share

Really nice answer and should be the way to go. In the end i did a dirty little camera hack and ins$$anonymous$$d of using real isometric angles i moved the x angle of the camera to 25 ins$$anonymous$$d 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 projection$$anonymous$$atrix solution

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Welcome to Unity Answers

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.



Follow this Question

Answers Answers and Comments

5 People are following this question.

avatar image avatar image avatar image avatar image avatar image

Related Questions

New sprites in 2D projects only? Cannot add in 3D project 0 Answers

2D Bring closest spites to front 1 Answer

How can I make a layer black? Unity 2D 1 Answer

3D background effects in a 2D game 2 Answers

Isometric camera with Spritemanager 2 Answers

  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges