Need Help! Can't get a timed loop to work

Hey guys! So I am about a week into game development and this is my first time reaching out for help. You guys have been amazing at having such an intensive KB online I am already grateful for all the assistance.

Now I doubt I am going about this the best way, but at this point, I am determined to figure out what I am doing wrong.

I have a chest that I am trying to open using a Clamp lock. And I can get it to click once in the loop but not multiple times… if I do get it to click multiple times, it jumps to the end and you don’t see the opening of the chest.

When I attempt to put a time delay into the loop logic it makes unity crash. I’ve tried multiple methods of getting this right and keep on getting stuck. This was my most promising code for the loop method…

void tickloop()
{
int tcount = 0;
bool copen = false;
for (int i = 24; i < ticks; i–)
{
tcount ++;
if (tcount == 24 && copen == false)
{
tcount = 0;
x–;

if (x <0)
{
copen = true;
}
}
if (tcount == 24 && copen == true)
{
isChestOpen = true;
}
}

I will post the rest of my code under here, just note the commented items are codes that I may find useful later (mainly because I haven’t gotten it to work yet.

using System;
using UnityEngine;

public class ChestRotationOpen : MonoBehaviour
{

 
         public int ticks = 24;
         bool loopt = true;

          public Transform ChestTilt;
       //  public Transform CFollow;
         public float openspeed = 2f;

         // set min and max rotations
         public float CMinLimit = 0f;
         public float CMaxLimit = 73f;

         // setup tracking veriables for angualr differences
         private float x = 0.0f;
         private float y = 200.0f;
         private float z = 0.0f;

         bool isChestOpen = false;


         // Start is called before the first frame update
         void Start()
         {
             //setup euler angles intial reading
             x = transform.eulerAngles.x;
             y = transform.eulerAngles.y;
             z = transform.eulerAngles.z;

         }

    // Update is called once per frame



    void tickloop()
    {
        int tcount = 0;
        bool copen = false;
        for (int i = 24; i < ticks; i--)
        {
             tcount ++;
            if (tcount == 24 && copen == false)
            {
                tcount = 0;
                x--;

                if (x <0)
                {
                    copen = true;
                }
            }
            if (tcount == 24 && copen == true)
            {
                isChestOpen = true;
            }
        }


     //   for (int i = 0; i < ticks; i++)
            /*    for (x = 73; x < ticks; x--)

                {
                    if (x < ticks)
                {
                    ticks--;

                }
                else
                {
                    isChestOpen = true;
                }
            } */
    }

      void Update()
      {

               /*   // DELAY LOOP
                if (ticks >= 0)
                { }
                else { ticks = 24; loopt = true; }
               */ //DELAY LOOP

       x = ClampAngle(x, CMinLimit, CMaxLimit);
       Quaternion newRot = Quaternion.Euler(x, y, z);
       transform.rotation = newRot;

       ChestTilt.eulerAngles = new Vector3(ChestTilt.eulerAngles.x, ChestTilt.eulerAngles.y, ChestTilt.eulerAngles.z);

      }
      float ClampAngle(float angle, float min, float max)
      {
                if (angle < -360)
                    angle += 360;
                if (angle > 360)
                    angle -= 360;

                return Mathf.Clamp(angle, min, max);
      }
     
         void OnMouseDown()
        {
        if (isChestOpen == false)
        {

                    tickloop();
         
            /*     int n = 73;

            do
            {
                ticks--;
                if (loopt == true) { loopt = false; x--; n--; Debug.Log(n); }
            }
            while (n > 0);


            isChestOpen = true;*/
        }
        else if (isChestOpen != false)
        {

            Debug.Log("Chest is already open! ... Silly");

        }
     
    }

}

I really appreciate the help! xoxo GignerNinja

Code is difficult to follow. Your x variable is undeclared in first code block and I gave up trying to follow the code after that because its unformatted and incomplete.

Use the code insert to format your code when posting and ensure what you post actually compiles without error. Perhaps if you can upload your project as a zip and define the problem, it’ll be easier for us to debug for you

Thank you for the advice, let me know if this is more understandable. I really appreciate the help!

using System;
using System;
using UnityEngine;

public class ChestRotationOpen : MonoBehaviour
{

    /// int ticks will be used to track time > as the chest is opening
 
         public int ticks = 24;
    // loopt looptime is a variable I am using to postpone the chest opening (loop will only progress while loopt == true) + (ticks hitting 0 will reset loopt to true and set the value of ticks back to 24)
         bool loopt = true;

    /// ChestTilt is the actual chest lid being rotated from 0 - 73 degrees
          public Transform ChestTilt;
     
    //  openspeed is the speed which the chest opens at > based on the timer I am not sure how useful this value will be
         public float openspeed = 2f;


    // Cmin & CMax are part of the clamps to stop motion of the chest lid opening to far or closing to much
         // set min and max rotations
         public float CMinLimit = 0f;
         public float CMaxLimit = 73f;

         // setup tracking veriables for angualr differences
         private float x = 0.0f;
         private float y = 200.0f;
         private float z = 0.0f;

         bool isChestOpen = false;


         // Start is called before the first frame update
         void Start()
         {
             //setup euler angles intial reading
             // Angle of Rotation will be happening on "x"
             x = transform.eulerAngles.x;
             y = transform.eulerAngles.y;
             z = transform.eulerAngles.z;

         }



   
    // this is the loop method which will be referenced onClick later in script
    void tickloop()
    {
        // tcount is the number of times the object should rotate before the chest is open
        int tcount = 0;
        // the loop will continue until the chest is declared open (it will not need to close again post-opening)
        bool copen = false;
        // I am using ticks as the reference for each progression of this loop (ticks = 24)
        for (int i = 0; i < ticks; i++)
        {
        // tcount will progress until it hits 24, then reset to 0, actions happen when tcount == 24
             tcount ++;
            // looking for tcount == 24 before progressing, if copen is still set to false then it will reset tcount and place a rotation on x (euler angle)
            if (tcount == 24 && copen == false)
            {
                tcount = 0;
                x--;

                // if euler angle x reaches closed position (@0) then it declares copen to true to pull of the final contingancy of this loop
                if (x <= 0)
                {
                    copen = true;
                    isChestOpen = true;
                }
            }
           
            // once true, it should return to the function onMouseDown() below.
            if (tcount == 24 && copen == true)
            {
                isChestOpen = true;
                return;
            }
        }

            /// old loop method ///

            //   for (int i = 0; i < ticks; i++)
            /*    for (x = 73; x < ticks; x--)
            {
                if (x < ticks)
            {
                ticks--;
            }
            else
            {
                isChestOpen = true;
            }
             } */
    }        /// old loop method ///


    void Update()
      {
        /// old loop method ///
        /*   // DELAY LOOP
         if (ticks >= 0)
         { }
         else { ticks = 24; loopt = true; }
        */ //DELAY LOOP
        /// old loop method ///

        // part of a script to set the maximum and minimum limits of the rotation (it works) /////////////////////////////////////////////
        x = ClampAngle(x, CMinLimit, CMaxLimit);                                                                                        //
       Quaternion newRot = Quaternion.Euler(x, y, z);                                                                                   //
       transform.rotation = newRot;                                                                                                     //
       ChestTilt.eulerAngles = new Vector3(ChestTilt.eulerAngles.x, ChestTilt.eulerAngles.y, ChestTilt.eulerAngles.z);                  //
                                                                                                                                        //
      }                                                                                                                                 //   
      float ClampAngle(float angle, float min, float max)                                                                               //  
      {                                                                                                                                 //
                if (angle < -360)                                                                                                       //
                    angle += 360;                                                                                                       //
                if (angle > 360)                                                                                                        //
                    angle -= 360;                                                                                                       //
                                                                                                                                        //
                return Mathf.Clamp(angle, min, max);                                                                                    //
    }                                                                                                                                   //
    // part of a script to set the maximum and minimum limits of the rotation (it works)//////////////////////////////////////////////////


    void OnMouseDown()
        {
        //call only when iscChestOpen == false
        if (isChestOpen == false)
        {
            // activate delayed release opening of chest (tickloop())
                    tickloop();


            // Old Loop I was testing out /////////////////////////////////////////
            /*     int n = 73;                                                   //
            do                                                                   //
            {                                                                    //
                ticks--;                                                         //
                if (loopt == true) { loopt = false; x--; n--; Debug.Log(n); }    //
            }                                                                    //
            while (n > 0);                                                       //
            isChestOpen = true;*/                                                //
            // Old Loop I was testing out /////////////////////////////////////////

        }

        //verifying the chest is open according to script on debug screeg
        else if (isChestOpen != false)
        {

            Debug.Log("Chest is already open! ... Silly");

        }
       
    }

}

I was able to resolve the issue! Turns out custom methods don’t track time as the update method does. If anyone is struggling with the same issue here is my final code:

using System;
using UnityEngine;

public class ChestRotationOpen : MonoBehaviour
{

    /// int ticks will be used to track time > as the chest is opening

    public float ticks = 73f;
    // loopt looptime is a variable I am using to postpone the chest opening (loop will only progress while loopt == true) + (ticks hitting 0 will reset loopt to true and set the value of ticks back to 24)

    /// ChestTilt is the actual chest lid being rotated from 0 - 73 degrees
    public Transform ChestTilt;

    //  openspeed is the speed which the chest opens at > based on the timer I am not sure how useful this value will be
    public float openspeed = 1f;


    // Cmin & CMax are part of the clamps to stop motion of the chest lid opening to far or closing to much
    // set min and max rotations
    public float CMinLimit = 0f;
    public float CMaxLimit = 73f;

    // setup tracking veriables for angualr differences
    private float x = 0.0f;
    private float y = 165f;
    private float z = 0.0f;

    bool isChestOpen = false;

    float tcount = 0f;
    float timetick = 0f;
    bool tactive = false;



    // Start is called before the first frame update
    void Start()
    {
       
        //setup euler angles intial reading
        // Angle of Rotation will be happening on "x"
        x = transform.eulerAngles.x;
        y = transform.eulerAngles.y;
        z = transform.eulerAngles.z;

    }




    // this is the loop method which will be referenced onClick later in script




    void Tickloop()
    {
        if (isChestOpen == false)
            tactive = true;
    }


  

    void Update()
        {
        // timer #########################
        if (tactive == true)            //
        {                               //
            tcount++;                   //
            if (tcount == openspeed)           //
            {                           //
                timetick++;             //
                tcount = 0;             //
           //   Debug.Log(timetick);      //
            }                           //
        }                               //
        //timer ##########################


        // Chest opening system
        float temp = 0f;
        float tdif;
        if (tactive == true)
        {
                if (temp != timetick)
                {
                    temp = timetick;
                    tdif = (73-temp*3);
                    Debug.Log(temp);
                    x = tdif;
                }    
            }
        if (temp >= ticks/3)
        {
            tactive = false;
            isChestOpen = true;
        }

        // Chest opening system



        // part of a script to set the maximum and minimum limits of the rotation (it works) /////////////////////////////////////////////
        x = ClampAngle(x, CMinLimit, CMaxLimit);                                                                                        //
            Quaternion newRot = Quaternion.Euler(x, y, z);                                                                                   //
            transform.rotation = newRot;                                                                                                     //
            ChestTilt.eulerAngles = new Vector3(x, ChestTilt.eulerAngles.y, ChestTilt.eulerAngles.z);                  //
                                                                                                                                             //
        }                                                                                                                                 //  
        float ClampAngle(float angle, float min, float max)                                                                               // 
        {                                                                                                                                 //
            if (angle < -360)                                                                                                       //
                angle += 360;                                                                                                       //
            if (angle > 360)                                                                                                        //
                angle -= 360;                                                                                                       //
                                                                                                                                    //
            return Mathf.Clamp(angle, min, max);                                                                                    //
        }                                                                                                                                   //
                                                                                                                                            // part of a script to set the maximum and minimum limits of the rotation (it works)//////////////////////////////////////////////////


    void OnMouseDown()
        {
   
            //call only when iscChestOpen == false
            if (isChestOpen == false)
            {
            Tickloop();
     Debug.Log("Opening Chest");
          
         
            }

            //verifying the chest is open according to script on debug screeg
            else if (isChestOpen != false)
            {

                Debug.Log("Chest is already open! ... Silly");

            }

        }

    }

More generally, non-Unity methods don’t get called unless you call them.

Here is some really spiffy timing diagram help:

https://docs.unity3d.com/Manual/ExecutionOrder.html

1 Like

You’re understanding it only partially. Custom functions can be aware of time and use timers when implemented correctly. Update only “tracks time” in that it runs once per frame, and that’s typically a bad way to make a timer as FPS will fluctuate. Don’t use a for loop to make a timer, it will run everything as fast as possible (which is what all code does unless you slow it down on purpose afaik). Use coroutines, InvokeRepeating, or Time.time to manage delays, repeats, timer ticks, etc.