- Home /
How to speed up a for loop?
I am rotating a camera in my scene but the camera is raotating too slowly. Any ideas on how to speed it up? Here is my code.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class cameraRotater : MonoBehaviour {
[SerializeField] GameObject theCam;
float tiltF;
float tiltS;
float spin;
float increment = 0.1f;
void Start() {
StartCoroutine(spinny());
}
IEnumerator spinny()
{
Debug.Log("It begins");
for (int i = 0; i < 10000; i++)
{
Debug.Log("It continues");
yield return new WaitForSeconds(0f);
if (tiltS > 60 || tiltS < -60)
{
tiltS = 0;
//tiltF = 0;
//spin = 0;
}
else
{
//tiltF += increment;
tiltS += increment;
//spin += increment;
}
//theCam.transform.eulerAngles = new Vector3(tiltF, spin, tiltS);
}
}
// Update is called once per frame
void Update () {
theCam.transform.eulerAngles = new Vector3(tiltF, spin, tiltS);
}
}
Answer by Xarbrough · Feb 16, 2018 at 04:47 AM
I'd like to propose a way to improve your code and fix your problem. I assume you want to rotate a transform by a constant speed. The greater than 60 and less then -60 checks also look like you may want to clamp the rotation between min and max values. Here is how this could look:
using UnityEngine;
/// <summary>
/// Rotates a transform at a constant speed within clamped limits in degrees offset from the original rotation.
/// </summary>
public class Rotator : MonoBehaviour
{
[Tooltip("Rotation speed in euler degress per second.")]
public Vector3 speed = new Vector3(0f, 0f, 1f);
[Tooltip("The minimum rotation per axis.")]
public Vector3 minValues = new Vector3(-60f, -60f, -60f);
[Tooltip("The minimum rotation per axis.")]
public Vector3 maxValues = new Vector3(+60f, +60f, +60f);
// A rotation that starts out at zero to track how far we have rotated.
private Vector3 localRotation;
// The offset between the localRotation variable and the actual transform rotation.
private Vector3 offset;
private void Start()
{
offset = transform.localEulerAngles;
}
private void Update ()
{
// Rotate the angles speed amount per second.
localRotation += speed * Time.deltaTime;
// Because localRotation started at zero, we can easily clamp min and max.
localRotation = Vector3.Max(Vector3.Min(localRotation, maxValues), minValues);
// But then also add the offset to respect the original transform rotation.
transform.localEulerAngles = localRotation + offset;
}
// The min-max clamp does this...
// if (localRotation.x < minValues.x)
// localRotation.x = minValues.x;
// if (localRotation.x > maxValue.x)
// localRotation.x = maxValue.x;
// etc...
}
First, we can assume that the component is put onto the object we want to rotate, instead of referencing it via an extra field. Instead I would make the settings public, so we can edit them in the inspector.
We can rotate an object by adding the speed increment every frame, but the rotation should be framerate independent, so we multiply by Time.deltaTime, which gives us a rotation unit of euler degrees per second.
If we want to clamp our values, we run into the problem that Unity euler angles will wrap around 0 - 360, meaning that instead of -60, the value will be 360 - 60 and so on. You can handle this with some if else checks, but I find it easier to simple cache the starting rotation, then move in our own custom rotation space which starts from zero and later convert back to Unity rotation by applying the original offset.
I didn't understand why you user a coroutine in your posted code. Was there a specific reason like that you wanted to start the spinning at a later point in time and not right when the scene loads? If not, you don't need it. Even if you want to start the spinning later it makes more sense to simply disable the component in the inspector and enable it from another script at runtime.
Lastly I should note that this approach might fail in specific configurations because of gimbal lock (you would see if the object suddenly flips and rotates weirdly at some specific point). Solving such a problem requires the use of Quaternions as Unity internally already uses. It shouldn't be an issue most of the time, but if it is, you can ask or search for more infos.
@Xarbrough thank you so much, I greatly appreciate the guidance that you have provided me with.
Answer by Meguia · Feb 16, 2018 at 05:03 AM
Hi @thunderbuns
Instead of incrementing the value of increment variable, you should multiply a rotation speed value by the delta time since the last frame.
This will make your movement frame rate independent. It means that if you are playing in a fast machine or a slow one, the camera rotation should be the same.
tiltS += increment * Time.deltaTime
Here is an example of moving a GameObject using Time.deltaTime
, note that the basic idea is the same.
Also, doing a for
loop inside a coroutine for 10000 times means that in less than 3 hours your camera won't be moving anymore.
I don't know if you want to do it anyway, but I think you should change it for a while(true)
loop (it will finish when the coroutine stops).
@$$anonymous$$eguia thanks you for assistance it has aided me greatly.
@$$anonymous$$derbuns you are welcome!
Good luck!
Your answer
Follow this Question
Related Questions
Javascript for loops and Arrays. 2 Answers
speed particles,Speed particles and camshake 0 Answers
Camera movement help 1 Answer