I have made a subclass of button that overrides Button, following the advice in the docs for how to make cursor locking in WebGL work. I made a subclass, but I’m at a loss as to how to place it within the UI. I know how to use the editor to make a canvas and I can put buttons on it and so on. But how to I make my subclassed button show up in the editor? Or is that even the way? I suspect this is one of those things so obvious it doesn’t get mentioned, so I’m prepared to be embarrassed! Thanks for any pointers.
I’m using Unity 2022.1.14.f1
This is the code of my subclass:
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class CursorCaptureButton : Button
{
public override void OnPointerDown(PointerEventData eventData)
{
base.OnPointerDown(eventData);
Cursor.lockState = CursorLockMode.Locked;
}
}
I also tried some other things, like this above the class declaration:
namespace UnityEngine.UI
{
[AddComponentMenu("UI/CaptureButton", 30)]
But I’m just shooting blind. I hope someone here can explain to me what I’m supposed to do.
Like any other component in Unity, you either drag and drop the script onto a GameObject, or you press Add Component in the inspector and add it there.
That being said - I wouldn’t recommend overriding the Button class for the use case you have here. Just make a regular MonoBehaviour script alongside the Button component and hook up the function call in the inspector.
Thanks for the suggestion. That was actually what I tried before, and I agree it would be preferable. Unfortunately, the behavior doesn’t work correctly in the MonoBehavior because (from the Unity docs):
"Unfortunately, Unity does not have separate event and rendering loops, so it defers event handling to a point where the browser no longer acknowledges a full-screen or cursor lock request issued from Unity scripting as a direct response to the event which triggered it. As a result, Unity triggers the request on the next user-initiated event, rather than the event that triggered the cursor lock or full-scree request.
To make this work with acceptable results, you should trigger cursor locking or full-screen requests on mouse/key down events, instead of mouse/key up events. This ensures that when the request is deferred to the next user-initiated event, it is triggered when the user releases the mouse or key.
Use Unity’s UI.Button component to achieve the desired behaviour by creating a subclass of Button, which overrides the OnPointerDown method."
So the docs recommend using a Button subclass. But they don’t explain how you actually incorporate a subclass of a UI element into a Scene. I did try dragging and dropping it onto the Canvas, but then it tries to add it as a script.
There’s some way of adding things to the menu, I guess, though I couldn’t figure it out, and everything I found may have been too old. I’m not to keen on this depending on some editor customization anyway (but I don’t know anything about editor customization, so maybe it isn’t what I think). I’ll only use this one time in any given project, I imagine. But it seems unavoidable for WebGL.
You seem to be a little confused about what a Button actually is and what the menu item to create a button in Unity actually does. A button you get from the GameObject → UI → Button menu is simply a GameObject with a Button component attached to it, an Image component, and a child object with a Text component.
You can certainly make your own menu item to create a GameObject and add your custom component to it, but that’s not necessary at all. You can just create a Button as normal, remove the existing Button component, and add your custom one. You’re overthinking this.
1 Like
Thank you @PraetorBlue !! That was EXACTLY my point of confusion. I did what you said, and now I have my Button subclass working in the scene. (Now I can get back to trying to make the cursor capture behavior right in WebGL, which is another matter.)
I’d like to mark the reply as an “answer” or something equivalent, but I don’t see any way to do that. Is there something I’m supposed to do?
1 Like
I believe you can edit your original post tags or something along that nature to mark it as Resolved.