在我的2D游戏中,玩家Prefab有子元素,这些子元素是武器(比如剑),所以当玩家移动时,武器会随着他的移动在世界空间中平移,同时保持恒定的局部位置(当然,直到攻击时间)。武器会自动指向附近的敌人,并在他们足够接近时摆动。
我想让武器沿着一个摆动弧旋转,这个摆动弧的旋转点定义在武器向敌人方向的一半范围内。一旦武器开始摆动,弧的局部位置和旋转应该保持不变,不再关心敌人的位置,而世界弧显然会随着玩家平移。武器应该沿着这个弧纯粹相对于玩家。
RotateAround似乎只在世界空间中起作用,因此当武器的世界位置在世界空间中时,试图围绕对象旋转时会导致奇怪的问题(以及我想要的枢轴点的世界位置)将随着玩家平移。此外,我需要它旋转的点需要相对于局部空间,因为当玩家移动时,武器需要保持其局部弧度,同时还随着玩家平移。
我还尝试在武器的transform.localposition上使用Vector3.Slerp,这似乎是一个完美的解决方案,但我似乎无法让弧与我想象的一个好的圆挥杆相匹配。
这次袭击包括三个部分:后摆,前摆和恢复。我最关心的部分是前摆弧,因为其他的可以很容易地通过简单的局部旋转和乐平来实现。
const int BACKSWING = 0;
const int FORESWING = 1;
const int RECOVER = 2;
float[] timeFrac = { .15f, .25f, .6f };
float[] rotations = { 120f, -240f, 120f };
float backSwingDistMultiplier = .5f;
//Swing Attack
public override IEnumerator Attack(float startAngle) {
var totalAttackTime = GetAttackTime();
var backSwingDist = backSwingDistMultiplier * Range;
var startPos = transform.localPosition;
var slerpCenterDiff = PerpDir(dir).normalized;
//Interpolation arrays
float[] swingTimes = { timeFrac[BACKSWING] * totalAttackTime,
timeFrac[FORESWING] * totalAttackTime,
timeFrac[RECOVER] * totalAttackTime };
float[] startAngles = { startAngle,
startAngle + rotations[BACKSWING],
startAngle + rotations[BACKSWING] + rotations[FORESWING] };
Vector3[] swingPositions = { startPos - (dir - slerpCenterDiff ) * backSwingDist,
startPos + dir * Range + slerpCenterDiff * backSwingDist };
Vector3[] slerpCenters = { (startPos + swingPositions[BACKSWING]) * .5f + slerpCenterDiff ,
((swingPositions[BACKSWING] + swingPositions[FORESWING]) * .5f) + slerpCenterDiff };
Vector3[] slerpStarts = { startPos - slerpCenters[BACKSWING],
swingPositions[BACKSWING] - slerpCenters[FORESWING]};
Vector3[] slerpEnds = { swingPositions[BACKSWING] - slerpCenters[BACKSWING],
swingPositions[FORESWING] - slerpCenters[FORESWING]};
timer = 0;
float percentDone;
//A swing attack has backswing, foreswing, and recovery
for (int swing = 0; swing <= 2; swing++) {
while (timer < swingTimes[swing]) {
percentDone = timer / swingTimes[swing];
//Backswing and Foreswing will slerp
if (swing < RECOVER) {
transform.localPosition = Vector3.Slerp(slerpStarts[swing], slerpEnds[swing], percentDone);
transform.localPosition += slerpCenters[swing];
} else { //Recover will lerp
transform.localPosition = Vector3.Lerp(swingPositions[FORESWING], startPos, percentDone);
}
transform.localRotation = Quaternion.Euler(0, 0,
startAngles[swing] + rotations[swing] * percentDone);
timer += Time.deltaTime;
yield return null;
}
transform.localRotation = Quaternion.Euler(0, 0, startAngles[swing] + rotations[swing]);
timer -= swingTimes[swing];
}
transform.localPosition = startPos;
}
我只想做一个动画出来,但我需要的范围是动态的,这是几乎不可能实现的关键帧。
1条答案
按热度按时间brccelvz1#
我能够通过首先在localPosition中定义弧中心来获得我想要的结果:
然后使用添加到玩家世界空间的位置调用RotateAround