I’m working on a game that requires the use of door.
I came up with this script:
using UnityEngine;
public class Door : MonoBehaviour
{
[SerializeField] enum OpenDirection { HORIZONTAL, VERTICAL };
[SerializeField] OpenDirection openDirection;
[SerializeField] float angle;
private Vector3 originalRotation;
public bool open = false;
private void Start()
{
originalRotation = transform.eulerAngles;
Open();
}
public void Open()
{
switch (openDirection)
{
case OpenDirection.HORIZONTAL:
while (transform.eulerAngles.z != angle)
{
transform.eulerAngles = new Vector3(transform.eulerAngles.x, transform.eulerAngles.y, Mathf.Lerp(transform.eulerAngles.z, angle, 2 * Time.deltaTime));
}
break;
case OpenDirection.VERTICAL:
while(transform.eulerAngles.x != angle)
{
transform.eulerAngles = new Vector3(Mathf.Lerp(transform.eulerAngles.x, angle, 2 * Time.deltaTime), transform.eulerAngles.y, transform.eulerAngles.z);
}
break;
}
open = true;
}
public void Close()
{
while(transform.eulerAngles != originalRotation)
{
transform.eulerAngles = Vector3.Lerp(transform.eulerAngles, originalRotation, 2 * Time.deltaTime);
}
open = false;
}
}
However, Unity freezes whenever I call the Open method (I’m calling it in start not Update).
I don’t know why it’s doing this, as there really shouldn’t be a n infinite for-loop right?
I want to refrain from using animations for doors as I really don’t want to make an animation for every door I in the game.
I really want a “universal door” script.
You’re doing animations wrong. The same animation would be used for all instances of a given door. You make a prefab and when it works perfectly, you use it for all doors.
Use a tweener then (perhaps DOTween?), unless you wanna write your own.
A: Your while loop is going infinite because
B: Don’t compare floating point values for equality
C: Write a coroutine if you want things to happen over time.
Okay, I put everything in a coroutine, and even accounted for floating point precision. However, while my doors open now, they continue to spin forever seemingly ignoring the conditions of the while loop.
using System.Collections;
using UnityEngine;
public class Door : MonoBehaviour
{
[SerializeField] enum OpenDirection { HORIZONTAL, VERTICAL };
[SerializeField] OpenDirection openDirection;
[SerializeField] float angle;
private Vector3 originalRotation;
public bool open = false;
private void Start()
{
originalRotation = transform.eulerAngles;
Interact();
}
public void Interact()
{
if (!open)
{
open = true;
StartCoroutine("Open");
}
else
{
open = false;
StartCoroutine("Close");
}
}
IEnumerator Open()
{
print("Opening door");
switch (openDirection)
{
case OpenDirection.HORIZONTAL:
while (Mathf.Abs(transform.eulerAngles.z - angle) > 0.01) //for floating point precsion
{
transform.eulerAngles = Vector3.Lerp(transform.eulerAngles, new Vector3(transform.eulerAngles.x, transform.eulerAngles.y, angle), 2 * Time.deltaTime);
yield return null;
}
break;
case OpenDirection.VERTICAL:
while (Mathf.Abs(transform.eulerAngles.x - angle) > 0.01) //for floating point precsion
{
transform.eulerAngles = Vector3.Lerp(transform.eulerAngles, new Vector3(angle, transform.eulerAngles.y, transform.eulerAngles.z), 2 * Time.deltaTime);
yield return null;
}
break;
}
}
IEnumerator Close()
{
print("Closing Door");
while (transform.eulerAngles != originalRotation)
{
transform.eulerAngles = Vector3.Lerp(transform.eulerAngles, originalRotation, 2 * Time.deltaTime);
yield return null;
}
}
}
Because
A: You’re using lerp incorrectly. It is not correct to throw Time.deltaTime into lerp as that demonstrates a misunderstanding on how it works.
B: Euler angles are not reliable way to measure rotations.
Also, why is it not reamended to use Time.deltaTime in a lerp? if t is the percent we need to lerp between the two values, wouldn’t using Tim.deltaTime sync between frames?
Maintain your own start and end values, and maintain a value that moved between a and b. Your while loop can operate on your own value, and not the euler angles.