通过Unity标准资产以编程方式旋转第三人称角色

时间:2019-02-02 22:23:08

标签: unity3d 3d

我正在尝试自动在Unity中对第三人称角色进行随机旋转,并且希望对旋转进行动画,就好像我是使用开箱即用的控制器自己旋转玩家一样和WASD键。目标是随机旋转的NPC,在人群中寻找某人。

这是我到目前为止在更新的协程中尝试过的。

float xDegress = Random.Range(10f, 75f);
float yDegress = Random.Range(10f, 75f);
float zDegress = Random.Range(10f, 75f);

// Works but immediate
this.transform.Rotate(0f, yDegress, 0f);

// Works but immediate
this.transform.LookAt(new Vector3(xDegress, 0f, zDegress));

// Doesn't work 
rB.rotation = Quaternion.Lerp(transform.rotation, new Quaternion(0, yDegress, 0, 0), 0.5f);

// Doesn't work 
rB.MoveRotation(new Quaternion(0, yDegress, 0, 1).normalized);

// Works but immediate
Vector3 newPosition = new Vector3(xDegress, 0f, zDegress);
transform.rotation = Quaternion.Lerp(
    transform.rotation,
    Quaternion.LookRotation(newPosition, Vector3.up),
    0.5f);

yield return new WaitForSeconds(_pauseSeconds);

这里是NPC的检查员,这是标准资产中的Ethan。

enter image description here

1 个答案:

答案 0 :(得分:0)

首先,因为它是RigidBody,所以您完全不应该使用transform.rotation =transform.,而应该使用rb.MoveRotation或任何rb.rotation方法。

比您以错误的方式使用Lerp。您想要的是一个从01的值。始终以固定的0.5f因子调用一次,导致第一和第二个旋转中间 一个-立即。


首先,您需要轮换的持续时间。

// How long in seconds should the rotation take? 
// might be a constant or set via the inspector
public float rotationDuration = 1.0f;

比开始旋转之前先旋转和结束旋转

float xDegress = Random.Range(10f, 75f);
float yDegress = Random.Range(10f, 75f);
float zDegress = Random.Range(10f, 75f);

var currentRotation = transform.rotation;

var targetRotation = currentRotation * Quaternion.Euler(xDegress, yDegress, zDegress);
// or
Vector3 newPosition = new Vector3(xDegress, 0f, zDegress);
var targetRotation = Quaternion.LookRotation(newPosition, Vector3.up);
// or whatever your target rotation shall be

现在,由于您已经在协程中,因此只需添加一个while循环即可在所需的持续时间内执行旋转(不过请不要忘记yield

var passedTime = 1.0f;
while(passedTime < rotationDuration)
{
    // interpolate the rotation between the original and the targetRotation
    // factor is a value between 0 and 1
    rb.MoveRotation = Quaternion.Lerp(currentRotation, targetRotation, passedTime / rotationDuration);

    // add time passed since last frame
    passedtime += Time.deltaTime;
    yield return null;
}

// to avoid overshooting set the target rotation fix when done
transform.rotation = targetRotation;

yield return new WaitForSeconds(_pauseSeconds);