0
\$\begingroup\$

I know there are 3 scripts here but they are all connected so I can't reduce the amount of code in this question.

I have some scripts. The first one switch between cameras. When I press on G it's switching between the cameras.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class SwitchCameras : MonoBehaviour
{
    private bool cycleAllCameras = false;
    public Camera[] storedCameras;

    public Vector3[] _originalPositions;
    public Vector3[] _lastPositions;
    public Camera[] _currentCameraSequence;
    public Camera[] _allCameras;
    int _currentCameraIndexInCycle;
    int _currentCameraIndexInAll;

    // Rather than store the current camera's index, AND its reference,
    // AND its name, AND its position, AND its original position...
    // let's just store its index, and everything else can be inferred
    // from that, so we don't have redundant data that can go out of sync.
    public Camera currentCamera
    {
        get
        {
            return _currentCameraSequence[_currentCameraIndexInCycle];
        }
    }

    void Start()
    {
        // Cache all cameras enabled at the start of the scene; 
        _allCameras = Camera.allCameras;
        _originalPositions = new Vector3[_allCameras.Length];
        _lastPositions = new Vector3[_allCameras.Length];

        // Select the first camera in whichever list we're using
        _currentCameraSequence = cycleAllCameras ? _allCameras : storedCameras;
        Camera currentCamera = this.currentCamera;

        // Disable every camera except the one we're using,
        // and cache their original positions to use later.
        for (int i = 0; i < _allCameras.Length; i++)
        {
            _allCameras[i].enabled = (_allCameras[i] == currentCamera);
            _lastPositions[i] = _originalPositions[i] = _allCameras[i].transform.position;
        }
    }

    void LateUpdate()
    {
        // Update the current camera's last position,
        // before we switch from it to a dormant one.
        _lastPositions[_currentCameraIndexInAll] = currentCamera.transform.position;

        // Use a named input so the user can remap it.
        if (Input.GetKeyDown(KeyCode.G))
            CycleCamera();
    }

    public void SwitchSequence()
    {
        if (_currentCameraSequence.Length > 0)
        {
            cycleAllCameras = !cycleAllCameras;
            CycleCamera();
        }
    }

    // Cycle action is in its own public method, in case you 
    // want to trigger it from other scripts or UI buttons.
    public void CycleCamera()
    {
        currentCamera.enabled = false;

        // If we've swapped sequences, re-index the camera.
        if (_currentCameraSequence == storedCameras)
        {
            if (cycleAllCameras == true)
            {
                _currentCameraIndexInCycle = _currentCameraIndexInAll;
                _currentCameraSequence = _allCameras;
            }
        }
        else if (cycleAllCameras == false)
        {
            _currentCameraIndexInCycle = Mathf.Max(0, System.Array.IndexOf(storedCameras, currentCamera));
            _currentCameraSequence = storedCameras;
        }

        // Step to the next camera, and wrap around the sequence.
        _currentCameraIndexInCycle = (_currentCameraIndexInCycle + 1) % _currentCameraSequence.Length;

        // Ensure we have a valid index into the "all" list
        // for looking up original position / last position / etc.
        _currentCameraIndexInAll = System.Array.IndexOf(_allCameras, currentCamera);

        //
        currentCamera.enabled = true;
    }
}

The second script is scaling object. It will scale the object up/down:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Scaling : MonoBehaviour
{
    public GameObject objectToScale;
    public GameObject lookAtTarget;
    public float duration = 1f;
    public Vector3 minSize;
    public Vector3 maxSize;
    public bool scaleUp = false;
    public Coroutine scaleCoroutine;

    public void Inits()
    {
        objectToScale.transform.localScale = minSize;
    }

    public IEnumerator scaleOverTime(GameObject targetObj, Vector3 toScale, float duration)
    {
        float counter = 0;
        Vector3 startScaleSize = targetObj.transform.localScale;

        while (counter < duration)
        {
            counter += Time.deltaTime;
            targetObj.transform.localScale = Vector3.Lerp(startScaleSize, toScale, counter / duration);
            if (scaleUp)
            {
                var lookPos = lookAtTarget.transform.position - objectToScale.transform.position;
                lookPos.y = 0;
                var rotation = Quaternion.LookRotation(lookPos);
                objectToScale.transform.rotation = Quaternion.Slerp(objectToScale.transform.rotation, rotation, counter / duration);
            }
            else
            {
                var lookPos = lookAtTarget.transform.position - objectToScale.transform.position;
                lookPos.y = 0;
                var rotation = Quaternion.LookRotation(Camera.main.transform.forward);
                objectToScale.transform.rotation = Quaternion.Slerp(objectToScale.transform.rotation, rotation, counter / duration);
            }

            yield return null;
        }
    }
}

