0

I have a start scene which has a start button. The start scene has a Camera adaptor gameobject. Camera adaptor gets main camera and performs some operations on every scene. When I click on start and the next scene is loaded, the camera adapter object is available in next scene but the camera is missing. here is my code and configuration:

Start scene hierarchy

Start scene inspector

Level1 hierarchy

level1 inspector

I have added the below code in my CameraAdapter script:

public class CameraAdaptor2D : MonoBehaviour

{

float displayWidth;
float displayHeight;


[SerializeField] Camera cam;


   void OnEnable()
{
    SceneManager.sceneLoaded += OnSceneLoaded;
}

void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
    cam = Camera.main;
}

// called when the game is terminated
void OnDisable()
{
    Debug.Log("OnDisable");
    SceneManager.sceneLoaded -= OnSceneLoaded;
}

private void Awake()
{
    DontDestroyOnLoad(this.gameObject);
}
// Start is called before the first frame update
void Start()
{
    cam = Camera.main;
    displayWidth = Screen.width;
    displayHeight = Screen.height;
positionCamera();}
   void PositionCamera()
    {
        Vector3 vector = new Vector3(0.0f,0.0f,0.0f);
        cam.transform.position = vector;
    }

What happens is when I click on the start button, unity loads the next level. But with the above code, I cannot get the camera of the current scene. Even when I added a breakpoint, the next scene is not pausing at the breakpoint. Is there something that I am missing to add in the code or is there another way to get the cam on every scene?

Kiran Cyrus Ken
  • 379
  • 1
  • 3
  • 17

2 Answers2

3

When using DontDestroyOnLoad all references that are scene specific are wiped when loading into a new scene. You will need to subscribe to sceneLoaded and assign the reference there.

void OnEnable()
{
    SceneManager.sceneLoaded += OnSceneLoaded;
}

void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
      // assign the reference here 
}

void OnDisable()
{
    // make sure to unsubscribe or you will get multiple calls after multiple scene loads 
    SceneManager.sceneLoaded -= OnSceneLoaded;
}

Another option is to put the object this script is on in every scene and assign the reference, then in Awake look for another instance of the script in the scene, then assign the older objects references to the current and destroy the current.

void Awake()
{
    CameraAdaptor2D obj =  Object.FindObjectOfType<CameraAdaptor2D>();

    if (obj != null)
    {
        // assign the other object here 
        obj.AssignCamera(cam);
        Destroy(this.gameObject);
        return;
    }

    DontDestroyOnLoad(this.gameObject);
}

public void AssignCamera(Camera c)
{
    cam = c;
}

I should also mention, both answers use DontDestroyOnLoad. The first requires there exists one instance in the first scene you load and you will never load this scene again in the same session. The second requires there to be the same object in every scene so the reference can be set by the local instance of the object in that scene. Let me know if you want any more details as to how either implementation works.

TEEBQNE
  • 6,104
  • 3
  • 20
  • 37
  • I used the first method and was able to get the camera loaded. But still when I try to perform some operation with the camera like changing it's position, it is not functioning. Even the breakpoints are not hit in debug in the second loaded scene – Kiran Cyrus Ken May 22 '21 at 05:51
  • @KiranCyrusKen Are you still using `DontDestroyOnLoad` in `Awake`? It is needed for the solution to work. And how are you assigning the camera reference from the scene? Are you still setting it as `cam = Camera.main;`? – TEEBQNE May 22 '21 at 07:07
  • Yes. I have updated the code. I am setting camera in start as cam = Camera.main. Then when I call positionCamera(), nothing is happening. Even the debug breakpoints are not pausing there. – Kiran Cyrus Ken May 22 '21 at 07:21
  • @KiranCyrusKen Alright I'll try to see what the issue is. I might need to get to this tomorrow as it is 3:30 AM where I am. – TEEBQNE May 22 '21 at 07:25
  • Sorry. It is in the ````OnSceneLoaded```` and ````Start```` too. I removed it from start. Still the same – Kiran Cyrus Ken May 22 '21 at 07:27
  • @KiranCyrusKen No worries. Just wanted to let you know if I stop replying that is why and if that is the case, I can answer you later. In your loaded scene, I am not seeing a Camera object? Is there any object in your new scene that is the main camera? – TEEBQNE May 22 '21 at 07:33
  • Yes. Every scene has its own main camera. I am trying to assign that camera in the CameraAdapter object – Kiran Cyrus Ken May 22 '21 at 09:34
  • 1
    @KiranCyrusKen I'm confident that the camera is being assigned. I would remove anything from `Start()` and put it in the `OnSceneLoaded` as `Start` will only be called in the first scene that your script is loaded into. – TEEBQNE May 22 '21 at 17:14
  • Yes. Camera is assigned. I can see it in the inspector. But in the code, the positionCamera() is not happening. The camera stays where it is. Even if the camera is assigned, I cannot do any operations on it – Kiran Cyrus Ken May 22 '21 at 18:13
  • 1
    @KiranCyrusKen Yes like I mentioned, it is because, in your snippet, that code is in `Start()`. When an object is set as `DontDestroyOnLoad`, the `Start()` and `Awake()` functions only run the first scene it is in. Move the call you are making to the `OnSceneLoaded` method. – TEEBQNE May 22 '21 at 18:17
0

Because you only carry over the CameraAdaptor2D but not the Camera itself

void Start()
{
    cam = Camera.main;
    displayWidth = Screen.width;
    displayHeight = Screen.height;

    DontDestroyOnLoad (cam);
}

But then make sure of course there is no other Cameras in your other scenes.

derHugo
  • 83,094
  • 9
  • 75
  • 115