#coroutine

1 messages · Page 1 of 1 (latest)

leaden nacelle
#

made a thread

#

so here's the code again

#
IEnumerator RunForTime(float duration) {
  float endTime = Time.time + duration;
  while (Time.time < endTime) {
    transform.position += Vector3.up * Time.deltaTime;
  }
}
#

We're missing the yield return null; line here.

#

That is very important.

fleet maple
#

oh right

leaden nacelle
#

Coroutines aren't really "special". I used to think they were actually running in parallel or something

#

They don't. They run exactly like any other method.

fleet maple
#

because it doesn't return a waitforseconds

leaden nacelle
#

The only exception is that you can yield to pause the method

#

and then Unity can resume it later

leaden nacelle
#

Time.time only increases when Unity gets to the next frame

fleet maple
#

what does "yield" do?

leaden nacelle
#

yield is a C# keyword. It's used in a method that returns IEnumerator.

#

C# does a little bit of magic when you write a method that returns IEnumerator

#

you can't actually "pause" a method like this in C#

#

that's not a thing

#

but what you can do is make a little class that remembers all of the local variables

#

and remembers where you were

#

that's what the IEnumerator winds up being!

fleet maple
#

i have a question

leaden nacelle
#

An IEnumerator is a thing that can give you values when you ask for them

#
foreach (Transform child in transform) {
  Debug.Log("My child is named: " + child.name);
}
#

you use enumerators whenever you use foreach

fleet maple
#

can i for example use something like this:
startingTime=time.Time
coroutine...

#

endingTime =time.Time

leaden nacelle
#

and pauses until you ask for another value

#
public IEnumerator<int> GiveMeInts() {
  yield return 1;
  yield return 2;
  yield return 3;
}

foreach (var num in GiveMeInts()) {
  Debug.Log(num):
}
fleet maple
#

and in the coroutine use something like
while (endingTime-startingTime < 5f)

leaden nacelle
#

This would log

leaden nacelle
leaden nacelle
fleet maple
leaden nacelle
#

while (Time.time - startingTime)

leaden nacelle
#

it's not too important

leaden nacelle
#

so, vitally

#

if you never yield return inside that while loop

#

the enumerator never finishes

#

Time.time only goes up when you get to the next frame

#

If you yield return null; inside a coroutine, Unity will resume your method on the next frame

#

you can also do stuff like yield return new WaitForSeconds(1f); to ask Unity to resume your method in one second

fleet maple
#

void FixedUpdate()
{
if (!isInCoRoutine)
{

        StartCoroutine(MoveForSecond());
    }    
}
IEnumerator MoveForSecond()
{
    isInCoRoutine = true;
    rb.velocity = new Vector3(xSpeed, 0, 0);
    yield return new WaitForSeconds(timeCoRoutine);
    rb.velocity = Vector3.zero;
    RotateEnemy();
    isInCoRoutine =false;
}

so, to fix this, i have to use time.Time and a variable for the starting point?

leaden nacelle
#

There's a very important difference between your code and mine

leaden nacelle
leaden nacelle
#

Once you set that velocity, Unity's physics system will move the rigidbody every physics update.

fleet maple
#

i can send you a video

leaden nacelle
#

What do you want it to do instead?

fleet maple
#

make it move for 5 seconds, then flip and move in the opposite direction

leaden nacelle
#

is the problem that the rigidbody is slowing down and stopping?

fleet maple
#

so that it has a constant loop of movement

leaden nacelle
#

Your code should make it move for timeCoRoutine seconds, rotate, and then immediately start moving again

fleet maple
#

wait i'll send you a video

#

actually, it doesn't even flip

leaden nacelle
#

okay, your problem is that the rigidbody is slowing down

leaden nacelle
#

it has friction with the ground

#

so it stops

fleet maple
#

the friciton?

#

friction

#

so i have to create a new physics material

leaden nacelle
fleet maple
#

can't i make the friction 0?

leaden nacelle
#

Sure, that would work

fleet maple
#

nothing changed btw

#

so i'll have to set it's velocity with the script

leaden nacelle
#

it also may have drag

fleet maple
#

void FixedUpdate()
{
if (!isInCoRoutine)
{

        StartCoroutine(MoveForSecond());
    }    
}
IEnumerator MoveForSecond()
{
    while (Time.time < startingTime + timeCoRoutine)
    {
        startingTime = Time.time
        isInCoRoutine = true;
        rb.velocity = Vector3.zero;
        RotateEnemy();
        isInCoRoutine = false;
        yield return null;

    }
}

can this work?

#

i forgot to set startingTime

#

does it now?

#

no wait, stuff that should be outside the while loop are inside it

leaden nacelle
#

yes, the loop should only contain the thing that makes the enemy move

#

you're also setting the enemy velocity to zero right now

fleet maple
#

void FixedUpdate()
{
if (!isInCoRoutine)
{

        StartCoroutine(MoveForSecond());
    }    
}
IEnumerator MoveForSecond()
{
    isInCoRoutine = true;
    startingTime = Time.time;
    while (Time.time < startingTime + timeCoRoutine)
    {
        rb.velocity = new Vector3(xSpeed, 0, 0);
    }
    RotateEnemy();
    isInCoRoutine = false;
    yield return null;
}
void RotateEnemy()
{
    transform.Rotate(0,180,0);
}

}

