Skip to content

Instantly share code, notes, and snippets.

@IneonInoodle
Created October 2, 2019 15:45
Show Gist options
  • Save IneonInoodle/64459ae547fabb7deb1d5133e28b2405 to your computer and use it in GitHub Desktop.
Save IneonInoodle/64459ae547fabb7deb1d5133e28b2405 to your computer and use it in GitHub Desktop.
switches cinemachine camera bounds and blends to new pre defined cameras
using Cinemachine;
using MoreMountains.Tools;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum CameraZoomType { Normal, ZoomIn, ZoomOut}
/// <summary>
/// Lets you change bounds based on triggers, also can zoom in and out, works with the obect CameraBoundsChanger.cs (use prefab)
/// </summary>
public class CameraBoundsManager : Singleton<CameraBoundsManager>
{
public CinemachineVirtualCamera CurrentVirtualCamera;
protected CinemachineVirtualCamera LastVirtualCamera;
public CameraZoomType CurrentCameraZoomType;
// say if you have two camera bounds, one camera bounds inside another, then both would be stored in here.
public List<CinemachineVirtualCamera> CurrentlyActiveVirtualCameras;
public List<CinemachineVirtualCamera> AllCameras;
public GameObject DefaultVirtualCameraPrefab;
public GameObject ZoomInVirtualCameraPrefab;
public GameObject ZoomOutVirtualCameraPrefab;
public GameObject VirtualCameraParent;
public CinemachineTargetGroup TargetGroup;
public CinemachineVirtualCamera SetToActive(CameraZoomType zoomType, Collider2D col)
{
CurrentCameraZoomType = zoomType;
GameObject currentNewCamera = null;
switch (zoomType)
{
case CameraZoomType.Normal:
currentNewCamera = Instantiate(DefaultVirtualCameraPrefab, VirtualCameraParent.transform);
break;
case CameraZoomType.ZoomIn:
currentNewCamera = Instantiate(ZoomInVirtualCameraPrefab, VirtualCameraParent.transform);
break;
case CameraZoomType.ZoomOut:
currentNewCamera = Instantiate(ZoomOutVirtualCameraPrefab, VirtualCameraParent.transform);
break;
}
// save last for setting priority
LastVirtualCamera = CurrentVirtualCamera;
// set current camera
CurrentVirtualCamera = currentNewCamera.GetComponent<CinemachineVirtualCamera>();
if (LastVirtualCamera != null)
{
// set priority to be one higher than the last so camera pans from last to camera we just created
CurrentVirtualCamera.Priority = LastVirtualCamera.Priority + 1;
}
else
{
// first camera
CurrentVirtualCamera.Priority = 10;
}
// set bounds of newly created camera to be the bonds we pass in
CinemachineConfiner _confiner = currentNewCamera.GetComponent<CinemachineConfiner>();
// if no col set to default col, then we check if this manger has collider, and we use that(its the collider attached to this prefab object), could be null! camera works fine with no bounds
if (col == null)
_confiner.m_BoundingShape2D = GetComponent<PolygonCollider2D>();
else
_confiner.m_BoundingShape2D = col;
_confiner.InvalidatePathCache();
// make camera follow player
CurrentVirtualCamera.Follow = TargetGroup.gameObject.transform;
// store camera in list
CurrentlyActiveVirtualCameras.Add(CurrentVirtualCamera);
return CurrentVirtualCamera;
}
/// <summary>
/// Called normally on player OnTriggerExit, to delete/remove camera
/// </summary>
/// <param name="c"></param>
public void RemoveFromActive(CinemachineVirtualCamera c)
{
if (c == null)
return;
// these means we had case of nested camera bounds
// dont need to create new default camera, because one exists still
if (CurrentlyActiveVirtualCameras.Count > 1)
{
int _index = CurrentlyActiveVirtualCameras.IndexOf(CurrentVirtualCamera);
// we couldnt find camera in our list
if (_index == -1)
{
Debug.LogWarning("ERROR Virtual camera from somewhere we didnt create?");
}
// our active camera is now the one we had before
CurrentVirtualCamera = CurrentlyActiveVirtualCameras[_index - 1];
} else
{
// we need to create a default camera with no bounds, we are not inside any bounds triggers
//set active camera to be a new default virtual cam with no bounds
SetToActive(CameraZoomType.Normal, null);
}
// remove item from list
CurrentlyActiveVirtualCameras.Remove(c);
// set its priority to 0 to shift to next camera
c.Priority = 0;
// destroy object, after 3 seconds to make sure cinemachine is not blending between this camera (blend time on CM Brain is 2)
Destroy(c.gameObject, 3);
}
// Start is called before the first frame update
void Awake()
{
// base awake initializes this singleton
base.Awake();
Initialize();
// create first vcam so we have a default one
SetToActive(CameraZoomType.Normal, null);
}
void Initialize()
{
// we want to parent the virtual camera in the right spot
if (VirtualCameraParent == null)
{
VirtualCameraParent = Camera.main.transform.parent.gameObject;
}
// cinemachine supports a thing called target group which works like super smash bros camera with multiple targets. We use this by default because game technically built for multiplayer. and would still work with multiplayer
if (TargetGroup == null)
{
// use target group to follow player (target group targets are set by level manager to be all the players in multiplayer, only has one player in it normally)
TargetGroup = FindObjectOfType<CinemachineTargetGroup>();
}
}
// Update is called once per frame
void Update()
{
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment