- Home /
How to create a delay in a function being called in update?
I am having an issue trying to delay my code once a certain condition has been met. Basically I have a laser object that turns towards a max angle and once that angle is reached, it revolves back the other way. I want to be able to pause the laser as it hits the max angle for a certain amount of time, then continue with the rest of the code. My code is shown below
public class LaserRotate : MonoBehaviour
{
[Header("XZ Plane Rotation")]
public bool ContinuousRotation; //if laser should continue to rotate
[Range(0,179)] //Anything greater or equal to 180 causes full revolution
public float RotationAngle; // max total rotation angle from starting point in xz direction
public float RotationSpeed; //How fast to rotate
private Quaternion StartingRotation;
private Quaternion TargetRotation;
private float RelativeRotation; //signifies angle with respect to starting position
private Vector3 AngleRotate;
private int direction = 1; //positive is clockwise,negative counter
// Use this for initialization
void Start ()
{
AngleRotate = new Vector3(0, direction * RotationAngle, 0);
StartingRotation = transform.rotation;
TargetRotation = Quaternion.AngleAxis(RotationAngle, AngleRotate);
RelativeRotation = transform.rotation.eulerAngles.y - StartingRotation.eulerAngles.y;
}
// Update is called once per frame
void Update ()
{
LaserRotation();
}
public void LaserRotation()
{
AngleRotate = new Vector3(0, direction * RotationAngle, 0);
TargetRotation = Quaternion.AngleAxis(RotationAngle, AngleRotate * direction);
RelativeRotation = (transform.rotation.eulerAngles.y - StartingRotation.eulerAngles.y);
if (Mathf.Abs(RelativeRotation) > 180)
{
RelativeRotation = 360 - Mathf.Abs(RelativeRotation);
}
//print("Relative Rotation angle is: " + RelativeRotation);
//print("Target Rotation is: " + TargetRotation.eulerAngles.y);
if (RelativeRotation >= TargetRotation.eulerAngles.y)
{
direction = direction * -1;
StartingRotation = transform.rotation;
print("Reversing direction...");
}
transform.Rotate(AngleRotate * Time.deltaTime * RotationSpeed);
}
}
In the segment
if (RelativeRotation >= TargetRotation.eulerAngles.y)
{
direction = direction * -1;
StartingRotation = transform.rotation;
print("Reversing direction...");
}
I want to add a small delay, because this signifies when the max angle has been reached. I want the laser to stay there for about a second, then continue with the rest of the code.
I've tried using coroutines, but this does not prevent the update from completing. If I try putting the entire function in a repeating coroutine that I call from start, the laser just jumps from max position to beginning position.
Answer by RealCool_Guy · Aug 28, 2018 at 03:23 AM
private void timer;
private bool TimeStart;
public void LaserRotation()
{
AngleRotate = new Vector3(0, direction * RotationAngle, 0);
TargetRotation = Quaternion.AngleAxis(RotationAngle, AngleRotate * direction);
RelativeRotation = (transform.rotation.eulerAngles.y - StartingRotation.eulerAngles.y);
if (Mathf.Abs(RelativeRotation) > 180)
{
RelativeRotation = 360 - Mathf.Abs(RelativeRotation);
}
//print("Relative Rotation angle is: " + RelativeRotation);
//print("Target Rotation is: " + TargetRotation.eulerAngles.y);
if (RelativeRotation >= TargetRotation.eulerAngles.y)
{
TimeStart = true;
timer += Time.deltaTime;
if (timer > 1)
{
timer = 0;
direction = direction * -1;
StartingRotation = transform.rotation;
print("Reversing direction...");
TimeStart = false;
}
}
if(TimeStart == false)
{
transform.Rotate(AngleRotate * Time.deltaTime * RotationSpeed);
}
else { }
}
I like the idea, however the last line
transform.Rotate(AngleRotate Time.deltaTime RotationSpeed);
is the line that causes the laser to rotate. The code you provided prevents the laser from stopping at the max angle, instead it continues rotating beyond.
But your code gave me an idea, with only a little tweak it runs as intended for now. I added in a bool TimeStart. When the it reaches max angle its value is set to true, and the laser is no longer rotated. After 1 second has passed TimeStart is set to false and the laser can now rotate again. Why do most of the answers related to creating a Delay suggest a coroutine? I understand it has little to no overhead, but it seems like this method is quicker and easier. I still have no idea how I would implement this with a coroutine @Hellium
$$anonymous$$aybe, if you set RelativeRotation
to 0 inside if (RelativeRotation >= TargetRotation.eulerAngles.y)
, you won't need the boolean.
In your case, I don't believe using a coroutine will be cleaner or simpler.
Ah okay thank you for the suggestion. I think I've got my answer with your help
Answer by Hellium · Aug 27, 2018 at 09:21 PM
Following code not tested
private float timer = 0 ;
public void LaserRotation()
{
AngleRotate = new Vector3(0, direction * RotationAngle, 0);
TargetRotation = Quaternion.AngleAxis(RotationAngle, AngleRotate * direction);
RelativeRotation = (transform.rotation.eulerAngles.y - StartingRotation.eulerAngles.y);
if (Mathf.Abs(RelativeRotation) > 180)
{
RelativeRotation = 360 - Mathf.Abs(RelativeRotation);
}
//print("Relative Rotation angle is: " + RelativeRotation);
//print("Target Rotation is: " + TargetRotation.eulerAngles.y);
if (RelativeRotation >= TargetRotation.eulerAngles.y)
{
timer += Time.deltaTime ;
if (timer > 1)
{
timer = 0 ;
direction = -direction;
StartingRotation = transform.rotation;
print("Reversing direction...");
}
}
transform.Rotate(AngleRotate * Time.deltaTime * RotationSpeed);
}