在Unity中向两个方向旋转门

时间:2017-10-10 09:18:10

标签: c# unity3d rotation

我在Unity创建了一个开门和关门。我可以致电Interact()打开那扇门。

现在我想创建一个始终远离玩家的门。就像一个沙龙的门。如果玩家在房间前面,门会旋转到房间,如果玩家在房间内,门会旋转出来。

目前我创建了一个bool opensAwayFromPlayer。如果这是真的,打开门时应该固定目标旋转。

[SerializeField]
private Vector3 targetRotation; // rotation angles

[SerializeField]
private float duration; // rotation speed

[SerializeField]
private bool closeAgain; // close the door again?

[SerializeField]
private float waitInterval; // close the door after x seconds

[SerializeField]
private Vector3 pivotPosition; // Vector3 of the pivot

[SerializeField]
private bool opensAwayFromPlayer; // door can open both directions

[SerializeField]
private Transform playerTransform; // Player Object

private Vector3 defaultRotation; // store the rotation when starting the game
private bool isActive = false;

Transform doorPivot; // the pivot point to rotate around

private void Start()
{
    doorPivot = new GameObject().transform; // create pivot
    doorPivot.position = pivotPosition; // place the pivot before parenting!
    transform.SetParent(doorPivot); // make the door being a child of the pivot
    defaultRotation = doorPivot.eulerAngles;
}

private IEnumerator DoorRotation()
{
    if (isActive)
        yield break;

    isActive = true;

    float counter = 0;
    Vector3 defaultAngles = doorPivot.eulerAngles;
    Vector3 openRotation = transform.eulerAngles + targetRotation;

    while (counter < duration)
    {
        counter += Time.deltaTime;
        LerpDoor(defaultAngles, openRotation, counter); // open the door
        yield return null;
    }

    if (!closeAgain)
        Destroy(this);

    yield return new WaitForSeconds(waitInterval); // wait some seconds

    while (counter > 0)
    {
        counter -= Time.deltaTime;
        LerpDoor(defaultAngles, openRotation, counter); // close the door
        yield return null;
    }

    isActive = false;
}

private void LerpDoor(Vector3 defaultAngles, Vector3 targetRotation, float counter)
{
    doorPivot.eulerAngles = Vector3.Lerp(defaultAngles, targetRotation, counter / duration);
}

private bool PlayerIsBehindDoor() // is the player in front of or behind the door?
{
    Vector3 doorTransformDirection = transform.TransformDirection(Vector3.forward); // door direction
    Vector3 playerTransformDirection = playerTransform.position - transform.position; // player direction
    return Vector3.Dot(doorTransformDirection, playerTransformDirection) < 0; // return player is in front or behind the door
}

public void Interact() // start the rotation
{
    StartCoroutine(DoorRotation());
}

正如你在这里看到的那样

if (opensAwayFromPlayer) // door can open both directions?
{
   if (PlayerIsBehindDoor()) // Player is behind the door? (in the room)
   {
       // openRotation = ; // open to the other direction
       // closeRotation = ; // close / back to the default rotation 
   }
}

我不知道如何计算它的不同轮换。只是将旋转设置为负值并不起作用。

当我将门向另一个方向旋转90度时,它没有向后旋转,向后旋转270度,同时向另一个方向旋转。

1 个答案:

答案 0 :(得分:3)

这应该是最终的脚本。您可以通过在游戏对象上拖动脚本并调用方法Interact()

来测试它
 [SerializeField]
    private Vector3 targetRotation;

    [SerializeField]
    private float duration;

    [SerializeField]
    private bool closeAgain;

    [SerializeField]
    private float waitInterval;

    [SerializeField]
    private Vector3 pivotPosition;

    [SerializeField]
    private bool opensAwayFromPlayer;

    private Vector3 defaultRotation;

    private bool isActive = false;

    private Transform doorPivot;

    private Transform playerTransform;

    private void Start()
    {
        playerTransform = Globals.GetPlayerObject().transform;
        doorPivot = new GameObject().transform;
        doorPivot.position = pivotPosition;
        transform.SetParent(doorPivot);
        defaultRotation = doorPivot.eulerAngles;
    }

    private IEnumerator DoorRotation()
    {
        if (isActive)
            yield break;

        isActive = true;

        float counter = 0;
        Vector3 defaultAngles = doorPivot.eulerAngles;

        if (PlayerIsBehindDoor())
            targetRotation = -targetRotation;

        Vector3 openRotation = transform.eulerAngles + targetRotation;

        while (counter < duration)
        {
            counter += Time.deltaTime;
            LerpDoor(defaultAngles, openRotation, counter);
            yield return null;
        }

        if (!closeAgain)
            Destroy(this);

        yield return new WaitForSeconds(waitInterval);

        while (counter > 0)
        {
            counter -= Time.deltaTime;
            LerpDoor(defaultAngles, openRotation, counter);
            yield return null;
        }

        isActive = false;
    }

    private void LerpDoor(Vector3 defaultAngles, Vector3 targetRotation, float counter)
    {
        doorPivot.eulerAngles = Vector3.Lerp(defaultAngles, targetRotation, counter / duration);
    }

    private bool PlayerIsBehindDoor()
    {
        Vector3 doorTransformDirection = transform.TransformDirection(Vector3.forward);
        Vector3 playerTransformDirection = playerTransform.position - transform.position;
        return Vector3.Dot(doorTransformDirection, playerTransformDirection) < 0;
    }

    public void Interact()
    {
        StartCoroutine(DoorRotation());
    }