2017-10-10 220 views
3

我在Unity中创建了开门和关门。我可以打电话Interact()打开那扇门。在Unity中向两个方向旋转门

现在我想创建一个总是远离玩家打开的门。就像一个轿车的门。如果玩家在房间前面,则门旋转到房间,如果玩家在房间内,则门旋转。

当前我创建了一个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度,而与另一个方向保持一致。

+0

尼特测试。 – Foggzie

回答

3

这应该是最后的脚本。 `tranform.forward`返回同样的事情`transform.TransformDirection(Vector3.forward)`:您可以通过拖动一个游戏物体的脚本,调用该方法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()); 
    }