running and changing variables in a function from update()

Hi
I have this script which I am using in a basic VR game. I use the reticlepointer to choose; if the person looks at an item for x seconds it kicks in the function. So this is the function called when i use the pointer enter event

    public void MouseHoverLook()
    {
        mousehover = true;   
    }

the update function then waits to see if the person looks at the object long enough to kick in the given script

void Update()
    {
        if (mousehover)
        {
                Counter += Time.deltaTime;
      
            if (Counter >= DelayStart)
            {
                     LetsGo();
            }
        }
    }

this works fine if I just want to start a process, but I need to use this to start/stop a buggy. So when the person looks at the buggy for x seconds it will start. They then need to be free to look around the scene, beyond the box collider on the buggy. When they look at the buggy again this should then stop it.

I have tried setting a boolean for whether the buggy is moving or not:

            if (move)
            {
                if (Counter >= DelayStart)
                {
                    LetsGo();
                }
            }
            else if (!move)
            {
                if (Counter >= DelayStop)
                {
                    LetsGo();
                }

            }

and also tried setting it up with coroutines but that didn’t work either. If I reset the counter either in mousehoverlook() or in update() it just stops the buggy from moving immediately.

The moving function is:

 private void LetsGo()
  //  IEnumerator LetsGo()
    {
      //  yield return null;
            speedset = speed;
        float distance = Vector3.Distance(PathToFollow.path_objs[CurrentWayPointID].position, transform.position)-1;
        transform.position = Vector3.MoveTowards(transform.position, PathToFollow.path_objs[CurrentWayPointID].position, Time.deltaTime * speedset);
    
        var rotation = Quaternion.LookRotation(PathToFollow.path_objs[CurrentWayPointID].position - transform.position);
        transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * rotationSpeed);

        if (distance <= reachDistance)
        {
            CurrentWayPointID++;
        }

        if (CurrentWayPointID > +PathToFollow.path_objs.Count - 1)
        {
if (loop)
            {
                CurrentWayPointID = 0;
            }
            else
            {
                mousehover = false;
            }
        }
     

    }
}

This doesn’t feel very complex but I cannot work out how to do this; any help gratefully received.

thanks v much

I think the issue is in your second script there, you’re only counting down if it’s moving, and calling the LetsGo() method if it isn’t. You should have it something like this,

                if (Counter >= DelayStart)
                {
                    counter += Time.deltaTime
                }
         
            else  if (Counter >= DelayStop && !move)
                {
                    move = true;
                    LetsGo();
                }

Sorry, another thing I also noticed, you should be handling your movement in a fixed update method. Then just set the speed to 0 until the LetsGo() method is called

thanks so much for trying to understand what wasn’t the clearest post! I think the problem I have is that if i reset the counter, the LetsGo() stops running. I think I need to reset the counter so that I can then look for the request to stop the buggy. If I don’t reset it the buggy continues to move. If I reset the counter in a mouseExit() or within update, the buggy stops moving as soon as I move the reticle pointer

This is the full script with your suggested changes, but it doesn’t work!

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gazetomovestartstop : MonoBehaviour
{
    public bool loop = false;
    public bool mousehover = false;
    private bool move = false;
    public float Counter = 0;
    public EditorPathScript PathToFollow;
    public int CurrentWayPointID = 0;
    private float speedset=0;
    public float speed;
    private float reachDistance = 1.0f;
    public float rotationSpeed = 5.0f;
    //public string pathName;

   //start buggy after x seconds
    public float DelayStart;
    //stop buggy after x seconds
    public float DelayStop;
     Vector3 last_position;
    Vector3 current_position;

    void FixedUpdate()
    {
        if (mousehover)
        {
            Debug.Log("speed is" + speedset + " because I am moving:" + move);
          
            Counter += Time.deltaTime;

            if (Counter >= DelayStart && !move)
            {
                speedset = speed;
                //StartCoroutine(LetsGo());
                LetsGo();
            }
          
            if (Counter >= DelayStop && move)
                {
                speedset = 0;
                LetsGo();
                }
        }

    }

    // mouse Enter event
    public void MouseHoverLook()
    {
            mousehover = true;  
    }

 

   private void LetsGo()
   // IEnumerator LetsGo()
    {
      //  yield return null;
          Debug.Log("lets go function has been called");
        Debug.Log("am i moving " + move);

        Debug.Log("speed set to: " + speedset);
    
        float distance = Vector3.Distance(PathToFollow.path_objs[CurrentWayPointID].position, transform.position)-1;
        transform.position = Vector3.MoveTowards(transform.position, PathToFollow.path_objs[CurrentWayPointID].position, Time.deltaTime * speedset);
   
        var rotation = Quaternion.LookRotation(PathToFollow.path_objs[CurrentWayPointID].position - transform.position);
        transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * rotationSpeed);

        if (distance <= reachDistance)
        {
           // Debug.Log("in  reach distaance");
            CurrentWayPointID++;
        }

        if (CurrentWayPointID > +PathToFollow.path_objs.Count - 1)
        {
            //Debug.Log("in  CurrentWayPointID");
            if (loop)
            {
                CurrentWayPointID = 0;
            }
            else
            {
                mousehover = false;
            }
        }

        if (!move)
        {
            move = true;
        }
        else
        {
            move = false;
        }
    }
}

So the issue is the buggy keeps moving even when you stop looking at it, but you only want it to move while looking at it? Just making sure I understand.

Edit: also, how are you calling the mouse hover? You can use OnMouseEnter() and OnMouseExit(), they are built in functions in Monobehavior that are called whenever your mouse hovers over an object.

Okay, through testing it out… I don’t wanna put you on blast, but there’s several issues here haha. I’ll list them off.

The first one is my bad, it should be if(counter <= delayStart), not >=.

Also, just nitpicking, but variables should be lowercase first letter, every second word capital, and methods and scripts should be capital every letter.

        if (!move)
        {
            move = true;
        }
        else
        {
            move = false;
        }

Why are you toggling this in your LetsGo() method?

Like I mentioned before, you can do something like this for your mouse hover

     void OnMouseEnter()
    {
        mousehover = true;
    }
    private void OnMouseExit()
    {
        mousehover = false;
        counter = 0;
        speedSet = 0;
        move = false;
    }

Again, nitpicking, but it’s strange that you’re multiplying your movement by speedset and not speed, generally variables with “set” in them are never altered, and the speed would be set to speedset lol

Well, I have it working, I can’t really test out your waypoints there, I hope this is something like what you wanted to accomplish.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Gazetomovestartstop : MonoBehaviour
{
    public bool loop = false;
    public bool mouseHover = false;
    private bool move = false;
    public float counter = 0;
    public Transform[] pathToFollow;
    public int currentWayPointID = 0;
    private float speedSet = 0;
    public float speed;
    private float reachDistance = 1.0f;
    public float rotationSpeed = 5.0f;
    //public string pathName;
    //start buggy after x seconds
    public float DelayStart;
    //stop buggy after x seconds
    public float DelayStop;
    void FixedUpdate()
    {
        if (mouseHover)
        {
            Debug.Log("speed is" + speedSet + " because I am moving:" + move);
            counter += Time.deltaTime;
            if (counter <= DelayStart)
            {
                counter += Time.deltaTime;
            }
            else if (counter >= DelayStop && !move)
            {
                move = true;
                speedSet = speed;
            }
        }
        if(move == true)
        {
            LetsGo();
        }
    }
    // mouse Enter event
     void OnMouseEnter()
    {
        mouseHover = true;
    }
    private void OnMouseExit()
    {
        mouseHover = false;
        counter = 0;
        move = false;
    }
    void LetsGo()
    {
            float distance = Vector3.Distance(pathToFollow[currentWayPointID].position, transform.position) - 1;
            transform.position = Vector3.MoveTowards(transform.position, pathToFollow[0].position, Time.deltaTime * speedSet);
            var rotation = Quaternion.LookRotation(pathToFollow[currentWayPointID].position - transform.position);
            transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * rotationSpeed);
            if (distance <= reachDistance)
            {
                Debug.Log("in  reach distaance");
                currentWayPointID++;
                if (currentWayPointID > pathToFollow.Length && loop)
                {
                    currentWayPointID = 0;
                }
         else{
                move = false;
                }
            }
       
    }
}

I tested it out and this works, it moves while your mouse is over it, and stops when it isn’t. I hope this is what you wanted. If not, let me know, I’ll see if I can help you out. I know debugging can be hell at first haha.

thanks but one of your assumptions was wrong - my fault and sorry to have led you down a blind alley
The flow is:
buggy is stationary
look at buggy for 3 seconds to start it moving
it should then continue to move, when i look away (they will want to look around the scene and not keep looking at the vehicle)
If they then look back at the buggy for 3 seconds, it will stop i.e. speedset = 0.
they can then look around again, maybe at a poster with some information on it
if they look at the buggy again it will start moving again
and so it continues.

the reason I toggle move is so I knw whether to start or stop the buggy - i have been moving this all over the place in the hope i might get it right
I am checking if counter >= delay so i can change how long the person has to look at the vehicle before it starts/stops

thanks for the coding convention tips; i am really bad with them, but since I have no senior developer to haul me over the coals not that worried about them!

Haha, I know, naming convention doesn’t really matter when you’re getting started, but you’ll see why it’s useful down the road… I’m sure I said that exact thing to someone on this forum a year ago lol

Ah, sorry, I’m not very great at fixing other peoples code, this might not be the best method, but I think this achieves what you’re looking for. So, if you hover your mouse over it, it will turn it on, I created a new bool, probably unnecessarily :stuck_out_tongue: but, so it will check if the toggler is false, and the toggler is set to false when you move your mouse off of it, and set to true when the timer is up.

A quick way to toggle is to set move to !move, which basically just quickly reverses it :slight_smile:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Gazetomovestartstop : MonoBehaviour
{
    public bool loop = false;
    public bool mouseHover = false;
    private bool move = false, toggler = false;
    public float counter = 0;
    public Transform[] pathToFollow;
    public int currentWayPointID = 0;
    private float speedSet = 0;
    public float speed;
    private float reachDistance = 1.0f;
    public float rotationSpeed = 5.0f;
    //public string pathName;
    //start buggy after x seconds
    public float Delay;
    //stop buggy after x seconds
    public float DelayStop;
    void FixedUpdate()
    {
        if (mouseHover)
        {
            Debug.Log("speed is" + speedSet + " because I am moving:" + move);
            counter += Time.deltaTime;
            if (counter < Delay)
            {
                counter += Time.deltaTime;
            }
            else if (counter >= Delay && !toggler)
            {
                toggler = true;
                move = !move;
                if (move)
                {
                    speedSet = speed;
                }
                else
                {
                    speedSet = 0;
                }
            }
        }
        if (speedSet > 0)
        {
            LetsGo();
        }
    }
    // mouse Enter event
     void OnMouseEnter()
    {
        mouseHover = true;
    }
    private void OnMouseExit()
    {
        mouseHover = false;
        toggler = false;
        counter = 0;
    }
    void LetsGo()
    {
            float distance = Vector3.Distance(pathToFollow[currentWayPointID].position, transform.position);
            transform.position = Vector3.MoveTowards(transform.position, pathToFollow[currentWayPointID].position, Time.deltaTime * speedSet);
            var rotation = Quaternion.LookRotation(pathToFollow[currentWayPointID].position - transform.position);
            transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * rotationSpeed);
        if (distance <= reachDistance)
        {
            Debug.Log("in reach distaance");
            currentWayPointID++;
            if (currentWayPointID >= pathToFollow.Length && loop)
            {
                currentWayPointID = 0;
            }
            else if(!loop)
            {
                speedSet = 0;
            }
        }
      
    }
}

Hope this fixes your issue. You can just drag your waypoints onto this script instead of using that separate script, unless you have some sort of waypoint generator.

thanks - unfortunately I can’t get it to work :frowning:
do I need to reference the OnMouseEnter and OnMouseExit on the object with the box collider in Editor? These aren’t exposed so I am guessing I don’t

But when I try to run the scene, nothing happens when I move the reticle pointer over the jeep.

i am wondering if line 35 should be move = true;
I was using this to identify when the vehicle is moving so I know it then needs to stop.

I also can’t see where the script then stops the buggy by setting speedset to 0 on line 65 since on line 46 we only call LesGo() if speed is more than 0

move = !move just basically toggles the bool. If it’s true it will set it to false, if it’s false it will set it to true. Does your jeep have a collider on it?

Also, it stops it at line 42.

understood
yes it has a collider - but the functions aren’t exposed. I assume this isn’t needed as they are in built functions?
IndexOutOfRangeException: Index was outside the bounds of the array.
Gazetomovestartstop.LetsGo () (at Assets/MyStuff/Scripts/Gazetomovestartstop.cs:64)
Gazetomovestartstop.FixedUpdate () (at Assets/MyStuff/Scripts/Gazetomovestartstop.cs:48)

Here are some notes on IndexOutOfRangeException and ArgumentOutOfRangeException:

1 Like

OnMouseEnter and OnMouseExit are for colliders, so yes, the script needs to be on the object with the collider in question.

Index out of range = look for your array:
pathToFollow[currentWayPointID]

currentWayPointID++;
if (currentWayPointID >= pathToFollow.Length && loop)

You’re using two conditions there, so somehow it’s not evaluating to true because the loop is false. Therefore your currentWayPointID isn’t getting set back to 0 once it goes over the limit.

but this is happening at the outset - not at the end… so not sure how that works

yes it is on the same object so that isn’t the problem

working!! thanks so much - I flipped the LetsGo function to an older version. Made the mouseOver functions public and attached to the object. And now it works
thanks so much for your help @seejayjames . That toggler appears to have been the special weapon. Haven’t wrapped my head around exactly why it has made such a difference but will get there :slight_smile:

2 Likes