2017-10-10 3 views
3

J'ai créé une porte d'ouverture et de fermeture dans Unity. Je peux ouvrir cette porte en appelant le Interact().Faire pivoter une porte dans les deux sens dans Unity

Maintenant, je veux créer une porte qui s'ouvre toujours loin du lecteur. Comme une porte d'un salon. Si le joueur est devant une pièce, la porte pivote vers la pièce, si le joueur est dans la pièce, la porte tourne à l'extérieur. J'ai actuellement créé un booléen opensAwayFromPlayer. Si cela est vrai, les rotations de la cible doivent être fixes, lors de l'ouverture de la porte.

[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()); 
} 

Comme vous pouvez le voir ici

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 
    } 
} 

Je ne sais pas comment calculer la différence de rotation pour elle. Le simple réglage des rotations sur des valeurs négatives n'a pas fonctionné.

Et quand j'ai tourné la porte dans l'autre direction à 90 degrés, elle n'a pas tourné en arrière, elle a tourné de 270 degrés vers l'arrière tout en restant dans l'autre sens.

+0

nit: 'tranform.forward' retourne la même chose que' transform.TransformDirection (Vector3.forward) '. – Foggzie

Répondre

3

Cela devrait être le dernier script. Vous pouvez le tester en faisant glisser le script sur un gameobject et appelant la méthode 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()); 
    }