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 to detect if a mobile is running the WebGL scene

Discussion in 'WebGL' started by notloop, Nov 9, 2016.

  1. notloop

    notloop

    Joined:
    Feb 28, 2016
    Posts:
    14
    Hi all,

    Is there a way to detect if a mobile is using WebGL at run-time?

    I've tried Application.isMobilePlatform, but it seems to return false, as I guess the run-time platform isn't actually mobile, but WebGL instead. Maybe I need to use System.Info or something similar? However, I was wondering if Unity had something built in for this?
     
  2. Marco-Trivellato

    Marco-Trivellato

    Unity Technologies

    Joined:
    Jul 9, 2013
    Posts:
    1,654
    In the Unity installation folder, PlaybackEngines/WebGLSupport/BuildTools/UnityConfig/UnityConfig.js contains code to do that. You could do the same in a simple jslib and create the corresponding C# binding.

    Does that make sense ?
     
    xiangshushu, Mehrdad995 and Aseemy like this.
  3. notloop

    notloop

    Joined:
    Feb 28, 2016
    Posts:
    14
    Hi Marco, yes that makes sense, got it all implemented. Thanks!
     
  4. rdurland

    rdurland

    Joined:
    May 3, 2013
    Posts:
    3
    I'm pretty new to developing and can wrap my head around how to use C# for scripting for a webgl project I'm working but need it to detect whether it's running on mobile and don't understand what I need to do here. Could you point me in the right direction for how to create this jslib and C# binding? I'm also unable to find the UnityConfig.js on my system. Thanks for any help!
     
  5. Marco-Trivellato

    Marco-Trivellato

    Unity Technologies

    Joined:
    Jul 9, 2013
    Posts:
    1,654
    You can get that information in Javascript from UnityLoader.SystemInfo.mobile:
    For example, in your html:
    Code (csharp):
    1.  
    2.     <script src="Build/UnityLoader.js"></script>
    3.     </script>
    4.       console.log("mobile: " + UnityLoader.SystemInfo.mobile);
    5.     </script>
    6.  
    will print true/false depending on whether it's running on a mobile browser.
    So, the idea is that you make your own jslib (see manual) to get that information from JS to C#.
    does that make sense?
     
    Mehrdad995, ba55yunky, jojue and 2 others like this.
  6. asimdeyaf

    asimdeyaf

    Joined:
    Nov 21, 2016
    Posts:
    3
  7. AdamSt

    AdamSt

    Joined:
    Jun 2, 2013
    Posts:
    18
    tantx and Da_Elf like this.
  8. MaskedMouse

    MaskedMouse

    Joined:
    Jul 8, 2014
    Posts:
    1,058
    Please don't necro old threads

    The WebGL Template has been changed in 2020.1 which includes detecting Mobile clients.
    You could use the same logic.

    Code (javascript):
    1. if (/iPhone|iPad|iPod|Android/i.test(navigator.userAgent))
    2. {
    3.   container.className = "unity-mobile";
    4.   config.devicePixelRatio = 1;
    5. }
    6. else
    7. {
    8.   canvas.style.width = "100%";
    9.   canvas.style.height = "100%";
    10. }
     
    Blarp and adamgolden like this.
  9. adamgolden

    adamgolden

    Joined:
    Jun 17, 2019
    Posts:
    1,494
    I do this from a jslib (same as @MaskedMouse suggested done within Unity),
    Code (JavaScript):
    1. mergeInto(LibraryManager.library, {
    2.   IsMobileBrowser: function () {
    3.     return (/iPhone|iPad|iPod|Android/i.test(navigator.userAgent));
    4.   }, [...]
     
  10. Siba_M_M

    Siba_M_M

    Joined:
    Aug 11, 2020
    Posts:
    15
    Hey,
    Could you explain more?
    I'm new to WebGL Unity and I'm facing a problem with the Retina display on MacBooks
    On windows it is all great and the FPS is 45-60 and the resolution is 1920 * 1xxx. On Macs the performance drops to 13-17 because of Retina and the resolution is 3300 * 2100 (double the laptop's resolution).It is because the Macs DPI is 2.
    Do you think your solution could solve this ? Like could I detect the Macs and change the DPI ? and where should I add this part of code ?
    Thanks in advance
     
  11. jukka_j

    jukka_j

    Unity Technologies

    Joined:
    May 4, 2018
    Posts:
    944
    @MaskedMouse' s code example shows how rendering to low/standard DPI is done. In the main .html file, set "config.devicePixelRatio = 1;" to override the DPI rendering scale. This works in Unity 2020.1 and newer iirc.
     
  12. limkuanyong

    limkuanyong

    Joined:
    Apr 29, 2019
    Posts:
    2
    Hi. I'm new to Unity WebGL and I'm still not very sure how to detect if a mobile is running in the WebGL Scene. The attached image is the error that I got after building and running it. I've also took reference from https://answers.unity.com/questions/1698508/detect-mobile-client-in-webgl.html, and the previous messages, but it still does not work.

    This is the script in my jslib file:
    Code (JavaScript):
    1. var CheckMobile = {
    2.     IsMobile : function()
    3.     {
    4.         return UnityLoader.SystemInfo.mobile;
    5.     }
    6. };
    7. mergeInto(LibraryManager.library, CheckMobile);
    This is my Unity script file:
    Code (CSharp):
    1.  
    2. using System.Runtime.InteropServices;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5. public class StartSceneController : MonoBehaviour
    6. {
    7.     private bool playOnce = false;
    8.     public Text text;
    9.     [DllImport("__Internal")]
    10.     private static extern bool IsMobile();
    11.     void Start()
    12.     {
    13.         text.text = "";
    14.     }
    15.     public bool isMobile()
    16.     {
    17. #if !UNITY_EDITOR && UNITY_WEBGL
    18.             return IsMobile();
    19. #endif
    20.         return false;
    21.     }
    22.     void Update()
    23.     {
    24.         if (playOnce == false)
    25.         {
    26.             text.text = "Mobile: " + isMobile();
    27.             playOnce = true;
    28.         }
    29.     }
    30. }
    31.  
    32.  
    Could anyone help?
     

    Attached Files:

    Last edited: Oct 28, 2020
  13. jukka_j

    jukka_j

    Unity Technologies

    Joined:
    May 4, 2018
    Posts:
    944
    The variable UnityLoader is not available in that JavaScript function scope. Try replacing the content of that function with

    Code (JavaScript):
    1. var CheckMobile = {
    2.     IsMobile : function()
    3.     {
    4.         return /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
    5.     }
    6. };
    7. mergeInto(LibraryManager.library, CheckMobile);
    or use the Application.isMobilePlatform API (https://docs.unity3d.com/ScriptReference/Application-isMobilePlatform.html)
     
  14. jukka_j

    jukka_j

    Unity Technologies

    Joined:
    May 4, 2018
    Posts:
    944
    This might also work:

    Code (JavaScript):
    1. var CheckMobile = {
    2.     IsMobile : function()
    3.     {
    4.         return Module.SystemInfo.mobile;
    5.     }
    6. };
    7. mergeInto(LibraryManager.library, CheckMobile);
    (although not 100% sure on that form)
     
  15. AgnosiaGames

    AgnosiaGames

    Joined:
    May 26, 2020
    Posts:
    57
    Hi @Siba_Gamyra. We have an asset for your problem. The asset is modifying the DPI dynamically depending on current FPS. If FPS is too low, the asset will reduce DPI automatically. And it is effortless totally. You should just add the prefab to your scene, That's all.

    You can check here;
    WebGL FPS Accelerator
     
    Last edited: Oct 30, 2020
  16. limkuanyong

    limkuanyong

    Joined:
    Apr 29, 2019
    Posts:
    2
    Hi @jukka_j. Thank you so much for your assistance. It can now detect if I am running it on Mobile devices. Thanks a lot! :)
     
  17. slaga

    slaga

    Joined:
    Dec 3, 2018
    Posts:
    142
    thank you for this but might i ask a question!? like how do we actually use it? i mean i have made a cross platform input system for a webgl game im making. inside unity it works fine ( when tested on device emulator it creates buttons on screen and when not you can move it the player with the keyboard and some other things ) but once i uploaded it to a testing server to try it , it didnt work, it detected it as webgl so i found this thread and used this code ( havent tested it yet ) but assuming in my case i want to use the code i have made already how would i do it??

    this is the system check script
    and ive added the code from above!
    Code (CSharp):
    1. using System.Runtime.InteropServices;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. using UnityEngine.SceneManagement;
    6. using UnityEngine.UI;
    7.  
    8. public class SystemDetect : MonoBehaviour
    9. {
    10.     public GameObject mobileControls;
    11.     public GameObject portraitWarning;
    12.  
    13.     private bool playOnce = false;
    14.     public Text text;
    15.     [DllImport("__Internal")]
    16.     private static extern bool IsMobile();
    17.     void Start()
    18.     {
    19.         text.text = "";
    20.     }
    21.     public bool isMobile()
    22.     {
    23. #if !UNITY_EDITOR && UNITY_WEBGL
    24.             return IsMobile();
    25. #endif
    26.         return false;
    27.     }
    28.     // Start is called before the first frame update
    29.  
    30.     // Update is called once per frame
    31.     void Update()
    32.     {
    33.         if (Application.platform == RuntimePlatform.WindowsEditor)
    34.         {
    35.             Debug.Log("webgl/windows");
    36.             Input.GetAxis("Horizontal");
    37.  
    38.         }
    39.         else if (Application.platform == RuntimePlatform.Android)
    40.         {
    41.             if (Screen.orientation == ScreenOrientation.Portrait)
    42.             {
    43.                 portraitWarning.SetActive(true);
    44.             }
    45.             else if (Screen.orientation == ScreenOrientation.Landscape)
    46.             {
    47.                 portraitWarning.SetActive(false);
    48.             }
    49.  
    50.             Debug.Log("Mobile");
    51.             mobileControls.SetActive(true);
    52.         }
    53.  
    54.     }
    55.     public void Play()
    56.     {
    57.         if (Application.platform == RuntimePlatform.Android)
    58.         {
    59.             if (Screen.orientation == ScreenOrientation.Landscape)
    60.             {
    61.                 SceneManager.LoadScene("Menu");
    62.             }
    63.         }else if (Application.platform == RuntimePlatform.WindowsEditor)
    64.         {
    65.             SceneManager.LoadScene("Menu");
    66.         }
    67.  
    68.     }
    69.     public void ToggleFullScreen()
    70.     {
    71.         // Toggle fullscreen
    72.         Screen.fullScreen = !Screen.fullScreen;
    73.     }
    74. }
    75.  
    and this my my controls. as you can see its nothing just a testing game to get things right
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class PlayerControl : MonoBehaviour
    6. {
    7.     public float moveSpeed;
    8.     private float movement;
    9.     private bool moveRight;
    10.     private bool moveLeft;
    11.     private Rigidbody2D rb2d;
    12.  
    13.     // Start is called before the first frame update
    14.     void Start()
    15.     {
    16.        
    17.         rb2d = GetComponent<Rigidbody2D>();
    18.         moveLeft = false;
    19.         moveRight = false;
    20.     }
    21.  
    22.     // Update is called once per frame
    23.     void Update()
    24.     {
    25.        if (Application.platform == RuntimePlatform.WindowsEditor)
    26.         {
    27.            desktopMovement();
    28.        }
    29.         else if (Application.platform == RuntimePlatform.Android)
    30.         {
    31.             mobileMovement();
    32.             rb2d.velocity = new Vector2(movement, rb2d.velocity.y);
    33.         }
    34.     }
    35.  
    36.     void desktopMovement()
    37.     {
    38.         movement = Input.GetAxis("Horizontal");
    39.         rb2d.velocity = new Vector2(movement * moveSpeed, rb2d.velocity.y);
    40.     }
    41.     void mobileMovement()
    42.     {
    43.         if (moveLeft)
    44.         {
    45.             movement = -moveSpeed;
    46.         }
    47.         else if (moveRight)
    48.         {
    49.             movement = moveSpeed;
    50.         }
    51.         else
    52.         {
    53.             movement = 0;
    54.         }
    55.        
    56.     }
    57.  
    58.     //settting up ui buttons movement
    59.     public void PointerDownLeft()
    60.     {
    61.         moveLeft = true;
    62.     }
    63.     public void PointerUpLeft()
    64.     {
    65.         moveLeft = false;
    66.     }
    67.     public void PointerDownRight()
    68.     {
    69.         moveRight = true;
    70.     }
    71.     public void PointerUpRight()
    72.     {
    73.         moveRight = false;
    74.     }
    75.  
    76. }  
    77.  
     
  18. adamgolden

    adamgolden

    Joined:
    Jun 17, 2019
    Posts:
    1,494
    Create a file called like "Assets/Plugins/webgl.jslib" - this adds the Javascript to your project:
    Code (CSharp):
    1. mergeInto(LibraryManager.library, {
    2.   IsMobileBrowser: function () {
    3.     return (/iPhone|iPad|iPod|Android/i.test(navigator.userAgent));
    4.   }
    5. });
    Then create a file like "Assets/Scripts/WebGLHandler.cs" to expose the functions from the .jslib that you want access to from C#:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Runtime.InteropServices;
    3. public class WebGLHandler : MonoBehaviour
    4. {
    5.   [DllImport("__Internal")]
    6.   public static extern bool IsMobileBrowser();
    7. }
    Then make something like "Assets/Scripts/Platform.cs" to wrap conditional compilation:
    Code (CSharp):
    1. public class Platform
    2. {
    3.   public static bool IsMobileBrowser()
    4.   {
    5. #if UNITY_EDITOR
    6.     return false; // value to return in Play Mode (in the editor)
    7. #elif UNITY_WEBGL
    8.     return WebGLHandler.IsMobileBrowser(); // value based on the current browser
    9. #else
    10.     return false; // value for builds other than WebGL
    11. #endif
    12.   }
    13. }
    Then anywhere you want, you can do this:
    Code (CSharp):
    1. if (Platform.IsMobileBrowser())
    2. {
    3.   // whatever for mobile browser
    4. } else {
    5.   // whatever for desktop browser
    6. }
    Edit: I don't think you need the "WebGLHandler" to extend from MonoBehaviour, I just stripped the above example down from stuff I do. You could probably remove
    : MonoBehaviour
    and remove the
    using UnityEngine;
    from the top of that.

    Edit: You could probably also combine WebGLHandler and Platform into the same class, just based the snippets on how I have things structured without much attention to simplifying.
     
    Last edited: Nov 11, 2020
    Argenuto, Mehrdad995 and ejx61s like this.
  19. slaga

    slaga

    Joined:
    Dec 3, 2018
    Posts:
    142
    thank you for your help , its a great start for me, but i cant get it work on Unity 2020. i changed all my code to this , but still it doesnt show the warning screen that forces the user to rotate the phone or the virtual buttons!
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class PlayerControl : MonoBehaviour
    6. {
    7.     public float moveSpeed;
    8.     private float movement;
    9.     private bool moveRight;
    10.     private bool moveLeft;
    11.     private Rigidbody2D rb2d;
    12.  
    13.     // Start is called before the first frame update
    14.     void Start()
    15.     {
    16.      
    17.         rb2d = GetComponent<Rigidbody2D>();
    18.         moveLeft = false;
    19.         moveRight = false;
    20.     }
    21.  
    22.     // Update is called once per frame
    23.     void Update()
    24.     {
    25.         if (PlatformOS.IsMobileBrowser())
    26.         {
    27.             mobileMovement();
    28.             rb2d.velocity = new Vector2(movement, rb2d.velocity.y);
    29.         }
    30.         else
    31.         {
    32.            desktopMovement();
    33.        }
    34.  
    35.     }
    36.  
    37.     void desktopMovement()
    38.     {
    39.         movement = Input.GetAxis("Horizontal");
    40.         rb2d.velocity = new Vector2(movement * moveSpeed, rb2d.velocity.y);
    41.     }
    42.     void mobileMovement()
    43.     {
    44.         if (moveLeft)
    45.         {
    46.             movement = -moveSpeed;
    47.         }
    48.         else if (moveRight)
    49.         {
    50.             movement = moveSpeed;
    51.         }
    52.         else
    53.         {
    54.             movement = 0;
    55.         }
    56.      
    57.     }
    58.  
    59.     //settting up ui buttons movement
    60.     public void PointerDownLeft()
    61.     {
    62.         moveLeft = true;
    63.     }
    64.     public void PointerUpLeft()
    65.     {
    66.         moveLeft = false;
    67.     }
    68.     public void PointerDownRight()
    69.     {
    70.         moveRight = true;
    71.     }
    72.     public void PointerUpRight()
    73.     {
    74.         moveRight = false;
    75.     }
    76.  
    77. }
    78.  
    and the gameManager Object that handles the controlls
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.SceneManagement;
    5. using UnityEngine.UI;
    6.  
    7. public class SystemDetect : MonoBehaviour
    8. {
    9.     public GameObject mobileControls;
    10.     public GameObject portraitWarning;
    11.  
    12.     // Start is called before the first frame update
    13.     void Start()
    14.     {
    15.  
    16.     }
    17.     // Update is called once per frame
    18.     void Update()
    19.     {
    20.         if (PlatformOS.IsMobileBrowser())
    21.         {
    22.             if (Screen.orientation == ScreenOrientation.Portrait)
    23.             {
    24.                 portraitWarning.SetActive(true);
    25.             }
    26.             else if (Screen.orientation == ScreenOrientation.Landscape)
    27.             {
    28.                 portraitWarning.SetActive(false);
    29.             }
    30.  
    31.             Debug.Log("Mobile");
    32.             mobileControls.SetActive(true);
    33.         }
    34.         else
    35.         {
    36.             Debug.Log("webgl/windows");
    37.  
    38.         }
    39.  
    40.  
    41.     }
    42.     public void Play()
    43.     {
    44.         if (PlatformOS.IsMobileBrowser())
    45.         {
    46.             if (Screen.orientation == ScreenOrientation.Landscape)
    47.             {
    48.                 SceneManager.LoadScene("Menu");
    49.             }
    50.         }
    51.         else
    52.         {
    53.             SceneManager.LoadScene("Menu");
    54.         }
    55.  
    56.     }
    57.     public void ToggleFullScreen()
    58.     {
    59.         // Toggle fullscreen
    60.         Screen.fullScreen = !Screen.fullScreen;
    61.     }
    62. }
    63.  
     
  20. adamgolden

    adamgolden

    Joined:
    Jun 17, 2019
    Posts:
    1,494
    It might be a problem with orientation, not sure if that works on WebGL like it does for mobile platforms - you could try replacing this:
    Code (CSharp):
    1. if (Screen.orientation == ScreenOrientation.Portrait)
    2.             {
    3.                 portraitWarning.SetActive(true);
    4.             }
    5.             else if (Screen.orientation == ScreenOrientation.Landscape)
    6.             {
    7.                 portraitWarning.SetActive(false);
    8.             }
    With this:
    Code (CSharp):
    1. portraitWarning.SetActive(Screen.width < Screen.height);
    Also, you could throw Debug.Log statements around and check the javascript console to see what's going wrong.
     
  21. nbg_yalta

    nbg_yalta

    Joined:
    Oct 3, 2012
    Posts:
    378
    Does this mean that Application.isMobilePlatform returns correct value to detect if webgl app is loaded on mobile or PC, or there is still no built in method for this?
     
  22. Hypertectonic

    Hypertectonic

    Joined:
    Dec 16, 2016
    Posts:
    75
    For anyone still looking at this, I tested it and yes, it does appear Application.isMobilePlatform reports correctly while in WebGL. I wish Unity would put information like that in the docs.
     
  23. JayadevHaddadi

    JayadevHaddadi

    Joined:
    Nov 9, 2020
    Posts:
    12
    Enough with:

    Application.platform == RuntimePlatform.WebGLPlayer && Application.isMobilePlatform
     
    tantx, mashermack and AedanDaShaman like this.