Skip to content

Conversation

@bitsandfoxes
Copy link
Contributor

@bitsandfoxes bitsandfoxes commented Jun 26, 2025

Fixes #928

Note: I've updated the prefab to include the logo on the top right. See the updated screenshot on Android.

Goal

The idea is to provide users a simple to use prefab to add to their game to allow players to provide user feedback. This is a first iteration and the things we're looking to have added to the feedback is:

  • Name (optional)
  • Email (optional)
  • A message - i.e. feedback (required)
  • Screenshot (optional)

Implementation Details

A prefab that holds a GameObject with a scaling canvas that can be dropped into any scene.
The prefab consists of two parts:

  1. The button to pop up the form
  2. The form to submit the feedback
Screenshot 2025-06-27 at 13 18 46

One Prefab

Button and form are part of the same prefab. It make little sense to provide them separately to customize them. The button would need to be provided with the form prefab, making this a customization. So you'd always end up with changes to both anyway.
Attempting to pass this (or parts of it) into the editor configuration window would counter the Unity workflow of adding prefabs to scenes that are support to have the feedback.

One MonoBehaviour that's shipped as .cs

Since we're providing a prefab to be dragged into scenes and we expect users to customize them, the accompanying MonoBehaviour should be as accessible as possible. We're providing it as a heavily commented "raw" .cs file that is getting compiled with the game.
This also allows us not to take on UnityEngine.UI as a dependency for the Unity SDK.

Custom Inspector

We're providing the SentryUserFeedbackMonoBehaviour it's own custom inspector to highlight broken or missing references

Screenshot 2025-06-27 at 13 19 07
  • Missing optional fields are getting highlighted in yellow.
  • Missing required fields are getting highlighted in red.

How to allow for customization

The prefab can be dragged anywhere into the /Assets allowing for the creation of a prefab variant. This variant "inherits" from the original and all values that have not been explicitly changed will get updated.
The form is controlled by a VertialLayoutGroup which allows for optional inputs (i.e. name, email) to be dropped while retaining the layout.

Adding to the scene

Adding the User Feedback to the scene can be done via drag&drop:

Addition.mov

The Feature in Action

Clicking the megaphone button pops up the form to submit user feedback.

Screen.Recording.2025-06-27.at.13.13.54.mov

Since the canvas scales with the screen, this works on a wide range of displays and resolutions, i.e. mobile

Screenshot 2025-06-27 at 13 18 08

When submitting the report we're delaying to send it to the EndOfFrame so the screenshot does not contain the form.

Screenshot 2025-06-27 at 13 18 08

@github-actions
Copy link
Contributor

github-actions bot commented Jun 26, 2025

Fails
🚫 Please consider adding a changelog entry for the next release.
Messages
📖 Do not forget to update Sentry-docs with your feature once the pull request gets approved.

Instructions and example for changelog

Please add an entry to CHANGELOG.md to the "Unreleased" section. Make sure the entry includes this PR's number.

Example:

## Unreleased