#

fixed it (i hope so)

leaden nacelle
#

Looks reasonable. You're just missing the thing to set the velocity to 0 at the end

#

but if you immediately set the velocity again, I guess that doesn't matter

#

also, this wouldn't make the enemy move back and forth

fleet maple
leaden nacelle
#

unless you're changing xSpeed somewhere else

fleet maple
leaden nacelle
#

the velocity of a rigidbody is in world space

fleet maple
#

people told me that by flipping it, it works

leaden nacelle
#

it doesn't matter what the rotation of the object is

#

the enemy will always move in the world +X direction

#

you could use rb.velocity = transform.forward to make the enemy move in whatever direction is "forward" for the enemy

fleet maple
#

ok

leaden nacelle
#

the blue arrow is forward here

#

You might want transform.right instead, if the red arrow is the way the enemy is supposed to move

fleet maple
#

they are moving in the x axis

#

the game is taking 4 minutes to load, is it normal?

#

it has always taken 10 seconds or so

leaden nacelle
#

if it gets stuck, you can kill the editor and reopen it

fleet maple
leaden nacelle
#

you can only lose scene data when you kill the editor

#

(if you haven't saved)

fleet maple
#

i didnt lose anything

#

it's still stuck

#

i wonder wether that's something related to the code

leaden nacelle
#

by "stuck" do you mean the editor is frozen after trying to play the game?

leaden nacelle
leaden nacelle
#

what's wrong here?

fleet maple
leaden nacelle
#

right, because you forgot something

fleet maple
#

yield return Time.time?

#

no

#

it has to return something

#

idk

#

😭

#

it's so complex

leaden nacelle
#

remember that yield return null tells Unity to resume the method one frame later

#

and you want to do this every frame

fleet maple
#

and how do i do it?

#

@leaden nacelle

leaden nacelle
#
        while (Time.time < startingTime + timeCoRoutine)
        {
            rb.velocity = new Vector3(xSpeed, 0, 0);
            yield return null;
        }

#

that's all you need

#

you set the velocity, then you pause the coroutine until the next frame

fleet maple
#

but you said that yield return null skips a frame

leaden nacelle
#

you do that over and over until Time.time is large enough

#

no, it does not skip a frame

#

if I'm in frame 6, the next frame is frame 7

fleet maple
#

and how does the coroutine stop?

#

after the while loop the isInCoRoutine is false, so it can start another coroutine, does that mean the coroutine is ended?

leaden nacelle
#

the coroutine ends when the method ends

leaden nacelle
fleet maple
#

ok

#

i have still the same issue as yesterday btw

#

the enemy gameObject doesn't flip

#

i tried with transform.Rotate, with rb.moverotate and rb.rotate but idk i don't get it

#

oh wait

#

no, nothing

#

to flip it i need to rotate it on the y axis, that's what i'm doing

leaden nacelle
#

you need to set the rotation of the rigidbody

#
rb.rotation *= Quaterion.AngleAxis(180, Vector3.up);
#

this will work

#

AngleAxis creates a rotation by that many degrees around a specific axis

#

Multiplying two quaternions combines their rotations

fleet maple
#

it cannot translate by unityengine.quaternions to system.numerics.quaternion

#

whatever that means

leaden nacelle
#

you have a bad using directive up top

#

there's a "Quaternion" class in System.Numerics

#

but this has nothing to do with Unity's Quaternion

#

get rid of using System.Numerics;

fleet maple
#

but there isn't a system.numerics there

leaden nacelle
#

show me your entire script

fleet maple
#

oh wait

#

yeah

#

done

#

so this should work?

#

maybe i got the issue

#

it flips, but it still goes on that direction

#

maybe during the coroutine, before flipping it, making its speed *= -1

leaden nacelle
#

if so, change that

fleet maple
#

rb.velocity = Vector3.right*xSpeed;

leaden nacelle
#

that's always going to go right

fleet maple
#

this is what i am using

leaden nacelle
#

Vector3.right is a constant. It's a vector pointing in the +X direction

fleet maple
#

oh and i have to rotate the object

leaden nacelle
#

transform.right varies. It's whatever direction is "right" for the transform

#

No, you don't need to do any more rotating. You just need to use the correct direction.

fleet maple
#

by using transform.forward it goes on the z

leaden nacelle
#

rb.velocity = transform.right * xSpeed; would make the enemy move in whatever direction is "right" for it

fleet maple
#

i'm using Vector3.forward

#

that's the problem

leaden nacelle
#

you mean transform.forward ?

fleet maple
#

nope

leaden nacelle
#

Vector3.forward will always move you into the screen

leaden nacelle
#

personally, I would rotate the enemy 90 degrees around the Y axis, so that its forward vector is pointing in the direction it wants to move

fleet maple
#

now i put there transform.forward

leaden nacelle
#

make sure you're on "local" mode when checking this

fleet maple
#

i am on local

leaden nacelle
#

okay, so select the enemy and rotate it so that its blue arrow points the way it should move

#

then set rb.velocity = transform.forward * speed;

fleet maple
#

rb.velocity = transform.forward*xSpeed;