之前讲了自己分解成不同的数学模型来实现,但是可随意性更改尺度不大,所以思考着用AnimationCurve实现,并简单搞了个编辑插件,方便让策划自己进行调整;这个也是参考了谁的,具体也忘记了,多谢那位大大;
以下是插件代码,能推导出具体实现,我就不贴具体实现代码了;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class EditorCurves : EditorWindow
{
private float xTime = 0;
private float yTime = 0;
private float startTime = 0;
private bool bShowAni = false;
private Vector3 startPos;
public string actIdxStr = "15";
AnimationCurve curveX = AnimationCurve.Linear(0, 0, 2, 2);
AnimationCurve curveY = AnimationCurve.Linear(0, 0, 2, 2);
[MenuItem("AniCurve/GenCurve")]
static void Init()
{
EditorWindow window = GetWindow(typeof(EditorCurves));
window.position = new Rect(200, 200, 340, 360);
window.Show();
}
void OnGUI()
{
curveX = EditorGUI.CurveField(new Rect(3, 3, position.width - 6, 25), "Animation on X", curveX);
curveY = EditorGUI.CurveField(new Rect(3, 43, position.width - 6, 25), "Animation on Y", curveY);
GUI.Label(new Rect(3, 80, 200, 25), "Role Show Action Index");
actIdxStr = GUI.TextField(new Rect(153, 80, position.width / 2, 25), actIdxStr);
if (GUI.Button(new Rect(3, 120, position.width - 6, 30), "Generate And Show Curve"))
{
if (Selection.activeGameObject)
{
int actIdx = int.Parse(actIdxStr);
FollowAnimationCurveShow comp = Selection.activeGameObject.GetComponent<FollowAnimationCurveShow>();
if (comp == null)
{
comp = Selection.activeGameObject.AddComponent<FollowAnimationCurveShow>();
}
curveX.postWrapMode = WrapMode.Once;
curveX.preWrapMode = WrapMode.Once;
curveY.postWrapMode = WrapMode.Once;
curveY.preWrapMode = WrapMode.Once;
comp.SetCurves(curveX, curveY, actIdx);
}
else
{
Debug.LogError("No Game Object selected for adding an animation curve");
}
}
if (GUI.Button(new Rect(3, 160, position.width - 6, 30), "Print Curve Param"))
{
SetCurves();
}
}
void SetCurves()
{
Debug.Log("水平动画曲线============================");
int len = curveX.keys.Length;
for (int i = 0; i < len; i++)
{
Keyframe key = curveX.keys[i];
Debug.Log("time:" + key.time + " value:" + key.value + " inTangent:" + key.inTangent + " outTangent:" + key.outTangent + " tangentMode:" + key.tangentMode);
}
Debug.Log("============================");
Debug.Log(" ");
Debug.Log("垂直动画曲线============================");
len = curveY.keys.Length;
for (int i = 0; i < len; i++)
{
Keyframe key = curveY.keys[i];
Debug.Log("time:" + key.time + " value:" + key.value + " inTangent:" + key.inTangent + " outTangent:" + key.outTangent + " tangentMode:" + key.tangentMode);
}
Debug.Log("============================");
}
}
public class FollowAnimationCurveShow : MonoBehaviour
{
public AnimationCurve curveX;
public AnimationCurve curveY;
private bool bShowAni = false;
private float xTime = 0;
private float yTime = 0;
private float startTime = 0;
private Vector3 startPos;
private Vector3 endPos;
private float endTime = 0;
public void SetCurves(AnimationCurve tmpCurveX, AnimationCurve tmpCurveY, int showIdx)
{
if (bShowAni)
{
Debug.LogError("animation curve is begining, waitting a monment");
return;
}
bShowAni = true;
curveX = tmpCurveX;
int len = tmpCurveX.keys.Length;
for (int i = 0; i < len; i++)
{
Keyframe key = tmpCurveX.keys[i];
xTime = key.time;
}
curveY = tmpCurveY;
len = tmpCurveY.keys.Length;
for (int i = 0; i < len; i++)
{
Keyframe key = tmpCurveY.keys[i];
yTime = key.time;
}
startTime = Time.realtimeSinceStartup;
startPos = transform.position;
Animator []ani = transform.GetComponents<Animator>();
if (ani != null && ani.Length > 0)
{
for (int i = 0; i < ani.Length; i ++)
{
ani[i].SetInteger("action", showIdx);
}
}
}
void Update()
{
if (! bShowAni)
{
if (Time.realtimeSinceStartup - endTime < 1)
{
transform.parent.transform.position = endPos;
}
else
{
transform.parent.transform.position = startPos;
}
return;
}
float h = 0;
float d = 0;
bool bEnd = true;
float dt = Time.realtimeSinceStartup - startTime;
if (curveX != null && dt <= xTime)
{
bEnd = false;
d = curveX.Evaluate(dt) * 10;
}
if (curveY != null && dt <= yTime)
{
bEnd = false;
h = curveY.Evaluate(dt) * 10;
}
if (bEnd)
{
endTime = Time.realtimeSinceStartup;
bShowAni = false;
Animator[] ani = transform.GetComponents<Animator>();
if (ani != null && ani.Length > 0)
{
for (int i = 0; i < ani.Length; i++)
{
ani[i].SetInteger("action", 0);
}
}
return;
}
endTime = 0;
float rotAngle = (90 - transform.eulerAngles.y) * Mathf.PI / 180;
float posx = startPos.x + d * Mathf.Cos(rotAngle);
float posy = startPos.y + h;
float posz = startPos.z + d * Mathf.Sin(rotAngle);
endPos = new Vector3(posx, posy, posz);
transform.parent.transform.position = endPos;
}
}
输出的参数填写到配置,然后根据配置的keys实现曲线运动轨迹效果,而且还可以增加其它变化,比如朝向啊之类的。