Is there any way that unity notifies a C# script if the user resizes a window in the browser (and thus, the rendering area that Unity uses has been modified).
I want the GUI to resize as well, so I need to know when to update the Rects.
I though of having a class that stores the last width and height of the screen, and when they change, throw an event, but I was wondering if theres something like that in Unity already.
Unity doesn’t get notified automatically of window size changes. However, if you can detect the change with some browser JavaScript in the page, you can call a function in the Unity player. Check out this manual page about communication between the web player and the browser.
I had the same problem, I was trying to create a level that could be resized and I wanted some box coliders to be my boundaries and for that they should be always placed just outside the Screen.
This code did the job to me:
public class LevelBoundaries : MonoBehaviour
{
Vector3 initialVectorBottomLeft;
Vector3 initialVectorTopRight;
Vector3 UpdatedVectorBottomLeft;
Vector3 UpdatedVectorTopRight;
void Start()
{
MainCamera = GameObject.Find("Main Camera");
initialVectorBottomLeft = MainCamera.camera.ScreenToWorldPoint(new Vector3(0, 0, 30));
initialVectorTopRight = MainCamera.camera.ScreenToWorldPoint(new Vector3(Screen.width, Screen.height, 30)); // I used 30 as my camera z is -30
}
void Update()
{
UpdatedVectorBottomLeft = MainCamera.camera.ScreenToWorldPoint(new Vector3(0, 0, 30));
UpdatedVectorTopRight = MainCamera.camera.ScreenToWorldPoint(new Vector3(Screen.width, Screen.height, 30));
if ((initialVectorBottomLeft != UpdatedVectorBottomLeft) || (initialVectorTopRight != UpdatedVectorTopRight))
{
Debug.Log("Screen Size has changed")'
}
}
I hope it helps as it took me a while to figure it out.
This is a pretty basic request, there should be some definitive answer on this. For example, let’s take windows standalone… user is using the app and decides to resize the app window; what now? How do I know the resize occurred and how do I respond to it so that I can implement the necessary adjustments at runtime?
using System.Collections.Generic;
public class SimpleDetector : Monobehaviour {
public float lastScreenWidth = 0f;
void Start(){
lastScreenWidth = Screen.width;
}
void Update(){
if( lastScreenWidth != Screen.width ){
lastScreenWidth = Screen.width;
StartCoroutine("AdjustScale");
}
}
IEnumerator AdjustScale(){
// set up the other scene params.
}
}
All the solutions you guys have posted are “correct”, in that they will compile and run. I try to avoid any Update() calls I can though. Regardless of whether or not the script has to scale the GUI every update, it still needs to check to see if it needs to, which is almost as bad. It seems like there could be something more elegant and efficient out there.
Since any screen resizing would ultimately be the result of some sort of mouse clicking or dragging, maybe triggering the scale adjustment via a mouse event in OnGUI() would be less taxing?
So, it’s become clear to me that the web player is the only one that actually can be resized. Why is this? Shouldn’t we be able to resize standalone builds just like you can resize the editor window? This would be a nice feature
@scone : Maybe its restricted by default to spare that kind of questions for developers precisely. I don’t know if you can make a standalone resizable though.
@kei_kvaartz : Checking the screen resolution in every frame seems the only solution to me ; trying to do it using the mouse is not reliable since you can probably change the window size by other means using system keyboard shortcuts. I think you can reduce the Update calls overhead by having a single Update() which calls every component that needs to do something on Update (I found this idea on this forum once). But it depends on Unity’s internal architecture and that’s probably something we don’t want to mess with if we can avoid it.
On the cost point of view, this test (comparing the windows dimensions to those of the previous frame) seems quite cheap to me. I mean, one frame is drawn every 20ms typically and modern computers can do a lot more things in 20ms than comparing 4 integers so it should be OK.
AFAIK you can’t. I’m sure that this is, in fact the reason, but I wonder if there is some kind of switch in DirectX or OpenGL for a non-resizable window that has some kind of performance boost. Either way, I would argue that extensibility is always better than fixed features, so how about a flag and an onResize event?
Why can’t unity just fire an windowresize or window resolution changed event? It is trival to add and saves us tons of headache and these cpu wasting “hacks”.
I agree that there still needs to be an OnWindowResized event available especially for resizing GUI elements as the GUI.Layout method rather seems to be a poor implementation using non-relative screen resolution parameters.
Unity provides resizable standalone applications. Go to your projects Build Settings and press the Player Settings… button. It will then bring up more options within the Inspector panel. Then look at Resolutions and Presentation => Standalone Player Options. There is a checkbox for Resizable Window.
I think the hack to check if Screen.width was changed is the best possible solution CPU wise. It might not be as elegant as a OnScreenResize event, but thats not such a problem. In any case whether OpenGL which has such an event, or Unity will add it to the monobehaviour arsental, In the end, that hack is still going to run on the CPU, there is no way around it.
I think this code achieves fairly efficient CPU usage, and readable too. calculate_rects() is the function I want to do each time A resize happens, however I dont want to check for a resize event every Update, or even FixedUpdate. So I add a coroutine that checks for a resize of width or height of the screen once every 0.3 seconds. Thats is fairly reasonable. And just to be sure that the coroutine exits if it is unecessary anymore, I change the bool stay to false in the OnDestroy() event. As a result the coroutine that activates calc_rects() if screen was resized every 0.3f seconds. And once the object to which this script attached to is destroyed. The coroutine is guaranteed to exit.
*Note. If you have multiple instances of this script, then you will have multiple instances of this coroutine running, if you dont want that effect, make it a static singleton of something like that, or just call me and I’ll show you how.
*Note. that OnGUI() will be called twice per frame if you dont do useGUILayout = false; at the start function. If you dont plan to use layouts, then deactivating that bool will activate OnGUI() only once per frame.
*Note. the last Note doesn’t really have anything to do with this thread, but its nice to know, since we care so much about our CPUs, no really, We care about our CPU more then we care about the women that would be angry at us if they read this
i dont know if there is a better option, but here is my solution for now, needs unity’s ugui. i used unity’s uibehaviour and the event onrecttransformdimentionschange event. i need to add this script to some gameobject using recttransform system.
using UnityEngine.UI;
using UnityEngine.Events;
using UnityEngine.EventSystems;
public delegate void OnWindowResize();
public class WindowChange : UIBehaviour{
public static WindowChange instance = null;
public OnWindowResize windowResizeEvent;
void Awake() {
instance = this;
}
protected override void OnRectTransformDimensionsChange ()
{
base.OnRectTransformDimensionsChange ();
if(windowResizeEvent != null)
windowResizeEvent();
}
}