Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
161 lines (135 sloc) 6.21 KB
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace FourthDimension {
public class CameraHolder : MonoBehaviour {
// Enum to dictate how the screen shake will happen.
public enum EShakeStyle {
Horizontal,
Vertical,
Angular,
Directional,
All
}
// The Main Camera, the one who won't shake (probably the one following the player, has its own Script)
public Camera mainCamera;
// Shake Camera, the reason this is a different camera is because we don't want to mess with the real camera position, so we won't have to do extra code to make sure the camera return to its original position.
public Camera screenshakeCamera;
// For Angular Screenshake
private const float maxAngle = .5f;
// For Directional Screenshake
private const float maxOffset = .5f;
private float m_cameraTrauma;
private EShakeStyle m_shakeStyle;
private Coroutine shakeRoutine;
void Awake() {
if(mainCamera == null) FourthDimension.LoggerUtility.LogError("Main Camera is not set on Camera Holder!");
if(screenshakeCamera == null) FourthDimension.LoggerUtility.LogError("Screen Shake Camera is not set on Camera Holder!");
}
void Start() {
m_shakeStyle = EShakeStyle.All;
shakeRoutine = null;
m_cameraTrauma = 0f;
}
#region Dealing with Camera Ortographic Size
public void SetCameraOrtographicSize(float ortographicSize) {
mainCamera.orthographicSize = ortographicSize;
screenshakeCamera.orthographicSize = ortographicSize;
}
public void LerpCameraOrtographicSize(float ortographicSize) {
StartCoroutine(LerpCameraOrtographicSizeRoutine(ortographicSize));
}
private IEnumerator LerpCameraOrtographicSizeRoutine(float ortographicSize) {
float currentOrtographicSize = mainCamera.orthographicSize;
float timeToLerp = 0.5f;
float timeElapsed = 0f;
while(timeElapsed < timeToLerp) {
timeElapsed += Time.deltaTime;
float t = (timeElapsed / timeToLerp);
mainCamera.orthographicSize = Mathf.Lerp(currentOrtographicSize, ortographicSize, t);
yield return null;
}
yield return null;
mainCamera.orthographicSize = ortographicSize;
screenshakeCamera.orthographicSize = mainCamera.orthographicSize;
}
#endregion
#region Screenshake
// Entry Point for the screenshake functionality
public void AddTraumaToCamera(float amount, EShakeStyle style) {
SetShakeStyle(style);
AddTraumaToCamera(amount);
}
public void SetShakeStyle(EShakeStyle shakeStyle) {
m_shakeStyle = shakeStyle;
}
// This can also be an entry point if you don't want to change the Shake Style
public void AddTraumaToCamera(float amount) {
if(m_cameraTrauma <= 0) {
screenshakeCamera.transform.position = mainCamera.transform.position;
// Changing which of the camera we are currently using!
// IMPORTANT!
screenshakeCamera.enabled = true;
mainCamera.enabled = false;
m_cameraTrauma = amount;
} else {
m_cameraTrauma += amount;
}
// If ShakeRoutine is not null, it means ScreenShake is already happening.
// This way, adding to the camera trauma will make the screen shake more and for a longer time, that means we don't need to reinitialize the Coroutine.
// Reinitializing the Coroutine would cause inumerous bad behaviors.
if(shakeRoutine == null) {
shakeRoutine = StartCoroutine(ShakeRoutine());
}
}
// Shake Routine
// Decays Linearly with Time.deltaTime
// But the effective shake is quadratic according to the camera trauma.
private IEnumerator ShakeRoutine() {
while(m_cameraTrauma > 0) {
m_cameraTrauma -= Time.deltaTime;
screenshakeCamera.transform.position = mainCamera.transform.position;
float angle = maxAngle * (m_cameraTrauma * m_cameraTrauma) * Random.Range(-1f, 1f);
float offsetX = maxOffset * (m_cameraTrauma * m_cameraTrauma) * Random.Range(-1f, 1f);
float offsetY = maxOffset * (m_cameraTrauma * m_cameraTrauma) * Random.Range(-1f, 1f);
ShakeWithStyle(new Vector2(offsetX, offsetY), angle);
yield return null;
}
screenshakeCamera.enabled = false;
mainCamera.enabled = true;
shakeRoutine = null;
}
private void ShakeWithStyle(Vector2 directionalOffset, float angularOffset) {
switch(m_shakeStyle) {
case EShakeStyle.Horizontal:
ShakeDirectional(new Vector2(directionalOffset.x, 0));
break;
case EShakeStyle.Vertical:
ShakeDirectional(new Vector2(0, directionalOffset.y));
break;
case EShakeStyle.Angular:
ShakeRotational(angularOffset);
break;
case EShakeStyle.Directional:
ShakeDirectional(directionalOffset);
break;
case EShakeStyle.All:
ShakeDirectional(directionalOffset);
ShakeRotational(angularOffset);
break;
}
}
private void ShakeDirectional(Vector2 offset) {
Vector3 t_position = screenshakeCamera.transform.position;
t_position.x += offset.x;
t_position.y += offset.y;
screenshakeCamera.transform.position = t_position;
}
private void ShakeRotational(float offset) {
Vector3 t_rotation = screenshakeCamera.transform.localEulerAngles;
t_rotation.z += offset;
screenshakeCamera.transform.localEulerAngles = t_rotation;
}
#endregion
}
}
You can’t perform that action at this time.