Forum rules - please read before posting.

Rendering Background and 3D on seperate layers

Hey everybody!

I have a problem that on first glance seems quite easy to solve, but maybe isn't that simple after all.
I'm creating a 2.5D game with 3D characters and terrain in front of 2D screens. We want to have a movable camera in every screen and it gets a little funky from time to time, because there are also different layers for background imagery, since there are objects that the character is supposed to walk behind, parallax, moving clouds etc.

So to simplify at least one bit of all of this, I wanted to have a 2d orthographic camera, that only renders textures and a 2d perspective camera that renders the characters (the terrain is invisible, we need the perspective camera with ken burns effect (thanks to AC) to adjust it to the backgrounds in every frame).

Now I found out through some research (correct me if I'm wrong) that culling masks don't work with AC Cams. Thus I tried the limit visibility script, and technically it does what I want.

My only problem is: How do I render 2 images through my Main Camera at the same time?

Comments

  • Also I wanna add: I'm working on Unity 2018.3.8f1, I think camera stacking is not possible in Unity 2019 anymore.

  • For what it's worth, a tutorial on scrolling 2.5D backgrounds can be found here.

    There shouldn't be any restriction about using culling masks as such, but since AC's "GameCameras" are only used as reference, it's only the MainCamera that actually performs any rendering (by default, at least).

    If a scene contains a GameCamera25D camera type, the MainCamera will have the "BackgroundImage" layer added to its mask. Otherwise, all such masks fields remain untouched.

  • Firstly, thank you for the quick response!
    But I think I see where the problem is now. I'd like to have 2 MainCameras rendering. One for the background and one for everything 3D related. The reason simply being that having the background rendered by an orthographic camera would make a lot of things easier imo (f. e. no need to resize background layers depending on their distance from my main camera, which is necessary with a perspective cam). On the other hand I can't lose the perspective camera, since it would make aligning 3D terrain to 2D backgrounds kind of impossible.

  • Okay so for everyone reading this, I wrote a little script to fix my problem.

    To clarify what this is for:
    3D terrain, with different layers of 2D screens (like area you're walking on, trees you should walk behind, clouds moving in the background).
    Working with 3D terrain on 2D screens mean you need a perspective camera in order to align the terrain with the graphics.
    So if some of your graphics are supposed to be closer to the camera than others they need to be scaled down and positioned just right, to align with the rest (and other background screens).

    How to use the script:
    Take your main background and align it with the terrain.
    Put all other graphics as children and put them in the BackgroundImage layer.
    Don't put the main background in that layer.
    (You can obviously alter the script and just exclude the main background by other means than the layer, it's just working that way for me, since I have some other objects attached to some of the children and I wanted to make sure they were excluded from the scaling.)

    Now put the main background in the SerializedField mainBackground and you'
    re good to go.

    public class BackgroundScaler : MonoBehaviour
    {
        [SerializeField] private GameObject mainBackground;
    
        private List<Transform> backgrounds = new List<Transform>();
        private Vector3 CameraPosition;
        private float defaultDistance;
        private Vector3 defaultVector3;
    
        // Start is called before the first frame update
        void Start()
        {
            CameraPosition = GetComponent<Transform>().position;
            defaultVector3 = CameraPosition - mainBackground.transform.position;
            defaultDistance =  defaultVector3.magnitude;
            foreach (var gObject in mainBackground.GetComponentsInChildren<Transform>())
            {
    
                if(gObject.gameObject.layer != 9) continue;
                backgrounds.Add(gObject);
            }
            ScaleBackgrounds();
        }
    
        private void ScaleBackgrounds()
        {
            foreach (var background in backgrounds)
            {
                float tempScale = GetDistance(CameraPosition, background.position) / defaultDistance;
                background.localScale = new Vector3(tempScale, tempScale, tempScale);
                background.position = CameraPosition - (defaultVector3 * tempScale);
            }
        }
    
        private float GetDistance(Vector3 v1, Vector3 v2)
        {
            return (v1 - v2).magnitude;
        }
    
    }
    
Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Welcome to the official forum for Adventure Creator.