之前项目有一个需求,要计算摄像机的运动轨迹,并将该运动轨迹的关键帧进行保存。将这些关键帧进行可视化,就像Unity3D中的Animation面板一样,可以查看每一个关键帧像机的状态。
这里使用了AnimationCurve来对关键帧进行计算和操作,代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 相机位置
/// </summary>
public class CameraPositionDatas : MonoBehaviour
{
/*------------------Variable---------------------------*/
TimelinedVector3 position = new TimelinedVector3();
TimelinedQuaternion rotation = new TimelinedQuaternion();
private List<float> value = new List<float>();
/*-----------------------------------------------------*/
/// <summary>
/// 根据传入的百分比得到Index
/// </summary>
/// <param name="number">传入的百分比</param>
/// <returns></returns>
private int GetIndex(float percentage)
{
int index = (int)percentage;// 转换成为Int型
float remainder = percentage % 1;// 求出小数部分
if (index == 0)
{
return 0;
}
else
{
return remainder < 0.5f ? index : index + 1;
}
}
/*---------------增删查改--------------------------*/
/// <summary>
/// 添加关键帧
/// </summary>
/// <param name="percentage">百分比</param>
/// <param name="transformObj">需要添加物体数据的Transform</param>
public void AddTransformDatas(float percentage, Transform transformObj)
{
int index = GetIndex(percentage);
if (value.Contains(index))
{
return;
}
else
{
value.Add(index);
position.Add(index, transformObj.position);
rotation.Add(index, transformObj.rotation);
}
}
/// <summary>
/// 移除关键帧
/// </summary>
/// <param name="percentage">百分比</param>
public void RemoveTransformDatas(float percentage)
{
int index = GetIndex(percentage);
if (position.total.keys.Length == 0)
{
return;
}
else
{
if (value.Contains(index))
{
for (int i = 0; i < position.total.keys.Length; i++)
{
if (position.total.keys[i].time == index)
{
position.Remove(i);
rotation.Remove(i);
}
}
value.Remove(index);
}
else
{
Debug.Log("没有当前帧");
}
}
}
/// <summary>
/// 为Transform进行赋值
/// </summary>
/// <param name="percentage">百分比</param>
/// <param name="transformObj">需要获取数据的物体Transform</param>
public void GetPositionDatas(float percentage, Transform transformObj)
{
int index = GetIndex(percentage);
if (value.Contains(index))
{
for (int i = 0; i < position.total.keys.Length; i++)
{
if (position.total.keys[i].time == index)
{
transformObj.position = position.FindPosition(i);
transformObj.rotation = rotation.FindQuaternion(i);
}
}
}
else
{
Debug.Log("该帧没有数据");
}
}
/// <summary>
/// 修改关键帧
/// </summary>
/// <param name="percentage"></param>
public void ChangeTransformDatas(float percentage,Transform transformObj)
{
// 获得索引值
int index = GetIndex(percentage);
for (int i = 0; i < position.total.keys.Length; i++)
{
// 如果要插入的帧前面为0
if (position.total.keys[i].time == index)
{
position.Insert(i, i, transformObj.position);
rotation.Insert(i, i, transformObj.rotation);
}
}
}
}
/*--------------------------------计算Position------------------------------*/
public class TimelinedVector3
{
public AnimationCurve x = new AnimationCurve();
public AnimationCurve y = new AnimationCurve();
public AnimationCurve z = new AnimationCurve();
public AnimationCurve total = new AnimationCurve();
public void Add(int index, Vector3 v)
{
x.AddKey(index, v.x);
y.AddKey(index, v.y);
z.AddKey(index, v.z);
total.AddKey(index, 0);
}
public void Insert(int leftIndex, int index, Vector3 v)
{
x.MoveKey(leftIndex, new Keyframe(index, v.x));
y.MoveKey(leftIndex, new Keyframe(index, v.y));
z.MoveKey(leftIndex, new Keyframe(index, v.y));
total.MoveKey(leftIndex, new Keyframe(index, 0));
}
public void Remove(int index)
{
x.RemoveKey(index);
y.RemoveKey(index);
z.RemoveKey(index);
total.RemoveKey(index);
}
public Vector3 FindPosition(int index)
{
return new Vector3(x.keys[index].value, y.keys[index].value, z.keys[index].value);
}
}
/*------------------------------------------计算Quaternion--------------------------------------*/
public class TimelinedQuaternion
{
public AnimationCurve x = new AnimationCurve();
public AnimationCurve y = new AnimationCurve();
public AnimationCurve z = new AnimationCurve();
public AnimationCurve w = new AnimationCurve();
public AnimationCurve total = new AnimationCurve();
public void Add(int index, Quaternion v)
{
x.AddKey(index, v.x);
y.AddKey(index, v.y);
z.AddKey(index, v.z);
w.AddKey(index, v.w);
total.AddKey(index, 0);
}
public void Insert(int leftIndex, int index, Quaternion v)
{
x.MoveKey(leftIndex, new Keyframe(index, v.x));
y.MoveKey(leftIndex, new Keyframe(index, v.y));
z.MoveKey(leftIndex, new Keyframe(index, v.y));
w.MoveKey(leftIndex, new Keyframe(index, v.w));
total.MoveKey(leftIndex, new Keyframe(index, 0));
}
public void Remove(int index)
{
x.RemoveKey(index);
y.RemoveKey(index);
z.RemoveKey(index);
w.RemoveKey(index);
total.RemoveKey(index);
}
public Quaternion FindQuaternion(int index)
{
return new Quaternion(x.keys[index].value, y.keys[index].value, z.keys[index].value, w.keys[index].value);
}
}