在Unity中向两个方向旋转门 [英] Rotate a door in both directions in Unity

查看:97
本文介绍了在Unity中向两个方向旋转门的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Unity中创建了一个开门和关门.我可以通过拨打Interact()来打开那扇门.

I created a opening and closing door in Unity. I can open that door by calling Interact().

现在,我要创建一扇始终从玩家打开的门.就像轿车门一样.如果玩家在房间前面,则门会旋转到房间;如果玩家在房间里,则门会旋转出房间.

Now I want to create a door that opens always away from the player. Like a door of a saloon. If the player is in front of a room, the door rotates to the room, if the player is in the room, the door rotates out of it.

当前,我创建了一个布尔值opensAwayFromPlayer.如果是这样,打开门时应该固定目标旋转.

Currently I created a bool opensAwayFromPlayer. If this is true, the target rotations should be fixed, when opening the door.

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

我不知道如何计算它的不同旋转角度.只是将旋转设置为负值是行不通的.

I don't know how to calculate the different rotation for it. Just setting the rotations to negative values didn't work.

当我将门向另一个方向旋转90度时,它没有向后旋转,而是在保持另一个方向的情况下向后旋转了270度.

And when I rotated the door to the other direction to 90 degrees, it didn't rotate back, it rotated 270 degrees back while staying with the other direction.

推荐答案

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

This should be the final script. You can test it by dragging the script on a gameobject and calling the method 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());
    }

这篇关于在Unity中向两个方向旋转门的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