0
\$\begingroup\$

The script:

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

public class ChangeScale : MonoBehaviour
{
    //Scaling change
    public GameObject objectToScale;
    public float duration = 1f;
    public Vector3 minSize;
    public Vector3 maxSize;

    private bool scaleUp = false;
    private Coroutine scaleCoroutine;

    //Colors change
    public Color startColor;
    public Color endColor;
    public float colorDuration; // duration in seconds

    //Lights change
    public DimLights dimlights;
    private Coroutine lightCoroutine;

    //Rotate
    public float rotationSpeed;
    public float rotationDuration;

    private void Start()
    {
        //startColor = GetComponent<Renderer>().material.color;
        endColor = Color.green;
        objectToScale.transform.localScale = minSize;
    }

    // Use this for initialization
    void Update()
    {
        //Scaling
        if (Input.GetKeyDown(KeyCode.F))
        {
            //Flip the scale direction when F key is pressed
            scaleUp = !scaleUp;

            //Stop old coroutine
            if (scaleCoroutine != null)
                StopCoroutine(scaleCoroutine);

            if (lightCoroutine != null)
                StopCoroutine(lightCoroutine);


            //Scale  up
            if (scaleUp)
            {
                //Start new coroutine and scale up within 5 seconds and return the coroutine reference
                scaleCoroutine = StartCoroutine(scaleOverTime(objectToScale, maxSize, duration));
                lightCoroutine = StartCoroutine(dimlights.dimLightOverTime(1, duration)); ;
            }

            //Scale Down
            else
            {
                //Start new coroutine and scale up within 5 seconds and return the coroutine reference
                scaleCoroutine = StartCoroutine(scaleOverTime(objectToScale, minSize, duration));
                lightCoroutine = StartCoroutine(dimlights.dimLightOverTime(0, duration)); ;
            }
        }

        //Change color
        if (Input.GetKeyDown(KeyCode.C))
        {
            StartCoroutine(ChangeColor());
        }

        //Rotate
        if (Input.GetKeyDown(KeyCode.R))
        {
            objectToScale.transform.Rotate(Vector3.up * rotationSpeed * Time.deltaTime);
            //StartCoroutine(RotateObject());
        }
    }

    IEnumerator scaleOverTime(GameObject targetObj, Vector3 toScale, float duration)
    {
        float counter = 0;

        //Get the current scale of the object to be scaled
        Vector3 startScaleSize = targetObj.transform.localScale;

        while (counter < duration)
        {
            counter += Time.deltaTime;
            targetObj.transform.localScale = Vector3.Lerp(startScaleSize, toScale, counter / duration);
            yield return null;
        }
    }

    IEnumerator ChangeColor()
    {
        float t = 0;

        while (t < colorDuration)
        {
            t += Time.deltaTime;
            GetComponent<Renderer>().material.color = Color.Lerp(startColor, endColor, t / colorDuration);
            yield return null;
        }
    }

    IEnumerator RotateObject()
    {
        float startTime = Time.time;

        while (Time.time - startTime < rotationDuration)
        {
            objectToScale.transform.Rotate(Vector3.up * rotationSpeed * Time.deltaTime);
            yield return null;
        }
    }
}

I tried using StartCoroutine but it didn't work. So for testing I tried to make that if I'm click/pressing on R once it will rotate the object nonstop but it's not working either it's not rotating it all.

Nothing i click on R and nothing happen. Tried to change the rotationSpeed from 1 to 10.

\$\endgroup\$
1
\$\begingroup\$

I would make the code like this:

public Update()
{
  if (Input.GetKey(KeyCode.R))
  {
      // If the player is holding the key, rotate the object.
      objectToScale.transform.Rotate( /* How much to rotate */ )
  } else if (Input.GetKeyUp(KeyCode.R)
  {
      // If the user has just let go of the key we want
      // to rotate for N seconds
      StartCoroutine(RotateObject());
  }
}

IEnumerator RotateObject()
{
    float startTime = Time.time

    while (Time.time - startTime < rotationDuration)
    {
        objectToScale.transform.Rotate( /* How much to rotate */ );
        yield return null;
    }
}

This should rotate the object while the player is holding the key, and after the player releases the key it should rotate for rotationDuration more seconds.

It's also important to note that this line Vector3.up * rotationSpeed * t / rotationDuration is kind of strange. If you want to rotate the object by rotationSpeed every second you should just do Vector3.up * rotationSpeed * Time.deltaTime.

\$\endgroup\$
1
\$\begingroup\$

You need parts from both of your attempts:

if (Input.GetKeyDown(KeyCode.R))

This will trigger exactly once until you let go of the key again. This is exactly the behavior you describe as wanting to have.

StartCoroutine(RotateObject());

This will do the rotation (via the coroutine function you already have set up).

When you use if (Input.GetKey(KeyCode.R)) and start a coroutine, you end up starting a dozen or more copies of the coroutine, all of which are trying to rotate your object and are conflicting with each other, leading to unpredictable behavior.

Then you have one other problem:

objectToScale.transform.Rotate(Vector3.up * rotationSpeed * t / rotationDuration);

This math is almost certainly not doing what you want it to. If you want a linear rotation speed, then you want Time.deltaTime here. Additionally the rotationDuration value isn't needed. Just use this:

objectToScale.transform.Rotate(Vector3.up * rotationSpeed * Time.deltaTime);
\$\endgroup\$
10
  • \$\begingroup\$ Neck to neck with these answers haha :D \$\endgroup\$ – Charanor Dec 25 '17 at 23:58
  • \$\begingroup\$ @Charanor Almost! I skimmed yours before finishing mine. I'm not sure that your code does what he wants, but I'm not actually sure what it is he wants. \$\endgroup\$ – Draco18s no longer trusts SE Dec 26 '17 at 0:06
  • \$\begingroup\$ After reading your answer I was also unsure... I got my interpretation from I want to make that when I press once on R the object will rotate for N seconds ... Then keep rotating it as long as I press on the key.. Perhaps they will tell us in comments if this is what they were trying to achieve. \$\endgroup\$ – Charanor Dec 26 '17 at 0:09
  • \$\begingroup\$ @Draco18s What I want is when I click on R once rotate the object at speed 1 for 10 seconds. I messed up the question. \$\endgroup\$ – jdoedoe doedoe Dec 26 '17 at 0:11
  • \$\begingroup\$ @Charanor I messed my question up. What i want is one situation. When i click on R once start the Coroutine. Then for example roate the object on peed 1 for 10 seconds inside the Coroutine. That's it. \$\endgroup\$ – jdoedoe doedoe Dec 26 '17 at 0:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.