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. Voting for the Unity Awards are OPEN! We’re looking to celebrate creators across games, industry, film, and many more categories. Cast your vote now for all categories
    Dismiss Notice
  3. Dismiss Notice

Update problem

Discussion in 'Scripting' started by Rick92M, Jan 11, 2018.

  1. Rick92M

    Rick92M

    Joined:
    Jan 11, 2018
    Posts:
    13
    Hello guys,
    I am here to ask you help about a thing that is bothering me from literally a week. Here is the problem:
    I have to put animations and charging of things (like particles) with the pressure of a touch button but I can't figure out how. I've tried CoRoutines, Loops, Booleans inside other methods, playing with Input.Touch (etc.) and so on but I can't find a solution.
    The code is too long, about 100 lines only for a serie of if statements in regard of the pressure and release of a button because there are lots of things going on; so I think it is better to post an example of what I mean:
    Code (CSharp):
    1. If(//Here I want to put the touch code that must work with a Canvas button but I can't comprehend how)
    2. {
    3. playerAnimation.Play("Particle")
    4. }
    All of this in the Update method, but I want to put THIS at work with touch buttons.
    With them the only things that I can do are single taps while the thing that I want are long presses.
    The buttons to be touched are made with Canvas, just to remember.
    With a normal key everything works fine.
    THANK YOU so much if you bother my question.
     
  2. bigmisterb

    bigmisterb

    Joined:
    Nov 6, 2010
    Posts:
    4,221
  3. Rick92M

    Rick92M

    Joined:
    Jan 11, 2018
    Posts:
    13
    Thank you for your response but as I said, I've tried everything.
    I studied thoroughly the documentation but I can't put that to work. Is for this precise reason that I'm asking help.
    The fact is, I can't put a long pressure on a Canvas button, even with the touch phases because I can't figure out how to give a position, to the touch, where the button is.
     
  4. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Just to be sure I have your intention correct, are you asking how you can execute a method if the touch lasts a certain amount of time?
     
  5. Rick92M

    Rick92M

    Joined:
    Jan 11, 2018
    Posts:
    13
    Not exactly.
    I want to play an animation, or something that have to last long, with a long pressure touch.
    The code that I want to execute is all inside the Update method. The problem is that I can't put that to work with a long pressure touch; with the keyboard works fine. I put single touches (or brief touches or single taps, you get the idea) outside the Update method and they work fine; when it comes to long touches nothing works.
     
  6. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,140
    You can get the position of a touch. And if you wanted, you could use a combination of things. Touch for the pressure and the ipointerdown/up interfaces to detect touching a button.

    But honestly, I might be confused as to what you want also. From the sounds of it, you have a button on the screen and you want to do different things based on a quick tap, a tap and hold.

    So, trigger the button and set a bool. While that bool is true, let your update check for touch if you need to. If you're using the touch pressure system. Then when you let go of the button, set the bool to false.
     
  7. Rick92M

    Rick92M

    Joined:
    Jan 11, 2018
    Posts:
    13
    I try to make things clear.
    I have a character that, with a long button pressure, plays a certain animation and do much other stuff.
    The code is inside the update function within an if statement.
    I have buttons on the screen, two that move the player on the x axis and two on the y axis; other than those I have different buttons that do different actions like shoot and jump for example. I have ALSO a button that makes the player play a precise animation, but this animation works only if you press the button long enough.
    The problem is this: I can't put to work long touches, not with other methods, Loops, Booleans, IF statements, calling the OnGUI method, references, Touch code and so on.
    The question is, how can I play a long animation with a long pressure touch located on the position of the Canvas button?
    This is enough, the other stuff inside the if statement isn't to consider.
    Thanks.
     
  8. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    I'd suggest using IPointerDown and begin a timer. If the time (long press) you want passes, do the animation. Otherwise, cancel the timer.
    You could be running the timer in Update() or a coroutine.
     
  9. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,140
    Well, I already explained it. If you press a button on your screen, you set a bool to true. Then while true, you do something. If you let go of the button, you set the bool to false, then you stop doing something.
    https://docs.unity3d.com/ScriptReference/EventSystems.IPointerDownHandler.html
    https://docs.unity3d.com/ScriptReference/EventSystems.IPointerUpHandler.html

    The confusion I'm having is the "long button pressure" if you just want to do something while the button is down, what I mention is enough. If you want the touch pressure system, then you'll need to integrate that as well, but you can use that in combination with what I said above. This is the touch pressure https://docs.unity3d.com/ScriptReference/Touch-pressure.html

    If you need both, you use the pointer system to detect you've pressed the button, then you check your touch pressure.

    Oh, and as @methos5k says, run a timer if you want different things to happen after a set time, then either trigger as x time passes or check that timer when you let go of the button.
     
  10. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Ya, sorry, I wasn't that familiar with the pressure of touch (not used it or participated in a lot of talks about it).
    "long pressure" could mean either, I suppose :)
     
  11. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,140
    I'm not either. Which is why I was trying to get clarification if he wanted the pressure or he just wanted how long a person is holding down the button. Since you asked about certain amount of time and OP said not exactly, I wasn't sure.
     
  12. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Ya, we'll see :)
     
  13. Rick92M

    Rick92M

    Joined:
    Jan 11, 2018
    Posts:
    13
    Thank you for your time.
    The problem, however, remains.
    Is obvious that without a script it can be difficult to give an idea, so I try to explain in another way:
    I want a specific CanvasButton to, if pressed for long enough (with touch code), to play an animation that need a certain amount of time to be completed. This, however, won't work in any case that I've tried. So, how can I create a touch.position in a particular point of the screen (in this case the button is a circle)?
     
  14. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,140
    If it's a button on the screen, then that's what we're explaining. Using the ipointer interfaces, you can push the button, start a timer/set a bool to true, and then when the button is released, you stop the timer/set bool to false.

    This way, while the button is pressed, the timer is going or the bool is true and you just use that to determine what you want to do. You don't need to use the Input.touch code, the ipointer interfaces handle touches or clicks.

    With what you are asking, it sounds like you want to start a timer, then as it ticks, check the value. Once it hits timer >= x amount, trigger your animation.

    The script with the ipointer interfaces on it would go on your button. This way only that button reacts to that down/up.

    Note that you don't actually need a button UI object. It can be an image, or even an image that has alpha set to 0. Just needs the raycast enabled on it.

    To explain better perhaps...
    1. Player presses button, the OnPointerDown registers the press and turns on timer.
    2. Player is holding finger against the button. Timer ticks. Some code checks the time passed.
    3. If required time passes, animation players.
    4. If player removes finger, timer stops.
    5. If player presses and holds finger again, timer resets and starts again.
     
    Last edited: Jan 11, 2018
  15. Rick92M

    Rick92M

    Joined:
    Jan 11, 2018
    Posts:
    13
    Even with your method things don't work.
    The fact is, the animation is something that you must play on the Update method, right? So with another method the only thing that Unity do is a frame of the animation. I've tried with a timer and even with a timer and a set of bools, but nothing changed.
    Thanks.
     
  16. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,140
    Are you using the animation system or are you animating it yourself by swapping sprites or moving things yourself?

    If you're just playing the animation, no, you shouldn't have to play it in update.

    Show some code, if you're trying stuff out, it will make it easier for us to help you if we see what you are doing.
     
  17. Rick92M

    Rick92M

    Joined:
    Jan 11, 2018
    Posts:
    13
    I'm using the animation system and, obviously, the animator.
    I need to play that specific animation in a certain amount of time.
    Moreover, I have in this code even a particle that will spread depending on the time you are pressing the button.
    I can't post the code because there's lot of staff that isn't matter of this question and will confuse more. I'll try to make an example:
    Code (CSharp):
    1. void Update(){
    2. if(Input.GetKey(KeyCode.A)){
    3. isCharging = true;
    4. }
    5.  
    6. if (isCharging){
    7. playerAnimation.Play ("Specific Animation");
    8. particle.SetActive(true);
    9. chargeCounter += chargeRegen * 0.5f;
    10. chargeBar.fillAmount = chargeCounter / 100f;
    11. }
    12. }
    There is a lot more going on, but this is an example of the essential code that I need to execute in order to work with the other.
    With the keyboard it works perfectly, but if I start putting touch code it doesn't work nor with timers, booleans inside other methods, methods, OnGUI, loops, references, buttons, IPointers, event system and so on.
    Everything of this code doesn't work.
     
  18. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Even in the simplest scenario, if you set the 'isCharging' to true when the IPointerDown event occurs, and to false when 'up' occurs, it should work. If you have some code that says "else isCharging = false' (related to your GetKey), you'd have to remove that, too, or work around it.

    Not sure how you wrote the other code that you say doesn't work.. :)
     
  19. Rick92M

    Rick92M

    Joined:
    Jan 11, 2018
    Posts:
    13
    Well, the thing is: I've made another script dedicated ONLY to this exact problem, therefore without other code that can interfere. It doesn't work anyway.
    I'll ask you a question (thank you for your time however), how you'll write a code like this made with a touch system in mind? Maybe if you show me what you mean even with few lines of code I can see if we're thinking the same thing (although I think we are).
     
  20. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    I think I already gave an example of what I'd do, as did @Brathnann .

    I would set a bool with IPointerDown and set my timer to 0. Then, with the help of the Update method or a coroutine, I would check against this bool and increment the timer (and whatever else). The first frame that the time is >= "long press time", I would start the animation (on a loop if you expect it to repeat before it's done).
    On PointerUp , I would set the bool to false.

    This script would go on the button.
     
  21. Rick92M

    Rick92M

    Joined:
    Jan 11, 2018
    Posts:
    13
    Well, I've did that as well!
    Let's look at the charging bar for a moment: in the Update function (with keys) it fills optimally, outside of it(even with a boolean inside the IPointerDown method and the code in the Update method) do not fills if not for the exact amount that would fill it in a frame... why? Obviously because is outside the Update method! That's the problem!


    The game is complete and this is the only thing that bothers me, it's incredible!
    I had no problems like this even with async code that sure is a little more complex!
     
  22. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    I'm not sure what to tell you. There must be a detail missing. Your conclusion isn't accurate, imho.
    I wish I could help more, but I'm unsure what is the matter.
     
  23. Rick92M

    Rick92M

    Joined:
    Jan 11, 2018
    Posts:
    13
    Yes, I think that as well. There is a little, tiny detail that I'm not considering. Tell me, how do you modify this code with IPointerDown(without considering IPointerUp)?
    Code (CSharp):
    1. void Update(){
    2.  
    3.     if (isCharging){
    4.     playerAnimation.Play ("Specific Animation");
    5.     particle.SetActive(true);
    6.     chargeCounter += chargeRegen * 0.5f;
    7.     chargeBar.fillAmount = chargeCounter / 100f;
    8.        particle.SetActive (true);
    9.             StartCoroutine (chargeDestruction ());
    10.     }
    11.     }
    12.  
    13.     public void OnPointerDown(PointerEventData data) {
    14.         startTimer = true;
    15.         if (timer >= 0f) { //There isn't a specific time to trigger the animation
    16.             isCharging = true;
    17.         }
    18.     }
    19.     IEnumerator chargeDestruction ()
    20.     {
    21.         GameObject clone = Instantiate (particle, transform.position, transform.rotation);
    22.         clone.name = clone.name.Replace ("(Clone)", "");
    23.         Destroy(clone, 0.2f);
    24.         yield return new WaitForSeconds (5f);
    25.     }
    26.  
    Remember that all of this works with a normal keyboard key. Don't work with buttons.
    The other code that I don't post isn't to consider because this is a script that I've made separately from my main code.
     
  24. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Sure, well ifCharging is never false (or you don't care about it), simply setting it to true with OnPointerDown is enough to work on that example, provided that that script is actually on the Button.
     
  25. Rick92M

    Rick92M

    Joined:
    Jan 11, 2018
    Posts:
    13
    Yes it is. The boolean doesn't matter if it is false or true because I've tried all the possible combinations. Try to read the code now, I've modified it a little.
     
  26. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    I would imagine all you need is 'isCharging = true' and chargeCounter = 0 in PointerDown, as that code shows nothing else relevant. startTimer for instance, isn't even used.
    Perhaps get rid of timer >= 0 and just say (in PointerDown): if (isCharging) return;

    That's from what I understand of your question.
     
  27. Rick92M

    Rick92M

    Joined:
    Jan 11, 2018
    Posts:
    13
    I'll thank you for your support, but this doesn't work. For every touch input that has to be executed for a certain amount of time, nothing works, at least for me.
     
  28. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Ya, you know what.. you're right but also your code threw me a little. That's my bad, though.

    So, previously when you said "It's working how I want when I set this bool, using GetKey" that's the part that threw me up, to be clear. Because that bool was never reset, I mean.

    You do need a PointerUp & Exit to complete this code, I think. (unless you don't care about exit).

    Code (csharp):
    1.  
    2. public void OnPointerDown(PointerEventData data) {
    3.     if(isCharging) return;
    4.     isCharging = true;
    5.     timer = 0;
    6.    }
    7. public void OnPointerUp(PointerEventData data) {
    8.    isCharging = false;
    9.   }
    10. void Update() {
    11.    if(isCharging)
    12.    {
    13.        if(timer >= YourValueHere)
    14.        {
    15.             // your code here
    16.        }
    17.       timer += Time.deltaTime * SomeSpeedVariable;
    18.    }
    19. }
    20.  
     
  29. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    I do not understand if you want the animation to begin straight away, and then something else happens later after the timer, or both things happen later after the timer, so I couldn't completely finish the code example.
    But hopefully with that it makes some sense.
     
  30. Rick92M

    Rick92M

    Joined:
    Jan 11, 2018
    Posts:
    13
    Man, I fu**ing did it! I've tried a few modifications on my previous code and it worked! It works yours too, I've tried it.
    Thank you so much for your time and your support!
     
  31. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Hey, that's awesome. When I saw your '*' explicit response, I was backing away.. but then it turned out to be good news lol.
    Finally, glad you got it working :)
     
  32. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,140
    Glad you got it working and @methos5k was able to post you an example.