The last script handle the scaling and others:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ObjectsManipulation : MonoBehaviour
{
    //Camera
    public Camera playerCamera;

    //Scaling
    private Scaling scaling;

    //Lights
    public DimLights dimlights;
    private Coroutine lightCoroutine;

    //Colors
    private Colors colors;

    //Rotating
    public bool stopRotation = false;
    private Rotating rotating;

    private void Start()
    {
        scaling = GetComponent<Scaling>();
        scaling.Inits();

        colors = GetComponent<Colors>();
        colors.Start();

        rotating = GetComponent<Rotating>();
    }

    // Use this for initialization
    void Update()
    {
        //Scaling
        if (Input.GetKeyDown(KeyCode.F))
        {
            //Flip the scale direction when F key is pressed
            scaling.scaleUp = !scaling.scaleUp;

            //Stop old coroutine
            if (scaling.scaleCoroutine != null)
                StopCoroutine(scaling.scaleCoroutine);

            if (lightCoroutine != null)
                StopCoroutine(lightCoroutine);


            //Scale  up
            if (scaling.scaleUp)
            {
                //Start new coroutine and scale up within 5 seconds and return the coroutine reference
                rotating.rotateBack = false;
                scaling.scaleCoroutine = StartCoroutine(scaling.scaleOverTime(scaling.objectToScale, scaling.maxSize, scaling.duration));
                if (dimlights.lightsOnOff == false)
                    lightCoroutine = StartCoroutine(dimlights.dimLightOverTime(1, scaling.duration));
            }

            //Scale Down
            else
            {
                //Start new coroutine and scale up within 5 seconds and return the coroutine reference
                rotating.rotateBack = true;
                scaling.scaleCoroutine = StartCoroutine(scaling.scaleOverTime(scaling.objectToScale, scaling.minSize, scaling.duration));
                if (dimlights.lightsOnOff == false)
                    lightCoroutine = StartCoroutine(dimlights.dimLightOverTime(0, scaling.duration)); ;
            }
        }

        //Rotate
        if (Input.GetKey(KeyCode.R) && !scaling.scaleUp)
        {
            rotating.x += Time.deltaTime * rotating.rotationSpeed;
            scaling.objectToScale.transform.localRotation = Quaternion.Euler(0, 0, rotating.x);
            rotating.keyPressed = true;
        }
        if (Input.GetKeyUp(KeyCode.R))
        {
            rotating.keyPressed = false;
        }

        if (!rotating.keyPressed && !scaling.scaleUp && rotating.rotateBack == false
            && DetectInteractable.detected == false)
        {
            scaling.objectToScale.transform.rotation = Quaternion.LookRotation(playerCamera.transform.forward);
        }

        if (DetectInteractable.detected == true && !scaling.scaleUp && stopRotation == false)
        {
            rotating.x += Time.deltaTime * rotating.rotationSpeed;
            scaling.objectToScale.transform.localRotation = Quaternion.Euler(0, 0, rotating.x);
        }
    }
}

In the script ObjectsManipulation when I press on F it will scale up/down the object.

The scaling script is using the Camera.main

In the SwitchCameras script I'm using the G key to switch between the cameras.

The problem happens if I press on F and while it's scaling the object I'm pressing on G then I'm getting exception in the Scaling script on the line:

var rotation = Quaternion.LookRotation(Camera.main.transform.forward);

Since I'm switching cameras then the main one is now null but the scaling not finished yet and is trying to access the main camera.

I'm not sure what logic should I put here and how. My logic I think should be that I will be able to switch between the cameras at any time pressing G and the scaling if I pressed F already the scaling either should be keep working in the background I mean I switched to another camera but the scaling should not stop so when I return back to the main camera I will keep see the scaling in progress or if it's ended.

Or maybe I should pause the scaling wait for switching back to the main camera and then continue the scaling.

Not sure how to do it. I keep getting the exception in the situation. When pressing F and while scaling pressing G to switch cameras.

\$\endgroup\$
2
\$\begingroup\$

Why not just expose the switcher's current camera and reference that?

eg. (inside the camera switcher script)

// Lazy singleton...
static SwitchCameras _instance;

public static Camera GetCurrentCamera() {
    return _instance.currentCamera;
}

void Awake() {
    _instance = this;
}

then you can replace any script trying to read

Camera.main

with

SwitchCameras.GetCurrentCamera()
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.