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.

Question How to make the game has better touch performance ?

Discussion in 'Scripting' started by EverydayImShuffling, Sep 11, 2023.

  1. EverydayImShuffling

    EverydayImShuffling

    Joined:
    Jul 17, 2023
    Posts:
    5
    Hi,
    I'm creating a 2D game that require players to touch on a specific cell on screen to earn points, there're 20 of incorrect cells and 2 correct cells. The players have to touch it fast as the screen will change each interval time (0.2s-0.4s)

    The problem arises when the game runs on slow phones (3gb ram, Snapdragon 439). The screen changes faster (~0.2s each change) and the game sometimes doesn't respone to players touches. I guess there's something slow in checking the touch.

    TouchHandler.cs
    Code (CSharp):
    1.  
    2.     void Awake()
    3.     {
    4.         playerInput = GetComponent<PlayerInput>();
    5.         touchPressAction = playerInput.actions["TouchPress"];
    6.         touchPositionAction = playerInput.actions["TouchPosition"];
    7.     }
    8.     void OnEnable()   {touchPressAction.performed += TouchPress;}
    9.     void OnDisable()  {touchPressAction.performed -= TouchPress;}
    10.  
    11.     void TouchPress(InputAction.CallbackContext context)
    12.     {
    13.         touchPos = touchPositionAction.ReadValue<Vector2>();
    14.         Ray ray = Camera.main.ScreenPointToRay(touchPos);
    15.         RaycastHit hit;
    16.         if(Physics.Raycast(ray, out hit, 100.0f))
    17.         {
    18.             string objectTag = hit.collider.gameObject.tag;
    19.             if(objectTag == "Cell")
    20.             {
    21.                 cell = hit.collider.gameObject.GetComponent<Cell>();
    22.                 gameFlow.CheckMatch(cell.Row, cell.Col);
    23.              }
    24.         }
    25.     }
    26.  
    GameFlow.cs
    Code (CSharp):
    1.     public void CheckMatch(int _row, int _col)
    2.     {
    3.         if (isGameOver) {return;}
    4.         if (gridManager.GridCell[_row, _col].CellType == profileManager.TrueType)
    5.         {
    6.             HandleTrueMatch(_row, _col); //create correct effects and score++
    7.         }
    8.         else
    9.         {
    10.             HandleFalseMatch(_row, _col); //create incorrect effects
    11.         }
    12.     }


    Within the above code, I'm not sure if I can make it any better. I would be very appriciated if someone can point out any flaws or make it a bit more performance :) Thank you in advance
     

    Attached Files:

    Last edited: Sep 11, 2023
  2. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,811
    This isn't a post for the 2D forum. It's a generic scripting/performance problem. It's not even using 2D physics. ;)

    Note that you're asking about performance and assuming that devs can somehow look at your post and see the performance problems. This is what the profiler is for so I would recommend for any performance questions, spin-up the profiler and see what the problem is or in the very least, see where in your project the performance areas are.

    I'll move your post to the Scripting forum.
     
  3. EverydayImShuffling

    EverydayImShuffling

    Joined:
    Jul 17, 2023
    Posts:
    5
    I'll be more careful next time :) Also, thanks for the "profiler" keyword, feels like the direction I'm looking for
     
    Last edited: Sep 11, 2023
  4. ijmmai

    ijmmai

    Joined:
    Jun 9, 2023
    Posts:
    188
    there is a chance I am oversimplifying things, but would buttons work as well?
    let them send an "I am hit" message to the controller that keeps track of game flow, when they are "blue" and clicked/tapped on. Change the color/sprite of the button when it is (de)selected to be valid.
     
  5. EverydayImShuffling

    EverydayImShuffling

    Joined:
    Jul 17, 2023
    Posts:
    5
    I added sound + particles to play if the buttons are hit, 100% of them are responsible in normal speed (~0.5s). But only when the game increases the speed, it sometimes misses the users touches.
     
  6. ijmmai

    ijmmai

    Joined:
    Jun 9, 2023
    Posts:
    188
    What I meant was, skip all the testing, what was hit, where it was hit, what the coordinates are in the grid, was it a circle that was meant to be hit and so on.

    In short:
    instantiate all circles (taking this from the image you shared)
    let a game controller set two of them as valid (by adjusting their color, and/or some boolean value)
    let the game controller wait for two valid hits within timespan x

    let a circle check when pressed, if it has the right color, or boolean value true
    if so, report to game controller
    if not, don't report to game controller. If needed perform actions (sound, animation) for invalid hits.

    no need to raycast, check grid coordinates and so on, if you put the logic in the buttons. Real buttons, work by default on mobile devices.

    But like I said, maybe there is more to the story, which makes your approach way more logical. I just try to keep things simple.
     
    EverydayImShuffling likes this.
  7. wideeyenow_unity

    wideeyenow_unity

    Joined:
    Oct 7, 2020
    Posts:
    728
    As far as your raycast check, this would be miles better for performance:
    Code (CSharp):
    1. if (Physics.Raycast(ray, out RaycastHit hit, 100.0f))
    2.         {
    3.             if (hit.collider.TryGetComponent<Cell>(out Cell cell))
    4.             {
    5.                 gameFlow.CheckMatch(cell.Row, cell.Col);
    6.             }
    7.         }
    So if the collider hit by raycast is a gameObject containing the class of "Cell", it will function for that appropriately.

    Also you may wish to cache the camera, as calling
    Camera.main
    is equivalent to GetComponent(), and is best cached if using more than once.

    also this can work without the extra "gameObject" call, as your just asking to go through more processes, which is not good. This should work just fine:
    cell = hit.collider.GetComponent<Cell>();


    As far as touch, I'm not entirely sure, as last I read into it, any handled mouse functions work as touch inputs. So what works better, or is more correct, I have no clue. I did notice a mobile performance vid on youtube the other day, I didn't look into it yet: here
    or even Unity's vid: here
     
    EverydayImShuffling likes this.
  8. EverydayImShuffling

    EverydayImShuffling

    Joined:
    Jul 17, 2023
    Posts:
    5
    Thanks, I watched the video and it gave me some good ideas on how to improve the performance. I'm now trying Async await and other parallel computing stuffs so that the game can run smoother.
     
    wideeyenow_unity likes this.
  9. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    37,245
    You might want to back up a moment and find out what is actually happening when you report:

    There's at a minimum THREE different things that could be in play here:

    - the input event is NOT being generated outside of your code and passed in

    - the input event IS being generated and your code is mis-handling it

    - something else entirely.

    Every one of those things is going to need a different approach to solving.

    Wrecking your codebase with guessed changes is not a good strategy in general, unless you recognize you are doing it and you have everything in source control for instant-reversion.

    Time to start debugging! Here is how you can begin your exciting new debugging adventures:

    You must find a way to get the information you need in order to reason about what the problem is.

    Once you understand what the problem is, you may begin to reason about a solution to the problem.

    What is often happening in these cases is one of the following:

    - the code you think is executing is not actually executing at all
    - the code is executing far EARLIER or LATER than you think
    - the code is executing far LESS OFTEN than you think
    - the code is executing far MORE OFTEN than you think
    - the code is executing on another GameObject than you think it is
    - you're getting an error or warning and you haven't noticed it in the console window

    To help gain more insight into your problem, I recommend liberally sprinkling
    Debug.Log()
    statements through your code to display information in realtime.

    Doing this should help you answer these types of questions:

    - is this code even running? which parts are running? how often does it run? what order does it run in?
    - what are the names of the GameObjects or Components involved?
    - what are the values of the variables involved? Are they initialized? Are the values reasonable?
    - are you meeting ALL the requirements to receive callbacks such as triggers / colliders (review the documentation)

    Knowing this information will help you reason about the behavior you are seeing.

    You can also supply a second argument to Debug.Log() and when you click the message, it will highlight the object in scene, such as
    Debug.Log("Problem!",this);


    If your problem would benefit from in-scene or in-game visualization, Debug.DrawRay() or Debug.DrawLine() can help you visualize things like rays (used in raycasting) or distances.

    You can also call Debug.Break() to pause the Editor when certain interesting pieces of code run, and then study the scene manually, looking for all the parts, where they are, what scripts are on them, etc.

    You can also call GameObject.CreatePrimitive() to emplace debug-marker-ish objects in the scene at runtime.

    You could also just display various important quantities in UI Text elements to watch them change as you play the game.

    Visit Google for how to see console output from builds. If you are running a mobile device you can also view the console output. Google for how on your particular mobile target, such as this answer for iOS: https://forum.unity.com/threads/how-to-capturing-device-logs-on-ios.529920/ or this answer for Android: https://forum.unity.com/threads/how-to-capturing-device-logs-on-android.528680/

    If you are working in VR, it might be useful to make your on onscreen log output, or integrate one from the asset store, so you can see what is happening as you operate your software.

    Another useful approach is to temporarily strip out everything besides what is necessary to prove your issue. This can simplify and isolate compounding effects of other items in your scene or prefab.

    If your problem is with OnCollision-type functions, print the name of what is passed in!

    Here's an example of putting in a laser-focused Debug.Log() and how that can save you a TON of time wallowing around speculating what might be going wrong:

    https://forum.unity.com/threads/coroutine-missing-hint-and-error.1103197/#post-7100494

    "When in doubt, print it out!(tm)" - Kurt Dekker (and many others)

    Note: the
    print()
    function is an alias for Debug.Log() provided by the MonoBehaviour class.
     
    darnoldi and EverydayImShuffling like this.
  10. EverydayImShuffling

    EverydayImShuffling

    Joined:
    Jul 17, 2023
    Posts:
    5
    Hi, thanks so much for your detail reply, I've solve the problem with this idea and using Debug.Log(). There's mostly nothing to do with the above code. I used the default interaction and it skipped performing if it didn't recognise the interaction pattern! ( e.g, touch and drag a bit).
    Now I add Press interaction with "Release Only" trigger and it works as my expect :D