- User Feedback ([#2220](https://github.com/getsentry/sentry-unity/pull/2220))

If none of the above apply, you can opt out of this check by adding #skip-changelog to the PR description.

Generated by 🚫 dangerJS against b6f5ff5

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved this out of the ScreenshotEventProcessor to be reused by CaptureUserFeedback as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added the UserFeedback to the scene

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the custom inspector for the SentryUserFeedback MonoBehaviour that we're providing as .cs.

using System;
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could have this MonoBehaviour as part of the SDK and ship it precompiled. But there are a couple for downsides

  1. The SDK would need to take on an additional dependency on UnityEngine.UI. This is not part of the ManagedPath/UnityEngine but lives somewhere in /ProjectPath/Library instead. We'd need create some workaround like we do for the testrunner.
  2. Users can't inspect the .cs in the Editor.
  3. The workflow of Embed&Change would not work that way

[SerializeField] private InputField _message;
[SerializeField] private Toggle _addScreenshot;

private void Awake()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The checks here go to the console and not the SDK logger and all have this as context. This allows us to

  • Warn right in the Editor
  • Clicking on the log highlights the GameObject in the Hierarchy
  • The custom inspector highlights any missing references

@bitsandfoxes bitsandfoxes marked this pull request as ready for review June 27, 2025 12:23
@bruno-garcia
Copy link
Member

@sentry review

@seer-by-sentry
Copy link

On it! We are reviewing the PR and will provide feedback shortly.

@seer-by-sentry
Copy link

PR Description

This pull request introduces a user feedback mechanism to the Sentry Unity SDK. The goal is to allow users to easily submit bug reports and feedback directly from within the application, including optional screenshots, to provide more context for debugging and issue resolution.

Click to see more

Key Technical Changes

  1. New SentryUserFeedback MonoBehaviour: This component provides the UI and logic for the feedback form, including input fields for name, email, and message, as well as a toggle for attaching a screenshot.
  2. Editor Integration: A custom editor (SentryUserFeedbackEditor.cs) is added to improve the inspector experience for the SentryUserFeedback component, providing visual cues for missing required references.
  3. SentryScreenshotUtility Class: This utility class encapsulates the screenshot capture logic, including resizing and handling platform-specific mirroring issues. It replaces the previous screenshot capture logic within ScreenshotEventProcessor.
  4. CaptureFeedback Method in SentryUnitySDK: This method handles the actual capture and submission of the user feedback to Sentry, including attaching the screenshot if requested.
  5. Modified ScreenshotEventProcessor: The screenshot capture logic is removed and replaced with a call to the new SentryScreenshotUtility.Capture method.

Architecture Decisions

The user feedback functionality is implemented as a self-contained MonoBehaviour with a corresponding editor script. This allows developers to easily integrate the feedback form into their existing UI. The screenshot capture logic is extracted into a separate utility class to promote code reuse and maintainability. The prefab is set up to use Unity's UI system, ensuring cross-platform compatibility.

Dependencies and Interactions

This feature depends on the UnityEngine.UI package for the UI elements. It interacts with the core Sentry SDK to submit the feedback data and attachments. The SentryUnityOptions class is used to configure screenshot quality and compression settings. It also interacts with SentrySystemInfoAdapter to determine if the graphics UV is flipped.

Risk Considerations

  1. Performance: Capturing screenshots can be a performance-intensive operation, especially on low-end devices. The screenshot quality and compression settings should be carefully configured to balance image quality and performance.
  2. UI Integration: The provided UI is a basic implementation and may require customization to fit the specific look and feel of different applications. Ensure the UI is responsive and accessible.
  3. Memory Management: Proper disposal of Unity objects (Textures, RenderTextures) is crucial to prevent memory leaks. The SentryScreenshotUtility.Capture method has been updated to include a try-finally block to ensure proper disposal.
  4. Input Validation: The CaptureFeedback method in SentryUnitySDK includes basic input validation and sanitization, but additional validation may be required to prevent malicious input.

Notable Implementation Details

The SentryScreenshotUtility.Capture method now uses a try-finally block to ensure that temporary RenderTextures and the Texture2D are always released, preventing potential memory leaks. The CaptureFeedback method in SentryUnitySDK now includes basic input validation and sanitization to prevent issues with long messages or invalid email formats. The SentryUserFeedback MonoBehaviour now includes null checks to prevent null reference exceptions if components are missing.

Comment on lines 43 to 46
}
else
{
hint.AddAttachment(CaptureScreenshot(Screen.width, Screen.height), "screenshot.jpg", contentType: "image/jpeg");
hint.AddAttachment(SentryScreenshotUtility.Capture(_options), "screenshot.jpg", contentType: "image/jpeg");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The refactoring looks good, but the method call should include error handling in case screenshot capture fails.

Suggested change
}
else
{
hint.AddAttachment(CaptureScreenshot(Screen.width, Screen.height), "screenshot.jpg", contentType: "image/jpeg");
hint.AddAttachment(SentryScreenshotUtility.Capture(_options), "screenshot.jpg", contentType: "image/jpeg");
else
{
try
{
hint.AddAttachment(SentryScreenshotUtility.Capture(_options), "screenshot.jpg", contentType: "image/jpeg");
}
catch (System.Exception ex)
{
_options.DiagnosticLogger?.LogError("Failed to capture screenshot: {0}", ex, ex.Message);
}
}

/// <summary>
/// Captures a User Feedback
/// </summary>
public static void CaptureFeedback(string message, string? email, string? name, bool addScreenshot) =>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm this is odd that we add an API here because it creates further confusion between SentrySdk vs SentryUnity. Both will have CaptureFeedback from the SentrySdk and get the screenshot taken before calling it and doing s => s.AddAttachment?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also not totally against adding this here, just sayijng it's not ideal

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the .NET SDK one should be hidden along with its Init.
Add a screenshot to the feedback should not require to either

  1. Implement their own screenshot capture to pass it in as attachment
  2. The SDK to make the screenshot capture publicly accessible
  3. Having to write code like this
SentryHint.WithAttachments(
    new SentryAttachment(
        AttachmentType.Default,
        new ByteAttachmentContent(SentryScreenshotUtility.Capture(_options)),
        "screenshot.jpg",
        "image/jpeg"))

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the .NET SDK one should be hidden along with its Init.

How do you capture events? It'll be on SentrySdk, right? some stuff on one, some on another

_feedbackForm.SetActive(false);

// We're waiting for the EndOfFrame so the FeedbackForm gets updated before capturing the screenshot
yield return new WaitForEndOfFrame();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

Comment on lines +26 to +32
// save event id
// wait for end of frame
// check if last id is event it
// send screenshot

// add workitem: screentshot for ID xxx
// sdk integration checking for work: if ID got sent, follow up with screenshot
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needs to be cleaned up?

/// <summary>
/// Captures a User Feedback
/// </summary>
public static void CaptureFeedback(string message, string? email, string? name, bool addScreenshot) =>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the .NET SDK one should be hidden along with its Init.

How do you capture events? It'll be on SentrySdk, right? some stuff on one, some on another

@bitsandfoxes bitsandfoxes merged commit 8cdc3b1 into main Jul 2, 2025
142 of 144 checks passed
@bitsandfoxes bitsandfoxes deleted the feat/feedback branch July 2, 2025 12:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

User Feedback Widget through Prefab

4 participants