You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
169 lines
5.4 KiB
169 lines
5.4 KiB
// Reference: https://www.behance.net/gallery/44375157/Free-Motion-Camera-Rig
|
|
using UnityEngine;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System;
|
|
#if UNITY_EDITOR
|
|
using UnityEditor;
|
|
#endif
|
|
|
|
namespace UltraCombos
|
|
{
|
|
[ExecuteAlways]
|
|
public class FreeMotionCameraRig : MonoBehaviour
|
|
{
|
|
[SerializeField] private int trailLength = 100;
|
|
|
|
[Header("Rotations")]
|
|
public float distance;
|
|
public float horizontal;
|
|
public float vertical;
|
|
|
|
[Header("Head Extra")]
|
|
[Range(-90, 90)] public float roll;
|
|
[Range(-90, 90)] public float tilt;
|
|
[Range(-90, 90)] public float pan;
|
|
public float slide;
|
|
|
|
[Header("Controllers")]
|
|
[SerializeField] private Transform tiltPivot;
|
|
[SerializeField] private Transform panPivot;
|
|
[SerializeField] private Transform rollPivot;
|
|
|
|
[Header("Automatic")]
|
|
[SerializeField] private float horizontalSpeed = 0;
|
|
|
|
[Header("Dev")]
|
|
[SerializeField] private float uiScale = 1;
|
|
|
|
private Queue<Vector3> trail = new Queue<Vector3>();
|
|
|
|
|
|
private void Start()
|
|
{
|
|
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
distance = Mathf.Max(distance, 0);
|
|
if (Mathf.Abs(horizontalSpeed) > 0)
|
|
{
|
|
horizontal = Mathf.Repeat(horizontal + horizontalSpeed * Time.deltaTime, 360);
|
|
}
|
|
|
|
transform.localEulerAngles = new Vector3(vertical, horizontal, 0);
|
|
|
|
if (tiltPivot)
|
|
{
|
|
tiltPivot.localPosition = new Vector3(0, 0, -distance);
|
|
tiltPivot.localEulerAngles = new Vector3(tilt, 0, 0);
|
|
}
|
|
|
|
if (panPivot)
|
|
{
|
|
panPivot.localEulerAngles = new Vector3(0, pan, 0);
|
|
}
|
|
|
|
if (rollPivot)
|
|
{
|
|
rollPivot.localPosition = new Vector3(0, 0, -slide);
|
|
rollPivot.localEulerAngles = new Vector3(0, 0, -roll);
|
|
}
|
|
|
|
trail.Enqueue(rollPivot.position);
|
|
if (trail.Count > trailLength)
|
|
{
|
|
trail.Dequeue();
|
|
}
|
|
}
|
|
|
|
private void OnDrawGizmosSelected()
|
|
{
|
|
#if UNITY_EDITOR
|
|
var rot = Quaternion.Euler(0, transform.localEulerAngles.y, 0);
|
|
var trs = Matrix4x4.TRS(transform.position, rot, transform.localScale * uiScale);
|
|
using (new Handles.DrawingScope(new Color32(5, 169, 245, 255), trs))
|
|
{
|
|
Handles.DrawWireDisc(Vector3.zero, Vector3.up, distance);
|
|
var d = distance * 1.1f;
|
|
var r = distance * 0.08f;
|
|
var triangle = GetPoints(3, true)
|
|
.Select(p => p * r * 2 + new Vector3(0, 0, d))
|
|
.ToArray();
|
|
Handles.DrawPolyLine(triangle);
|
|
Handles.DrawWireDisc(new Vector3(+d, 0, 0), Vector3.up, r);
|
|
Handles.DrawWireDisc(new Vector3(-d, 0, 0), Vector3.up, r);
|
|
var circle = GetPoints(32, false);
|
|
var lines = new List<Vector3>();
|
|
var cr = distance * 0.9f;
|
|
for (var i = 0; i < circle.Count; ++i)
|
|
{
|
|
var i2 = (i + 1) % circle.Count;
|
|
lines.Add(circle[i] * cr);
|
|
lines.Add(circle[i2] * cr);
|
|
}
|
|
Handles.DrawDottedLines(lines.ToArray(), 4);
|
|
}
|
|
|
|
var size = distance * 0.1f;
|
|
|
|
if (tiltPivot)
|
|
{
|
|
|
|
}
|
|
|
|
if (panPivot)
|
|
{
|
|
using var scp = new Handles.DrawingScope(new Color32(194, 153, 0, 255), panPivot.localToWorldMatrix);
|
|
var w = size;
|
|
var h = size * 2;
|
|
var points = new Vector3[] {
|
|
new Vector3(+w, 0, 0),
|
|
new Vector3(0, 0, +h),
|
|
new Vector3(-w, 0, 0),
|
|
new Vector3(0, 0, -h),
|
|
new Vector3(w, 0, 0) };
|
|
Handles.DrawPolyLine(points);
|
|
}
|
|
|
|
if (rollPivot)
|
|
{
|
|
using var scp = new Handles.DrawingScope(new Color32(56, 186, 110, 255), rollPivot.localToWorldMatrix);
|
|
var p0 = rollPivot.InverseTransformPoint(transform.position);
|
|
Handles.DrawLine(p0, Vector3.zero);
|
|
var p1 = rollPivot.InverseTransformPoint(trs.MultiplyPoint(new Vector3(0, 0, -distance)));
|
|
Handles.DrawLine(p1, Vector3.zero);
|
|
|
|
var w = size * 1.2f;
|
|
var h = size * 0.2f;
|
|
var points = new Vector3[] {
|
|
new Vector3(+w, 0, -h),
|
|
new Vector3(-w, 0, -h),
|
|
new Vector3(0, 0, h * 4),
|
|
new Vector3(+w, 0, -h) };
|
|
Handles.DrawPolyLine(points);
|
|
}
|
|
|
|
Handles.DrawPolyLine(trail.ToArray());
|
|
#endif
|
|
}
|
|
|
|
private List<Vector3> GetPoints(int sides, bool close)
|
|
{
|
|
var da = 2 * Mathf.PI / sides;
|
|
var points = new List<Vector3>();
|
|
for (var i = 0; i < sides; i++)
|
|
{
|
|
var a = da * i + Mathf.PI / 2;
|
|
points.Add(new Vector3(Mathf.Cos(a), 0, Mathf.Sin(a)));
|
|
}
|
|
if (close)
|
|
{
|
|
points.Add(points.First());
|
|
}
|
|
return points;
|
|
}
|
|
}
|
|
|
|
} |