I’m trying to write a script that will move my object around randomly, and if it hits a wall it turns around and keeps going, but the coroutine I’m using fails to move (and I guess to execute), anyone know what I’m getting wrong?
using UnityEngine;
using System.Collections;
public class NewRandomMovement : MonoBehaviour
{
float rotationY;
private float speed = 3;
void Start()
{
StartCoroutine(Rotate());
}
void Update()
{
transform.Translate(Vector3.forward * Time.deltaTime * speed); //MOVE FORWARD
var randomint = Random.Range(0, 360);
var rotationY = randomint; //RANDOM Y ROTATION
var fwd = transform.TransformDirection(Vector3.forward); //DIRECTION
RaycastHit hit;
if (Physics.Raycast(transform.position, fwd, out hit, 5)) //IF HITS THE WALL
{
if (hit.collider.tag == "Walls")
{
var target = Quaternion.Euler(0, 210, 0); //ROTATE 210 DEGREES
transform.rotation = Quaternion.Slerp(transform.rotation, target, Time.deltaTime);
}
}
}
IEnumerator Rotate()
{
while (true) //INFINITE ROUTINE
{
var randomintRotate = Random.Range(0, 360);
var rotationY = randomintRotate;
var targetRotate = Quaternion.Euler(0, rotationY, 0);
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotate, Time.deltaTime); //ROTATION
yield return new WaitForSeconds(3);
}
}
}
You want it to be turning always, but each change in rotation takes 3 seconds to execute?
while(true) {
// get random
// save current rotation
for(float t = 0; t <= 3; t += Time.deltaTime) {
// do Slerp using saved starting rotation & the random target rotation, and the 3rd parameter is 't'
}
}
Hope that helps as an idea to get that part sort of working. In order to incorporate your changing rotation on the wall hit, that would require a few modifications, I’d imagine (for example, if you changed it in update, it would simply be overriden in the coroutine).
No the turn can be done in any time required by the turning itself, but it does have to be done every 3 seconds, like every 3 seconds it changes the rotation
The rotation on the wall is already set up, it works fine, my only problem was with the coroutine that does nothing, it’s like if it’s not written at all…
Well, okay… So, you want the rotation to be instantaneous? That’s not how you had written it, so that was part of the confusion. If you want it to change rotation every 3 seconds, then in your coroutine, you have to set the rotation to your ‘targetRotation’ variable from your first script, instead of trying to Slerp your way there.
Then your first script should work, I believe.
Your first attempt was asking it to change it’s rotation, based on an interpolation of Time.deltaTime (as a fraction of between rotation A and rotation B) and that’s it… never more.
Thanks for helping, I can be a little misdirecting because I’m not really good at coding, could you please lead me with the code? What should I change in the coroutine?
Again, thanks a lot 
Well, let’s see… Just pasting & modifying your original code.
IEnumerator Rotate()
{
WaitForSeconds wfs = new WaitForSeconds(3); // variable can be re-used in the loop.
while (true) //INFINITE ROUTINE
{
var randomintRotate = Random.Range(0, 360);
transform.rotation = Quaternion.Euler(0, randomintRotate, 0);
yield return wfs;
}
}
Excuse the crappy indentation - that’s what happens when you paste here and remove the bullets/ordering
(and are too lazy to fix it yourself lol)
The coroutine works fine now! Thanks 
But there’s an issue related to that, the rotation is “flashy”, I’ll upload a gif to explain better
There is https://giphy.com/gifs/WCVOPCIXhBngY
Ahah don’t worry about the indentation, it’s okay 
There’s 1 spot in the video, where after a rotation it semi-jerks to a new rotation almost right away… that looks a bit odd, but the rest more or less looks how you’d imagine (with the code), I think.
It’s not smooth, I mean setting a rotation directly (unless it’s a small increment) will always look like that. If you want to smooth it out, you have to do it over time; it’s up to you which is more desirable, I guess 
You could sort of mix together my earlier suggestion, plus the working coroutine but just reduce the time from 3 seconds to rotate down to like .5 seconds or something… see if you like that better?
Yep that weird rotation happens at the start of the “Play”, I think it’s the start of the coroutine that puts up the new direction right away, but I’m not sure
Anyway, I tried to reduce the seconds, but it just rotates like a crazy spider fidget spinner like that
About that smooth thing, yeah I’d like to have it real smooth, time is not a problem, my purpose is to create something that feels life like (this will be a aracnophobia treatment for psychologists, I’m currently a psy student trying to develop
)
Ah okay, well if it’s just once at the beginning that’s not a big deal (though you could have it yield at the start of the coroutine before entering the loop.
And about lowering the time, I didn’t mean to lower it for the loop, no no… I meant that you could add some logic to Slerp over time (see my earlier post) - and that time frame to rotate could be something like a 1/2 second… but the overall loop that chooses a new rotation, would still be 3 seconds apart. 
Oh I see it now, if I understood right, this should look like this, right?
IEnumerator Rotate()
{
WaitForSeconds wfs = new WaitForSeconds(3); // variable can be re-used in the loop.
while (true) //INFINITE ROUTINE
{
for (float t = 0; t <= 1.5; t += Time.deltaTime)
{
var randomintRotate = Random.Range(0, 360);
var target = Quaternion.Euler(0, randomintRotate, 0);
transform.rotation = Quaternion.Slerp(transform.rotation, target, t);
}
yield return wfs;
}
}
But I feel like I’m wrong because it doesn’t work either 
That post didn’t include the initial wait at the start (just mentioning that as an observation , not required for the rest to work atm).
Okay, so you want to move the rotation and random outside of that inner loop
Quaternion rot = transform.rotation;
Quaternion targetRot = Quaternion.Euler(0, randomintRotate,0);
// then this..
for(float t = 0; t <= 1.5f; t += Time.deltaTime) {
transform.rotation = Quaternion.Slerp(rot, targetRot, t);
yield return null;
}
yield return wfs;
like that I think.
Slerp (and lerp) work with :
starting_point, ending_point, fraction (between starting and ending points)
Sometimes (sometimes often) you see people using the current (whatever) value in the first parameter. Sometimes this works, by coincidence and sometimes it works badly
But having the start saved is almost always better to use. And, the other change was getting the random part outside of that loop, obviously you don’t need to get a new one everytime in the loop.
And i made a mistake. editing my last post.
Edit: last post updated & fixed. Added ‘yield return null’ on the inner loop 
Uhm, it works in a “funny” way, it glitches but seems to do a slerp rotation in some way - https://giphy.com/gifs/PWL3h5C7yIvQc
I’m using it this way, the randomintRotate was put at the start (under public class NewRandomMovement : MonoBehaviour)
IEnumerator Rotate()
IEnumerator Rotate()
{
WaitForSeconds wfs = new WaitForSeconds(3); // variable can be re-used in the loop.
while (true) //INFINITE ROUTINE
{
Quaternion rot = transform.rotation;
Quaternion targetRot = Quaternion.Euler(0, randomint, 0);
// then this..
for (float t = 0; t <= 1.5f; t += Time.deltaTime)
{
transform.rotation = Quaternion.Slerp(rot, targetRot, t);
}
yield return wfs;
}
}
That is messed up lol
Oh man , i went to test your code in a project to see what’s wrong… and didn’t notice right away that you didn’t look at my update note for the last post!
I did, but I might be a little (lot) confused by now, if you want I can send you the project so you can test 
This is working pretty good for me. Of course you can adjust the value in the inner loop to a time you find fitting.
IEnumerator Rotate()
{
WaitForSeconds wfs = new WaitForSeconds(3); // variable can be re-used in the loop.
while (true) //INFINITE ROUTINE
{
int randomint = Random.Range(0, 360);
Quaternion rot = transform.rotation;
Quaternion targetRot = Quaternion.Euler(0, randomint, 0);
// then this..
for (float t = 0; t <= .5f; t += Time.deltaTime)
{
transform.rotation = Quaternion.Slerp(rot, targetRot, t);
yield return null;
}
yield return wfs;
}
}
1 Like
Please just try that update. It was the ‘yield return null’ that was needed inside. And you should always set the random number on each iteration of the (larger) loop, because otherwise it’s not very random 
1 Like
IT WORKS! It’s perfect! I can never thank you enough! 
How could I do that?