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.