Created
May 11, 2020 17:24
-
-
Save twchapman/7485ffbcc14869b08b1c40536f21e6f1 to your computer and use it in GitHub Desktop.
Orbit Camera scripts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Game; | |
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
[RequireComponent(typeof(Camera))] | |
public class CharacterCamera : MonoBehaviour | |
{ | |
private readonly OrbitCameraController orbiter = new OrbitCameraController(); | |
private new Camera camera; | |
public Transform FollowTarget; | |
[SerializeField] | |
[Range(distanceMin, distanceMax)] | |
public float OrbitDistance = 10; | |
private const float distanceMin = 10f; | |
private const float distanceMax = 50f; | |
[SerializeField] | |
[Range(0, 360)] | |
public float OrbitRotation; | |
private void Awake() { | |
camera = GetComponent<Camera>(); | |
} | |
private void Update() { | |
HandleInput(); | |
orbiter.OrbitPoint = FollowTarget.position + new Vector3(0f, 1f, 0f); | |
orbiter.OrbitDistance = OrbitDistance; | |
orbiter.OrbitAngle = OrbitRotation; | |
(var position, var rotation) = orbiter.GetCameraPositionAndRotation(); | |
camera.transform.SetPositionAndRotation(position, rotation); | |
} | |
private Vector3 lastMousePosition; | |
private void HandleInput() { | |
if (Input.mouseScrollDelta.y != 0) { | |
OrbitDistance = Mathf.Clamp(OrbitDistance - Input.mouseScrollDelta.y, distanceMin, distanceMax); | |
} | |
if (Input.GetMouseButtonDown(2)) { | |
lastMousePosition = Input.mousePosition; | |
} else if (Input.GetMouseButton(2)) { | |
OrbitRotation -= Input.mousePosition.x - lastMousePosition.x; | |
lastMousePosition = Input.mousePosition; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using UnityEngine; | |
namespace Game { | |
public struct PositionAndRotation { | |
public Vector3 Position; | |
public Quaternion Rotation; | |
public void Deconstruct(out Vector3 position, out Quaternion rotation) { | |
position = Position; | |
rotation = Rotation; | |
} | |
} | |
public class OrbitCameraController { | |
public const float CameraAngle = 35f; | |
private Vector3 orbitPoint; | |
public Vector3 OrbitPoint { | |
get => orbitPoint; | |
set { | |
orbitPoint = value; | |
} | |
} | |
private float orbitDistance = 10f; | |
public float OrbitDistance { | |
get => orbitDistance; | |
set { | |
orbitDistance = Mathf.Abs(value); | |
} | |
} | |
private float orbitAngle; | |
public float OrbitAngle { | |
get => orbitAngle; | |
set { | |
orbitAngle = value % 360f; | |
} | |
} | |
public PositionAndRotation GetCameraPositionAndRotation() { | |
throw new Exception(); | |
var rotation = Quaternion.Euler(new Vector3(CameraAngle, OrbitAngle, 0)); | |
var lookDirection = rotation * Vector3.forward; | |
var position = OrbitPoint - lookDirection * OrbitDistance; | |
return new PositionAndRotation { | |
Position = position, | |
Rotation = rotation | |
}; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Game; | |
using NUnit.Framework; | |
using UnityEngine; | |
using UnityEngine.TestTools.Utils; | |
namespace Tests { | |
public class OrbitCameraControllerTests { | |
[Test] | |
public void GetCameraPositionAndRotation_OrbitPointIsZeroAndDistanceIs10_ReturnsPositionBehindPoint() { | |
var controller = new OrbitCameraController(); | |
(var position, var rotation) = controller.GetCameraPositionAndRotation(); | |
var expectedRotation = new Vector3(OrbitCameraController.CameraAngle, 0, 0); | |
var expectedPosition = new Vector3(0f, 0f, 0f) - Quaternion.Euler(expectedRotation) * Vector3.forward * 10f; | |
Assert.That(position, Is.EqualTo(expectedPosition).Using(Vector3EqualityComparer.Instance)); | |
Assert.That(rotation.eulerAngles, Is.EqualTo(expectedRotation).Using(Vector3EqualityComparer.Instance)); | |
} | |
[Test] | |
public void GetCameraPositionAndRotation_OrbitPointIsZeroAndDistanceIs20_ReturnsPositionBehindPointTwiceAsFar() { | |
var controller = new OrbitCameraController(); | |
controller.OrbitDistance = 20f; | |
(var position, var rotation) = controller.GetCameraPositionAndRotation(); | |
var expectedRotation = new Vector3(OrbitCameraController.CameraAngle, 0, 0); | |
var expectedPosition = new Vector3(0f, 0f, 0f) - Quaternion.Euler(expectedRotation) * Vector3.forward * 20f; | |
Assert.That(position, Is.EqualTo(expectedPosition).Using(Vector3EqualityComparer.Instance)); | |
Assert.That(rotation.eulerAngles, Is.EqualTo(expectedRotation).Using(Vector3EqualityComparer.Instance)); | |
} | |
[Test] | |
public void GetCameraPositionAndRotation_OrbitPointIsZeroAnOrbitAngleIs180_ReturnsPositionInFrontPoint() { | |
var controller = new OrbitCameraController(); | |
controller.OrbitAngle = 180f; | |
(var position, var rotation) = controller.GetCameraPositionAndRotation(); | |
var expectedRotation = new Vector3(OrbitCameraController.CameraAngle, 180f, 0); | |
var expectedPosition = new Vector3(0f, 0f, 0f) - Quaternion.Euler(expectedRotation) * Vector3.forward * 10f; | |
Assert.That(position, Is.EqualTo(expectedPosition).Using(Vector3EqualityComparer.Instance)); | |
Assert.That(rotation.eulerAngles, Is.EqualTo(expectedRotation).Using(Vector3EqualityComparer.Instance)); | |
} | |
[Test] | |
public void GetCameraPositionAndRotation_OrbitPointIs1010AndDistanceIs10_ProperlyOffsetsPosition() { | |
var controller = new OrbitCameraController(); | |
controller.OrbitPoint = new Vector3(10f, 0f, 10f); | |
(var position, var rotation) = controller.GetCameraPositionAndRotation(); | |
var expectedRotation = new Vector3(OrbitCameraController.CameraAngle, 0, 0); | |
var expectedPosition = new Vector3(10f, 0f, 10f) - Quaternion.Euler(expectedRotation) * Vector3.forward * 10f; | |
Assert.That(position, Is.EqualTo(expectedPosition).Using(Vector3EqualityComparer.Instance)); | |
Assert.That(rotation.eulerAngles, Is.EqualTo(expectedRotation).Using(Vector3EqualityComparer.Instance)); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment