Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

How would I expand and retract an object on tap?

Discussion in '2D' started by InfiSnyp, Apr 26, 2016.

  1. InfiSnyp

    InfiSnyp

    Joined:
    Mar 25, 2016
    Posts:
    21
    So when I tap I want an object to expand a little and then retract. I have this working like this.

    Code (CSharp):
    1.    
    2.     public float size;
    3.     float velocity;
    4.  
    5.     void Update()
    6.     {
    7.  
    8.         size = Mathf.SmoothDampAngle( size, (Input.GetMouseButton(0)) ? .65f : .6f, ref velocity, .05f);
    9.  
    10.         transform.localScale = new Vector3(size, size, 1);
    11.     }
    This works like this. When I press down the object starts expanding but right when I let go of the tap the object stops expanding and retracts. I don't want this to happen. What I want is when I do a quick tap the obejct expands and retracts. You'd think i would just add in "Input.GetMouseButtonDown(0)" but if I do that then the object expands and retracts really really really fast. I don't know how to slow it down. I'm not sure i'm doing this right in the first place.
     
  2. theANMATOR2b

    theANMATOR2b

    Joined:
    Jul 12, 2014
    Posts:
    7,790
    I'm not a coder but I believe I've seen mention of this type of mishap before. I believe it might be due to the incorrect input (function/action?). There are several GetMouseButton - inputs. I believe you may want Input.GetMouseButtonDown Maybe -
     
  3. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,802
    I just whipped this up quickly without testing, but this is another approach that might help you:
    Code (CSharp):
    1. public bool startsBig = false;
    2. public float smallSize = .6f;
    3. public float bigSize = .65f;
    4. public float speed = 1f;
    5.  
    6. private Vector3 targetScale;
    7. private bool isBig;
    8.  
    9. private void Start() {
    10.     float size = startsBig ? bigSize : smallSize;
    11.     transform.localScale = new Vector3(size, size, 1);
    12.     targetScale = transform.localScale;
    13.     isBig = startsBig;
    14. }
    15.  
    16. private void Update() {
    17.     // on click, toggle the target scale
    18.     if(Input.GetMouseButtonDown(0)) {
    19.         toggleTargetSize();
    20.     }
    21.  
    22.     if(transform.localScale != targetScale) {
    23.         // lerp the scale by a speed variable over time
    24.         transform.localScale = Vector3.Lerp(transform.localScale, targetScale, speed * Time.deltaTime);
    25.     }
    26. }
    27.  
    28. private void toggleTargetSize() {
    29.     // toggle the "isBig" bool
    30.     isBig = !isBig;
    31.     // based on the "isBig" bool, choose the new target scale
    32.     float size = isBig ? bigSize : smallSize;
    33.     // set the target scale
    34.     targetScale = new Vector3(size, size, 1);
    35. }
     
    theANMATOR2b likes this.
  4. theANMATOR2b

    theANMATOR2b

    Joined:
    Jul 12, 2014
    Posts:
    7,790
    Thanks for the pickup. I felt I was wandering into the forest a little too far - and it felt kinda scary. ;)
     
    Last edited: Apr 26, 2016
  5. InfiSnyp

    InfiSnyp

    Joined:
    Mar 25, 2016
    Posts:
    21
    This is kinda what i need but you made it so when i click it expands but when i click again it retracts. What id like is when i click once it expands and retracts.
     
  6. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,802
    Well, I recommend you check out the Animator system. It would be great for something like this and wouldn't require anywhere near as much programming.

    I hope this script doesn't fly over your head (no offense intended), but I reworked it to use a Coroutine to do the sequenced animations. Let me know if you have any questions about what is happening.

    Also once again I did not test this, but it compiles so it must work right? haha...

    Code (CSharp):
    1. public float smallSize = .6f;
    2. public float bigSize = .65f;
    3. public float speed = 1f;
    4.  
    5. private void Update() {
    6.     // on click, start the animation coroutine
    7.     if(Input.GetMouseButtonDown(0)) {
    8.         // stops any currently running coroutines before starting a new one
    9.         StopAllCoroutines();
    10.         // start a coroutine which will grow, then shrink the scale
    11.         StartCoroutine(growAndShrink());
    12.     }
    13. }
    14.  
    15. private IEnumerator growAndShrink() {
    16.     // create Vector3's from the size floats
    17.     Vector3 smallScale = smallSize * Vector3.one;
    18.     Vector3 bigScale = bigSize * Vector3.one;
    19.  
    20.     // animate from small to large, and dont move on until its done
    21.     yield return animateScale(smallScale, bigScale);
    22.     // animate large to small, and dont move on until it's done
    23.     yield return animateScale(bigScale, smallScale);
    24. }
    25.  
    26. private IEnumerator animateScale(Vector3 startScale, Vector3 endScale) {
    27.     bool done = false;
    28.     while(!done) {
    29.         // lerp the scale from start to end over time
    30.         transform.localScale = Vector3.Lerp(startScale, endScale, speed * Time.deltaTime);
    31.  
    32.         // get the distance between the current scale and the end scale
    33.         float distance = Vector3.Distance(transform.localScale, endScale);
    34.  
    35.         // if the current scale is within 0.01 of the end scale... close enough!
    36.         if(distance <= 0.01) {
    37.             // now were done
    38.             done = true;
    39.         }
    40.  
    41.         // wait a frame then continue from here
    42.         yield return null;
    43.     }
    44. }
     
  7. InfiSnyp

    InfiSnyp

    Joined:
    Mar 25, 2016
    Posts:
    21
    Code doesn't seem to work. Hmm. Here. The funny thing is; is that I have 4 lines of code which is working almost perfect. So really i don't think adding another 40 lines will make it work any better. No offence. Just talking from experience as a programmer coming from a different platform and language. Can you possibly explain how this code works by any chance?

    Code (CSharp):
    1.    
    2.     public float size;
    3.     float velocity;
    4.  
    5.     void Update()
    6.     {
    7.  
    8.         size = Mathf.SmoothDampAngle( size, (Input.GetMouseButton(0)) ? .65f : .6f, ref velocity, .05f);
    9.  
    10.         transform.localScale = new Vector3(size, size, 1);
    11.     }
    What I know is that if i change the ".65f" and ".6f" then the object changes sizes and such. If i change ".05f" then it goes faster and slower. The docs don't explain how the Math.SmoothDampAngle works so I need a little bit of help with that. Thanks for the help so far!
     
  8. theANMATOR2b

    theANMATOR2b

    Joined:
    Jul 12, 2014
    Posts:
    7,790
    What do ya know - this circled back around into my neck of the woods.
    Two animation states - one idle (motionless/closed) mouse click to trigger animation, animation plays open/close - returns back to idle/closed state.
    Forget all that code stuff - well except for the input.
     
  9. InfiSnyp

    InfiSnyp

    Joined:
    Mar 25, 2016
    Posts:
    21
    Well like I said. The code works. I just need someones expert eyes to take a look and maybe explain it.
     
  10. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,802
    Well as a programmer you should know that # of lines doesn't determine what is good code. A longer script with better readability is better than a single line that is difficult to determine what is happening, even if it works perfectly.

    SmoothDampAngle smoothly interpolates from the first float parameter to the second float parameter incrementally based on the speed parameter. So every frame your code is interpolating from the current value of "size" towards .6, and then assigning it back to "size".

    It will only interpolate towards .65 when you hold down the mouse button, so that is not doing what you said you wanted.

    I tested my code and found the problem, and then reworked it to use Vector3.SmoothDamp.

    My code does indeed represent two states. It remains idle until you click, and it does the grow/shrink and then goes back to idle. I didn't include any explicit named-states for it, but that is what it does.

    There may be less verbose ways to accomplish this, but the way I did it is sufficiently reusable and clean.

    Alternatively you can download DOTween asset (its free), and use that for all your animation needs.

    This does work:
    Code (CSharp):
    1. public float smallSize = .6f;
    2. public float bigSize = .65f;
    3. public float speed = 1f;
    4.  
    5. private void Update() {
    6.     // on click, start the animation coroutine
    7.     if(Input.GetMouseButtonDown(0)) {
    8.         // stops any currently running coroutines before starting a new one
    9.         StopAllCoroutines();
    10.         // start a coroutine which will grow, then shrink the scale
    11.         StartCoroutine(growAndShrink());
    12.     }
    13. }
    14.  
    15. private IEnumerator growAndShrink() {
    16.     // animate from small to large, and dont move on until its done
    17.     yield return animateScale(bigSize * Vector3.one);
    18.     // animate large to small, and dont move on until it's done
    19.     yield return animateScale(smallSize * Vector3.one);
    20. }
    21.  
    22. private IEnumerator animateScale(Vector3 endSize) {
    23.     bool done = false;
    24.     Vector3 vel = Vector3.zero;
    25.     while(!done) {
    26.         // lerp the scale from current to end over time
    27.         transform.localScale = Vector3.SmoothDamp(transform.localScale, endSize, ref vel, speed);
    28.  
    29.         // get the distance between the current scale and the end scale
    30.         float distance = Vector3.Distance(transform.localScale, endSize);
    31.  
    32.         // if the current scale is within 0.1 of the end scale... close enough!
    33.         if(distance <= 0.1) {
    34.             // now were done
    35.             done = true;
    36.         }
    37.  
    38.         // wait a frame then continue from here
    39.         yield return null;
    40.     }
    41. }
     
    Last edited: Apr 27, 2016