Project_WL/Assets/Critter Volumetric Lighting/Demo/Demo Scripts/CameraController.cs

338 lines
7.5 KiB
C#
Raw Permalink Normal View History

using System.Collections;
using UnityEngine;
/**
Crude camera controller for demonstrating how volumetric light behaves with camera movement and rotations.
*/
namespace CritterVolumetricLighting
{
public class CameraController : MonoBehaviour
{
public Transform target;
public float rotationSpeed = 125f;
public float rotationAngle = 90f;
public float movementSpeed = 10f;
private Coroutine _currentRotationCoroutine = null;
private float _movementMultiplier = 1f;
private float _lastAngle;
private float _lastStationaryAngle;
private float _newTargetAngle;
private float _cooldownTimer = 0;
private float _cdTimerQ = 0;
private float _cdTimerE = 0;
private float _startDistance;
private int _movingClockWise; // -1 = not moving, 0 = false, 1 = true
private int _que = 0;
void Start()
{
Vector3 delta = this.transform.position - target.position;
_startDistance = delta.magnitude;
_movingClockWise = -1;
_lastStationaryAngle = this.transform.eulerAngles.y;
// StartCoroutine(TempCoroutine());
}
IEnumerator TempCoroutine()
{
yield return new WaitForSeconds(1f);
_cdTimerQ = 0;
float moveAngle;
if (_movingClockWise == 0)
{
_que = 0;
moveAngle = 0;
} else if (_movingClockWise == 1)
{
if (_que >= 1)
{
} else
{
_que++;
}
} else // -1...
{
moveAngle = rotationAngle;
}
_movingClockWise = 1;
StartRotation(rotationAngle);
yield return null;
}
void Update()
{
if (_cooldownTimer < 0.1f)
{
_cooldownTimer += Time.deltaTime;
return;
}
_lastAngle = this.transform.eulerAngles.y;
if (_cdTimerQ < 0.15f)
{
_cdTimerQ += Time.deltaTime;
} else
{
HandleQ();
}
if (_cdTimerE < 0.15f)
{
_cdTimerE += Time.deltaTime;
} else
{
HandleE();
}
this.transform.position = target.position - _startDistance * this.transform.forward;
HandleMovement(target);
}
private void HandleQ()
{
bool qPressed = false;
#if ENABLE_INPUT_SYSTEM
qPressed = UnityEngine.InputSystem.Keyboard.current.qKey.isPressed;
#else
qPressed = Input.GetKey(KeyCode.Q);
#endif
if (qPressed)
{
_cdTimerQ = 0;
float moveAngle;
if (_movingClockWise == 0)
{
_que = 0;
moveAngle = 0;
} else if (_movingClockWise == 1)
{
if (_que >= 1)
{
return; // We're already going in that direction
} else
{
_que++;
return;
}
} else // -1...
{
moveAngle = rotationAngle;
}
_movingClockWise = 1;
StartRotation(moveAngle);
return;
}
}
private void HandleE()
{
bool ePressed = false;
#if ENABLE_INPUT_SYSTEM
ePressed = UnityEngine.InputSystem.Keyboard.current.eKey.isPressed;
#else
ePressed = Input.GetKey(KeyCode.E);
#endif
if (ePressed)
{
_cdTimerE = 0;
float moveAngle;
if (_movingClockWise == 0)
{
if (_que <= -1)
{
return; // We're already going in that direction
} else
{
_que--;
return;
}
} else if (_movingClockWise == 1)
{
_que = 0;
moveAngle = 0;
} else // -1...
{
moveAngle = -rotationAngle;
}
_movingClockWise = 0;
StartRotation(moveAngle);
}
}
void HandleMovement(Transform mover)
{
Vector3 forwardDirection = this.transform.forward;
Vector3 rightDirection = this.transform.right;
forwardDirection.y = 0f; // Remove vertical component
rightDirection.y = 0f; // Remove vertical component
forwardDirection.Normalize();
rightDirection.Normalize();
// Movement based on input
Vector3 movement = Vector3.zero;
# if ENABLE_INPUT_SYSTEM
if (UnityEngine.InputSystem.Keyboard.current.wKey.isPressed)
{
movement += forwardDirection;
}
if (UnityEngine.InputSystem.Keyboard.current.sKey.isPressed)
{
movement -= forwardDirection;
}
if (UnityEngine.InputSystem.Keyboard.current.aKey.isPressed)
{
movement -= rightDirection;
}
if (UnityEngine.InputSystem.Keyboard.current.dKey.isPressed)
{
movement += rightDirection;
}
#else
if (Input.GetKey(KeyCode.W))
{
movement += forwardDirection;
}
if (Input.GetKey(KeyCode.S))
{
movement -= forwardDirection;
}
if (Input.GetKey(KeyCode.A))
{
movement -= rightDirection;
}
if (Input.GetKey(KeyCode.D))
{
movement += rightDirection;
}
#endif
// Normalize the movement vector to prevent faster diagonal movement
if (movement.magnitude > 1f)
{
movement.Normalize();
}
# if ENABLE_INPUT_SYSTEM
if (UnityEngine.InputSystem.Keyboard.current.spaceKey.isPressed)
{
_movementMultiplier = 3f;
} else
{
_movementMultiplier = 1f;
}
#else
if (Input.GetKey(KeyCode.LeftShift))
{
_movementMultiplier = 3f;
} else
{
_movementMultiplier = 1f;
}
#endif
mover.Translate(movement * movementSpeed * Time.deltaTime * _movementMultiplier);
}
void StartRotation(float angle)
{
_cooldownTimer = 0;
if (_currentRotationCoroutine != null)
{
StopCoroutine(_currentRotationCoroutine);
}
_newTargetAngle = _lastStationaryAngle + angle;
_currentRotationCoroutine = StartCoroutine(RotateAroundTarget(_newTargetAngle));
}
IEnumerator RotateAroundTarget(float targetAngle, bool cameFromCoroutine = false)
{
// Debug.Log("TargetAngle: "+targetAngle+" lastAngle: "+lastAngle);
float angle = Mathf.DeltaAngle(_lastAngle, targetAngle);
Vector3 rotationAxis = target.up;
float totalRotationTime = Mathf.Abs(angle) / rotationSpeed; // Total time to complete the rotation
// totalRotationTime = 10000f;
float elapsedTime = 0f;
float initialRotation = transform.eulerAngles.y;
while (elapsedTime < totalRotationTime)
{
elapsedTime += Time.deltaTime;
float t = elapsedTime / totalRotationTime; // calculate current progress
float usedT;
if (_que == 0)
{
usedT = SmoothStep(t, cameFromCoroutine); // apply easing
} else
{
usedT = SmoothStep(t, cameFromCoroutine); // Don't apply easing when we are in que.
}
Vector3 rotationCenter = target.position; // update rotation center each frame
float targetRotation = initialRotation + usedT * angle; // target rotation after applying easing
float rotationThisFrame = targetRotation - transform.eulerAngles.y; // rotation to be done this frame
transform.RotateAround(rotationCenter, rotationAxis, rotationThisFrame);
yield return null;
}
_lastStationaryAngle = this.transform.eulerAngles.y;
if (_que != 0)
{
_que = 0;
_newTargetAngle = _lastStationaryAngle + angle;
StopCoroutine(_currentRotationCoroutine);
_currentRotationCoroutine = StartCoroutine(RotateAroundTarget(_newTargetAngle, true));
yield return null;
}
// apply a final rotation to ensure we exactly hit the target angle
Vector3 finalRotationCenter = target.position;
float finalRotation = targetAngle - transform.eulerAngles.y;
transform.RotateAround(finalRotationCenter, rotationAxis, finalRotation);
_movingClockWise = -1;
_lastStationaryAngle = this.transform.eulerAngles.y;
_currentRotationCoroutine = null;
}
float SmoothStep(float hardT, bool cameFromCoroutine)
{
return SmoothStepLogic(hardT);
}
float SmoothStepLogic(float steppedValue)
{
return steppedValue * steppedValue * (3f - 2f* steppedValue);
}
}
}