정현우
정현우

Reputation: 31

Particle system rendering behind another GameObject

First, I want you to understand my English.

I manually change the camera's projection to orthographic using the source code. Please refer to the code below.

using UnityEngine;
using System.Collections;

public class CameraOrthoController : MonoBehaviour
{
    private Matrix4x4 ortho;

    private Matrix4x4 perspective;

    public float near = 0.001f;

    public float far = 1000f;

    private float aspect;

    public static CameraOrthoController Instance
    {
        get
        {
            return instance;
        }
        set { }
    }

    //-----------------------------------------------------
    private static CameraOrthoController instance = null;
    //---------------------------------------------------
    // Use this for initialization
    void Awake()
    {
        if (instance)
        {
            DestroyImmediate(gameObject);
            return;
        }

        //  이 인스턴스를 유효한 유일 오브젝트로 만든다
        instance = this;
    }

    private void Start()
    {
        perspective = Camera.main.projectionMatrix;
    }

    public void StartMatrixBlender(float OrthoSize)
    {
        aspect = (Screen.width + 0.0f) / (Screen.height + 0.0f);

        if (OrthoSize != 0f)
        {
            float vertical = OrthoSize;
            float horizontal = (vertical * 16f) / 9f;

            ortho = Matrix4x4.Ortho(-horizontal, horizontal, -vertical, vertical, near, far);

            BlendToMatrix(ortho, 1f);
        }
        else
        {
            BlendToMatrix(perspective, 1f);
        }
    }

//---------------------------------------
    private Matrix4x4 MatrixLerp(Matrix4x4 from, Matrix4x4 to, float time)
    {
        Matrix4x4 ret = new Matrix4x4();
        int i;
        for (i = 0; i < 16; i++)
            ret[i] = Mathf.Lerp(from[i], to[i], time);
        return ret;
    }

    IEnumerator LerpFromTo(Matrix4x4 src, Matrix4x4 dest, float duration)
    {
        float startTime = Time.time;
        while (Time.time - startTime < duration)
        {
            Camera.main.projectionMatrix = MatrixLerp(src, dest, (Time.time - startTime) / duration);
            yield return new WaitForSeconds(0f);
        }
        Camera.main.projectionMatrix = dest;
    }

//-------------------------------------------------
    private Coroutine BlendToMatrix(Matrix4x4 targetMatrix, float duration)
    {
        StopAllCoroutines();
        return StartCoroutine(LerpFromTo(Camera.main.projectionMatrix, targetMatrix, duration));
    }

//-------------------------------------------------
    public void OnEvent(EVENT_TYPE Event_Type, Component Sender, object Param = null, object Param2 = null)
    {
        switch (Event_Type)
        {

        }
    }
}

I use code this way.

CameraOrthoController.Instance.StartMatrixBlender(OrthographicSize);

This has worked well so far. However, the problem occurred when i added particle system for effect.

The screen where the problem is occurring

In a normal state, the effect appears in front of the gameobject, as shown on the scene screen at the bottom of the picture above.

But if I use the code I wrote above to manipulate the camera, the effect will always be obscured by all gameobject, as if it were on the game screen at the top of the picture. Despite the fact that the effects are located in front of the game object.

At first, I thought it would be possible to solve it with layer sorting, but I don't think it's a layer problem because it's visible under normal camera conditions.

I want to know where the problem is with the above codes because I have to use them.

Please let me know if you know how to solve it. Thank you.

Upvotes: 3

Views: 10775

Answers (1)

Programmer
Programmer

Reputation: 125445

When you modify Camera.projectionMatrix, the camera will no longer update its rendering based on the field of view. The particle will remain behind the GameObject until you call Camera.ResetProjectionMatrix() which ends the effect off setting the Camera.projectionMatrix property.


If this doesn't work, use multiple cameras to make the particle system always appear on top of the 3D object. Basically, you render the 3D Object and other objects with the main camera then render the Particle System with another camera.

Layer:

1.Create new layer and name it "Particle"

2.Change the Particle System layer to Particle

enter image description here

Main Camera:

1.Make sure that the main camera's Clear Flags is set to Skybox.

2.Change the Culling Mask to "Everything". Click on Everything which is a setting of Culling Mask and de-select/uncheck Particle.

enter image description here

3.Make sure that its Depth is set to 0.

The camera should not render the Particle System at this point.

New Camera:

1.Create new Camera. Make sure it's at the-same position/rotation as the main camera. Also remove the AudioListener that is attached to it.

2.Change Clear Flags to Depth only.

3.Change the Culling Mask of the camera to be Particle and make sure that nothing else is selected in the "Culling Mask"

enter image description here

4.Change Depth to 1.

This will make the Particle System to always display on top of every object rendered with the first or main camera.


If you want the Particle System to appear on top of a Sprite/2d Object instead of Mesh/3D Object, change the sortingOrder of the particle's Renderer to be bigger than the SpriteRenderer's sortingOrder. The default is 0 so changing the Particle's sortingOrder to 1 or 2 should be fine.

particle.GetComponent<Renderer>().sortingOrder = 2;

Upvotes: 9

Related Questions