Using time in C# and switch

Hello everyone,

Admittedly, I am not very good at coding in C#, but I am learning. I am working on a 2D top down farming game and I am making a few small tests as I get my feet wet to get familiar with C# and Unity at the same time. I wrote a script that progresses the stage of a crop in sprite form every time the space bar is pressed, but I have a few questions.

  1. How do I tie this to a timer that starts once the crop is planted?

  2. How do I set the sprite to change after a certain amount of time has passed, as opposed to pressing the space bar?

I tried this via a switch, but I am not familiar enough with the concept to get it to work properly. I would like to use switch, so I can call back to earlier in the sequence for crops that can have multiple harvests.

Any help is greatly appreciated.

This is what I have at present

using UnityEngine;
using System.Collections;

public class GrowingTest : MonoBehaviour
{

   private int GrowStage = 0; //Sets variable called GrowStage
   public Sprite stage1; // Drag first crop sprite here
   public Sprite stage2; // Drag second crop sprite here
   public Sprite stage3; // Drag third crop sprite here

   private SpriteRenderer spriteRenderer;
   // Use this for initialization
   void Start ()
   {
   
     spriteRenderer = GetComponent<SpriteRenderer>(); //Calls Sprite Renderer Component from Unity via spriteRenderer alias

   }
   
   // Update is called once per frame
   void Update ()
   {
   if (Input.GetKeyDown("space"))  //When spacebar is pressed
       GrowStage = GrowStage + 1;  //Add 1 to GrowStage variable
       
   }
   void FixedUpdate()
      {
       if (GrowStage > 0) //If GrowStage variable is set to 1
           {
           spriteRenderer.sprite = stage1; //swap to sprite 1
           }
       if (GrowStage > 1)
           {
           spriteRenderer.sprite = stage2;
           }
       if (GrowStage > 2)
           {
           spriteRenderer.sprite = stage3;
           }
     }


}

Time.deltaTime is what you want to use to get the elapsed time since the last update, so you will do a += Time.deltaTime on a stored variable.

While we are making small corrections, your FixedUpdate could use a bit of change, by doing IF … ELSE IF … ELSE IF, and changing the conditions.

Right now, it will change the sprite multiple times in the same update, meaning that it uses a bit more resources than it should.
It doesn’t impact things too much for a small project, but it’s good to try and not fall into those small traps.

What you are building is a simple state machine. This is definitely something you want to read up on as a lot of simple game play components require an understanding of this technique.

The code below compiles and is tested within the limits that I care to test for.

The component can be attached to a plant and have the sprites populated through an array in the Inspector. It will also fire events whenever the plant changes state, which is very useful if you want other scripts to know when the plant starts and stops growing or has completely grown.

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

[RequireComponent(typeof(SpriteRenderer))]
public class GrowthMachine : MonoBehaviour
{
    // event to fire when the plant advances to the next growth stage
    public delegate void GrownToStageHandler(Object sender, int growthStage, int growthStages);
    public event GrownToStageHandler GrownToStage;

    // event to fire when the plant has completely grown
    public delegate void CompletelyGrownHandler(Object sender, int growthStage, int growthStages);
    public event CompletelyGrownHandler CompletelyGrown;

    // event to fire when the plant starts to growth
    public delegate void StartedGrowingHandler(Object sender, int growthStage, int growthStages);
    public event StartedGrowingHandler StartedGrowing;

    // event to fire when the plant stops to growth
    public delegate void StoppedGrowingHandler(Object sender, int growthStage, int growthStages);
    public event StoppedGrowingHandler StoppedGrowing;

    // Sprites for each growth stage
    [SerializeField]
    protected List<Sprite> m_stages;

    // how long to wait in seconds between each growth stage
    [SerializeField]
    [Range(0.01f, 100.0f)]
    protected float m_growthRate;

    // should I start growing the moment I am planted?
    [SerializeField]
    protected bool m_growImmediately;

    // what stage of growth is this plant at?
    private int m_growthStage;

    // cached sprite renderer component
    private SpriteRenderer m_spriteRenderer;

    // indicates whether the plant is growing or not
    private bool m_isGrowing;

    void Start()
    {
        m_spriteRenderer = GetComponent<SpriteRenderer>();
        // should I start growing the moment I am planted?
        if (m_growImmediately)
        {
            StartGrowing();
        }

    }

    // stops the plant from growing and terminates the coroutine that makes the plant grow
    public void StopGrowing()
    {
        // am I growing? if not, do nothing
        if (m_isGrowing == false)
        {
            return;
        }

        StopCoroutine(Growing());
        m_isGrowing = false;
        FireStoppedGrowing();
    }

    // forces the plant to start growing -- either automatically when it is planted or forcibly
    public void StartGrowing()
    {
        // am I already growing? if so, do nothing
        if (m_isGrowing)
        {
            return;
        }

        StartCoroutine(Growing());
    }

    // coroutine that will grow the plant through the various stages to the end
    IEnumerator Growing()
    {
        m_isGrowing = true;
        // verify we don't have a negative or zero growth rate
        System.Diagnostics.Debug.Assert(m_growthRate > 0.0f);
        // verify we have a list of sprites to handle the growth stages
        System.Diagnostics.Debug.Assert(m_stages != null);
        int stagesToGrow = m_stages.Count;
        // verify we have at least one sprite to handle the first growth stage
        System.Diagnostics.Debug.Assert(stagesToGrow > 0);
        FireStartedGrowing();
        ResetGrowth();
        for (int i = 1; i < stagesToGrow; i++)
        {
            yield return new WaitForSeconds(m_growthRate);
            AdvanceToNextGrowthStage();
        }

        m_isGrowing = false;
        FireStoppedGrowing();
    }

    // reset the growth of the plant to the very first stage. Assumes we have a first stage to reset to
    public void ResetGrowth()
    {
        GrowthStage = 0;
    }

    // advance the plant to the next stage of growth
    public void AdvanceToNextGrowthStage()
    {
        // have we grown to the last stage? if so, do nothing more
        if (GrowthStage >= (m_stages.Count - 1))
        {
            return;
        }

        // update the sprite to the next growth stage
        GrowthStage++;
        // let any other scripts paying attention to this plant know about the growth
        FireAdvancedToNextStage();
        // let any other scripts paying attention to this plant know about reaching the final stage growth
        if (GrowthStage == (m_stages.Count - 1))
        {
            FireCompletelyGrown();
        }

    }

    // reset the script values to sane defaults
    void Reset()
    {
        m_stages = new List<Sprite>();
        m_growthRate = 1.0f;
        m_growImmediately = true;
    }

    // inform any other scripts listening to this plant that i've started growing -- either forcibly or because I
    // started automatically.
    private void FireStartedGrowing()
    {
        if (StartedGrowing != null)
        {
            StartedGrowing(this, m_growthStage, m_stages.Count);
        }

    }

    // inform any other scripts listening to this plant that i've stopped growing -- either forcibly or because I
    // reached the end of my growth cycle).
    private void FireStoppedGrowing()
    {
        if (StoppedGrowing != null)
        {
            StoppedGrowing(this, m_growthStage, m_stages.Count);
        }

    }

    // inform any other scripts listening to this plant that i've completely grown up
    private void FireCompletelyGrown()
    {
        if (CompletelyGrown != null)
        {
            CompletelyGrown(this, (int)(m_growthStage), m_stages.Count);
        }
    }

    // inform any other scripts listening to this plant that i've grown to the next stage
    private void FireAdvancedToNextStage()
    {
        if (GrownToStage != null)
        {
            GrownToStage(this, (int)(m_growthStage), m_stages.Count);
        }

    }

    // permits the growth stage to be immediately set by other scripts
    public int GrowthStage
    {
        get
        {
            return m_growthStage;
        }
        set
        {
            System.Diagnostics.Debug.Assert(value >= 0);
            System.Diagnostics.Debug.Assert(value < m_stages.Count);
            m_growthStage = value;
            m_spriteRenderer.sprite = m_stages[value];
        }
    }

    // indicates whether the plant is currently growing or not
    public bool IsGrowing
    {
        get
        {
            return m_isGrowing;
        }
    }

}

I really appreciate the tips. I have reworked my own code based on this.

Goodness… I don’t even know what half that stuff means at present, but I certainly appreciate you providing the code. I will copy it and study it until I understand it completely and can configure it myself. I do have a long way to go, but I have a lot of videos from Youtube and various websites (Unity Live Training included) to get a handle on things.

I am very grateful for your help!

would this work in 3d?