最近在处理飞行效果的需求,类似【完美世界】里的飞行(五连跳?),起初是自己琢磨其中每一段飞行的轨迹并分解成不同数学模型,实现了直线匀变速、二阶贝塞尔曲线、抛物线轨迹效果,其代码如下:
一、直线匀变速(我就不整合向上向下了,亦或者归结为90度的斜抛物运动轨迹)
// startPos 起始位置
// curShowPoint 当前位置
// startDir 起始朝向
// 当前朝向
// dt 该段轨迹开始到当前的时间
private Vector3 getShowPosByLineUp(Vector3 startPos, Vector3 curShowPoint, float startDir, float curDir, float dt)
{
if (sLen == -1)
{
sLen = Mathf.Sqrt(height * height + distance + distance);
}
if (startSpeed == -99999)// 直线向上运动
{
startSpeed = speed;//(sLen + accSpeed * time * time / 2) / time;
}
curSpeed = startSpeed - accSpeed * dt;
float d = startSpeed * dt - accSpeed * dt * dt / 2;
float rate = d / sLen;
float rotAngle = (float)((curDir - startDir) * Math.PI / 180);
Vector3 vec = Quaternion.AngleAxis(rotAngle, new Vector3(curShowPoint.x, startPos.y, curShowPoint.z)) * startPos;
rotAngle = (float)(curDir * Math.PI / 180);
float posx = vec.x + distance * rate * Mathf.Cos(rotAngle);
float posy = startPos.y + height * rate;
float posz = vec.z + distance * rate * Mathf.Sin(rotAngle);
return new Vector3(posx, posy, posz);
}
二、二阶贝塞尔曲线
private Vector3 getShowPosByBezier(Vector3 startPos, Vector3 curShowPoint, float startDir, float curDir, float dt)
{
float rotAngle = (float)((curDir - startDir) * Math.PI / 180);
Vector3 v0 = Quaternion.AngleAxis(rotAngle, new Vector3(curShowPoint.x, startPos.y, curShowPoint.z)) * startPos;
double a = curDir * Math.PI / 180;
float cosD = (float)Math.Cos(a);
float sinD = (float)Math.Sin(a);
Vector3 v1 = new Vector3(v0.x + distance * 0.3f * cosD, height + v0.y, v0.z + distance * 0.3f * sinD);
Vector3 v2 = new Vector3(v0.x + distance * cosD, v0.y, v0.z + distance * sinD);
float t = MapUtil.GetGroundY3(v2 * Direction2D.MAP_RATE);
if (t != -9999999)
{
v2.y = t * Direction2D.MAP_RATE_MUL;
}
return calculateCubicBezierPoint(dt, v0, v1, v2);
}
public Vector3 calculateCubicBezierPoint(float t, Vector3 p0, Vector3 p1, Vector3 p2)
{
float u = 1 - t;
float tt = t * t;
float uu = u * u;
Vector3 p = uu * p0;
p += 2 * u * t * p1;
p += tt * p2;
return p;
}
三、抛物线
private Vector3 getShowPosByParaCurve(Vector3 startPos, Vector3 curShowPoint, float startDir, float curDir, float dt)
{
if (startSpeed == -99999)// 抛物线运动
{
startSpeed = speed;
}
curSpeed = startSpeed;
float d = startSpeed * dt * Mathf.Cos(paraCurveAngle);
float h = startSpeed * dt * Mathf.Sin(paraCurveAngle) - (accSpeed * dt * dt) / 2;
float rotAngle = (float)(curDir * Math.PI / 180);
float posx = startPos.x + d * Mathf.Cos(rotAngle);
float posy = startPos.y + h;
float posz = startPos.z + d * Mathf.Sin(rotAngle);
return new Vector3(posx, posy, posz);
}
上面三种是强行用用数学模型计算飞行轨迹,效率未知,但对于需求千变万化不太适应,所以一直查找其它方式实现。起初想结合itween,后来发现AnimationCurve更适合,会在后续贴出;
(非常抱歉我的数学烂,该处的旋转是存在问题的,不是居于当前玩家位置的xz和初试位置的y构成的点进行旋转的,所以最终飞行过程中转向效果不对,因为暂时有更紧急的事要处理暂时放这,希望有大神帮忙解决下)