2017-10-10 31 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

마지막 스크립트 여야합니다. ``transform.TransformDirection (Vector3.forward)`같은 일을 반환 tranform.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()); 
    }