我正在制作一款3D游戏并尝试正确设置角色动作。交互很简单,屏幕上有一个单一的模型,用户点击屏幕上的一个点,模型旋转面对点击的点(此时模型是一个有点眼睛的幽灵,所以眼睛转向面对点击,并且,一旦面对该点,模型将移动到那里。
我使用了一些我自己编写的代码,但动画并不平滑,模型经常会超出/低于目的地,然后向后或向前猛拉到位。我以前只在2d动画上使用Universal Tween引擎,但决定尝试一下。它解决了急躁问题,并且可以自行旋转和转换两种工作方式,但是我无法让它们按顺序一起工作。
如果我只启用旋转模型的代码,它可以正常工作(好吧,几乎没问题,某些东西变得奇怪,在某些角度确定顺时针或逆时针旋转,但这是以后的另一个问题) :我单击一个位置,模型旋转以面向它并保持新的旋转直到下一次单击,然后它转向面向该位置。与仅启用翻译相同:我点击一个点,模型移动到它并保留它的新翻译,直到我再次点击,然后它移动到该位置等。
当翻译和旋转都启用时,我遇到了问题。模型将首先旋转以面向单击的点,然后设置回其初始旋转,然后移动到单击的点。在随后的点击中,模型将首先返回其初始平移,然后旋转以面向单击的点(实际上是相对于重新初始化的位置的点击点的位置),然后移动到单击的点。
我尝试重新排列代码,使用回调,将新的翻译和轮换缓存到游戏模型类的成员,然后在开始补间之前使用set()
及其值,但没有任何效果。< / p>
以下是我TweenAccessor
的相关代码:
public class GameModelTweenAccessor implements TweenAccessor<DynamicModel> {
public int getValues(DynamicModel target, int tweenType, float[] returnValues) {
trans = target.model.transform.getTranslation(trans);
switch (tweenType) {
...
case POSITION_XYZ:
returnValues[0] = trans.x;
returnValues[1] = trans.y;
returnValues[2] = trans.z;
return 3;
case ROTATION:
axisVec = new Vector3();
angle = target.model.transform.getRotation(new Quaternion()).getAxisAngle(axisVec) * axisVec.nor().y;
returnValues[0] = angle;
return 1;
...
}
}
public void setValues(DynamicModel target, int tweenType, float[] newValues) {
trans = target.model.transform.getTranslation(trans);
switch (tweenType) {
...
case POSITION_XYZ:
target.model.transform.setToTranslation(newValues[0], newValues[1], newValues[2]);
break;
case ROTATION:
target.model.transform.setToRotation(Vector3.Y, newValues[0]);
break;
...
}
}
}
以下是启动时间轴和补间的代码(它在this file中):
Timeline.createSequence()
.push(Tween.to(screen.ghost, GameModelTweenAccessor.ROTATION, Math.abs(angle - newRotation) / 200)
.target(newRotation)
.ease(TweenEquations.easeNone))
.push(Tween.to(screen.ghost, GameModelTweenAccessor.POSITION_XYZ, duration).
target(intersection.x, intersection.y, intersection.z)
.ease(TweenEquations.easeNone))
.start(screen.ghostManager);
有人能指出我的解决方案吗?
编辑:
似乎在每个补间完成后设置的转换在另一个补间完成后重置为0。这些是来自getValues
中setValues
和TweenAccessor
函数的值的日志:
Get Rot: 0.0
Get Trans: x: 0.0 y: 0.0 z: 0.0
Get Rot: 0.0
Get Trans: x: 0.0 y: 0.0 z: 0.0
Get Rot: 0.0
Set Rot: 9.598349
Set Rot: 9.814415
Set Rot: 10.052449
...
Set Rot: 39.99417
Set Rot: 43.397423
Set Rot: 46.62333
Get Trans: x: 0.0 y: 0.0 z: 0.0
Set Trans: x: 0.0012489144 y: 0.0 z: 0.001180494
Set Trans: x: 0.024489587 y: 0.0 z: 0.023147952
Set Trans: x: 0.04921494 y: 0.0 z: 0.04651875
...
Set Trans: x: 6.4197707 y: 0.0 z: 6.06807
Set Trans: x: 6.444479 y: 0.0 z: 6.091425
Set Trans: x: 6.453598 y: 0.0 z: 6.1000443
Get Rot: 0.0
Get Trans: x: 6.453598 y: 0.0 z: 6.1000443
Get Rot: 0.0
Get Trans: x: 6.453598 y: 0.0 z: 6.1000443
Get Rot: 0.0
Set Rot: 3.4318955
Set Rot: 6.795984
Set Rot: 10.0074415
...
Set Rot: 156.79567
Set Rot: 159.99591
Set Rot: 162.38742
Get Trans: x: 0.0 y: 0.0 z: 0.0
Set Trans: x: 0.03550978 y: 3.836017E-8 z: 0.021066409
Set Trans: x: 0.15527377 y: 1.6773768E-7 z: 0.092117175
...
Set Trans: x: 6.848614 y: 7.3983565E-6 z: 4.062985
Set Trans: x: 6.961268 y: 7.5200533E-6 z: 4.129818
Set Trans: x: 7.0624847 y: 7.6293945E-6 z: 4.189865
Get Rot: 0.0
Get Trans: x: 7.0624847 y: 7.6293945E-6 z: 4.189865
Get Rot: 0.0
Get Trans: x: 7.0624847 y: 7.6293945E-6 z: 4.189865
Get Rot: 0.0
Set Rot: -3.2620814
Set Rot: -6.8205137
Set Rot: -9.834579
...
Set Rot: -76.57533
Set Rot: -79.91388
Set Rot: -80.610855
Get Trans: x: 0.0 y: 0.0 z: 0.0
Set Trans: x: 0.01940876 y: 0.0 z: 0.033669088
Set Trans: x: 0.04174851 y: 0.0 z: 0.07242267
Set Trans: x: 0.06332677 y: 0.0 z: 0.109855264
...
Set Trans: x: 2.7853239 y: 0.0 z: 4.8318033
Set Trans: x: 2.808029 y: 0.0 z: 4.8711905
Set Trans: x: 2.827034 y: 0.0 z: 4.9041595
在补间开始之前,为每种类型的补间(平移和旋转)调用 getValues
两次。此时,翻译的值仍然是在最后一个翻译补间结束时设置的值。旋转的值已经设置回0(我猜测是因为下一轮调用setValues
进行轮换)。
setValues
进行旋转,直到达到目标旋转。这是(除了重置旋转)工作,因为我期待和希望。在getRotation
调用之后,翻译被设置回0,0,0,但不是通过调用setValues
(没有记录它)。然后,通过多次setValues
调用将翻译动画化为目标。
在此之后,循环在另一次点击时重新开始,getValues
再次被调用两次以进行旋转和平移。翻译具有在上一次setValues
中最后一次调用Timeline
时设置的值,但只有在轮换(返回0)之后才会通过其补间运行。
对getValues
的4次调用可能是件事。我不确定在我的设置中会导致Timeline
在补间开始之前抓取翻译的值,如果它们应该按顺序运行,因为它们会被推入Timeline
。我也不确定为什么getValues
为每个补间调用两次,但是在补间过程中Tween引擎会调用它两次并不是不可行的。
我非常确定我使用的LibGDX的翻译/旋转功能都很好,他们坚持使用#&#39;对于模型而言,我使用与非Tween-Engine版本相同的翻译。旋转类似,但功能不同。
在第二次翻译期间改变Y值是值得研究的。
答案 0 :(得分:1)
因此解决方案与Universal Tween Engine无关或如何实现。这只是我对LibGDX中矩阵变换函数的不了解。对setToRotation
的调用重置转换矩阵,然后仅应用旋转,从而将前一个转换归零。 setToTranslation
也会这样做,导致轮换失败。
对于翻译,我使用setTranslation
代替,并且旋转不会丢失。我不认为有相似的轮换功能(使用rotate
导致各种问题),所以我得到一个新的Vector3
,其中存储了模型的位置在其中,然后应用setToRotation
,然后将转换设置为新的向量。这是TweenAccessor
的最新代码:
public void setValues(DynamicModel target, int tweenType, float[] newValues) {
trans = target.model.transform.getTranslation(trans);
switch (tweenType) {
...
case POSITION_XYZ:
target.model.transform.setTranslation(newValues[0], newValues[1], newValues[2]);
break;
case ROTATION:
// store the position
Vector3 position = target.model.transform.getTranslation(new Vector3());
// then set the rotation and reset the translation
target.model.transform.setToRotation(Vector3.Y, newValues[0]).setTranslation(position);
break;
default:
assert false;
break;
}
}