Coroutine: delay transform rotation but start transform movement immediately
Hi,
At the moment I've written this script so that when a boolean value is toggled on, I move the camera to a new position and rotation over time.
The problem I'm having is that in the coroutine MoveToPositionOrtho, I want to start the movement immediately, but have a delay of 2 seconds before rotating the camera. But I still want the movement and rotation to finish at the same time.
I can't work out how I need to write this, because if I move the transform.position above the line yield WaitForSeconds
this stops the movement during the delay.
Does anyone have any pointers on how I should go about scripting this - is it possible to have a delay only affecting the rotation and not the movement?
using UnityEngine;
using System.Collections;
[RequireComponent (typeof(MatrixBlender))]
public class PerspectiveSwitchFinal : MonoBehaviour {
private Matrix4x4 ortho, perspective;
public float fov = 60f,
near = 0.3f,
far = 1000f,
orthographicSize = 50f;
private float aspect;
private MatrixBlender blender;
public bool orthoOn;
public GameObject cameraMain;
private float degree;
private float angle;
void Start()
{
aspect = (float) Screen.width / (float) Screen.height;
ortho = Matrix4x4.Ortho(-orthographicSize * aspect, orthographicSize * aspect, -orthographicSize, orthographicSize, near, far);
perspective = Matrix4x4.Perspective(fov, aspect, near, far);
GetComponent<Camera>().projectionMatrix = ortho;
orthoOn = true;
blender = (MatrixBlender) GetComponent(typeof(MatrixBlender));
}
public void orthoToggle(bool on)
{
orthoOn = on;
if (orthoOn != true)
{
blender.BlendToMatrix(perspective, 12f);
degree = 6f;
StopAllCoroutines();
StartCoroutine (MoveToPositionPersp (new Vector3(0,0.5f,-12f), 8f, 0f));
}
if (orthoOn == true)
{
blender.BlendToMatrix(ortho, 6f);
degree = 45f;
StopAllCoroutines();
StartCoroutine ( MoveToPositionOrtho (new Vector3(0,5.5f,-3.6f), 2f, 4f)); //4 3.2
}
}
public IEnumerator MoveToPositionOrtho(Vector3 position, float timeToMove, float waitTime)
{
yield return new WaitForSeconds(waitTime);
var currentPos = transform.position;
var currentPosRotate = transform.rotation;
var t = 0f;
while(t < 1)
{
t += Time.deltaTime / timeToMove;
transform.position = Vector3.Lerp(currentPos, position, t);
angle = Mathf.LerpAngle(transform.rotation.x, degree, Time.deltaTime);
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.Euler(degree, 0, 0), t);
yield return null;
}
}
public IEnumerator MoveToPositionPersp(Vector3 position, float timeToMove, float waitTime)
{
yield return new WaitForSeconds(waitTime);
var currentPos = transform.position;
var currentPosRotate = transform.rotation;
var t = 0f;
while(t < 1)
{
t += Time.deltaTime / timeToMove;
transform.position = Vector3.Lerp(currentPos, position, t);
angle = Mathf.LerpAngle(transform.rotation.x, degree, Time.deltaTime);
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.Euler(degree, 0, 0), t);
yield return null;
}
}
}
Any help would be so much appreciated!
Best, Laurien
Answer by NoseKills · Jul 02, 2016 at 10:14 PM
Calculate another 't' that for example starts '2 seconds below zero' , increment it proportionally faster so it reaches 1 at the same time with 't' and use that value as 't' for rotation.
const float delay = 2f;
var t = 0f;
var ratio = delay/(timeToMove - delay);// ratio of delay vs. time left for rotation
var t2 = -ratio;
while(t < 1)
{
t += Time.deltaTime / timeToMove;
t2 += Time.deltaTime / (timeToMove/(1 + ratio));
...
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.Euler(degree, 0, 0), t2);
}
On my mobile. Not sure about the math coz i couldn't test it.
Another way of course would be to use separate coroutines for movement & rotation.
You must separately handle situations where timeToMove
is less than delay.
That's so great thanks - I've got that working now!!! Though what do you mean by separately handling the situations where timeTo$$anonymous$$ove is less than the delay, as isn't the delay is always fixed?
Delay is always 2 in this code but if you call the nethod with parameter 'timeTo$$anonymous$$ove' as 1, this will break.
Answer by SrGonzalez · Apr 19, 2017 at 04:48 PM
you must use better in the coroutine that:
IEnumerator Counter()
{
yield return new WaitForSeconds(2); //Anything after this line is going to be called
//here goes your code //after 2 seconds
}
Your answer
Follow this Question
Related Questions
MoveTowards and Lerp not working 1 Answer
Object moving chaotically using lerp and repeating. 1 Answer
Transform search function only sporadically works?! 1 Answer
Nothing after coroutine gets executed 1 Answer
Problem with Mathf.Lerp 1 Answer