Skip to content

Latest commit

 

History

History
330 lines (235 loc) · 8.51 KB

File metadata and controls

330 lines (235 loc) · 8.51 KB

Troubleshooting

Common issues and their solutions.

Table of Contents


Data Not Showing in UiPresenter

Symptoms: UI opens but data fields are empty or show default values.

Cause 1: Not Using Generic Open Method

// ❌ WRONG - Data not passed
await _uiService.OpenUiAsync<PlayerProfile>();

// ✅ CORRECT - Use generic overload with data
var data = new PlayerData { Name = "Hero", Level = 10 };
await _uiService.OpenUiAsync<PlayerProfile, PlayerData>(data);

Cause 2: OnSetData Not Implemented

public class PlayerProfile : UiPresenter<PlayerData>
{
    // ❌ MISSING - Must override OnSetData
    
    // ✅ CORRECT
    protected override void OnSetData()
    {
        nameText.text = Data.Name;
        levelText.text = Data.Level.ToString();
    }
}

Cause 3: Wrong Base Class

// ❌ WRONG - Missing <T> generic
public class PlayerProfile : UiPresenter

// ✅ CORRECT
public class PlayerProfile : UiPresenter<PlayerData>

Animations Not Playing

Symptoms: UI with AnimationDelayFeature opens/closes instantly without animation.

Cause 1: Feature Component Not Attached

// ❌ MISSING - No feature component
public class AnimatedPopup : UiPresenter
{
}

// ✅ CORRECT - Require and reference the feature
[RequireComponent(typeof(AnimationDelayFeature))]
public class AnimatedPopup : UiPresenter
{
    [SerializeField] private AnimationDelayFeature _animationFeature;
}

Cause 2: Animation Clips Not Assigned

Check in the Inspector:

  • Animation Component is assigned
  • Intro Animation Clip is assigned
  • Outro Animation Clip is assigned

Alternative: Use TimeDelayFeature for simple delays without animation:

[RequireComponent(typeof(TimeDelayFeature))]
public class SimpleDelayedPopup : UiPresenter
{
    [SerializeField] private TimeDelayFeature _delayFeature;
    // Configure delay times in Inspector
}

Cause 3: Animation Component Missing

AnimationDelayFeature requires an Animation component on the GameObject.

  1. Add an Animation component to the presenter GameObject
  2. Or use Animator with AnimationClip assets

UiConfig Not Added Error

Error: KeyNotFoundException: The UiConfig of type X was not added to the service

Cause: The UI type is not registered in your UiConfigs asset.

Solution

  1. Open your UiConfigs ScriptableObject asset
  2. Add a new entry for your presenter type:
    • Type: Select your presenter class
    • Addressable Address: Set the Addressable key (e.g., UI/MyPresenter)
    • Layer: Set the depth layer number
  3. Save the asset

Verification:

// In UiConfigs inspector:
// Type: MyNewPresenter
// Addressable: Assets/UI/MyNewPresenter.prefab
// Layer: 2

UI Flickers on Open

Symptoms: UI briefly appears at wrong position or state before proper display.

Cause: Prefab's root GameObject is active during initialization.

Solution

  1. Open your UI prefab
  2. Disable the root GameObject (uncheck the checkbox at top of Inspector)
  3. Save the prefab

The UI Service will enable it when ready to display.

Note: If creating UI dynamically:

var go = Instantiate(prefab);
go.SetActive(false); // Ensure disabled
_uiService.AddUi(go.GetComponent<UiPresenter>(), layer: 3, openAfter: true);

Cancellation Not Working

Symptoms: CancellationToken doesn't stop UI loading.

Cause 1: Token Not Passed

// ❌ WRONG - Token not used
await _uiService.OpenUiAsync<Shop>();

// ✅ CORRECT - Pass the token
var cts = new CancellationTokenSource();
await _uiService.OpenUiAsync<Shop>(cancellationToken: cts.Token);

Cause 2: Cancelling Too Late

Cancellation only works during the async load phase:

var cts = new CancellationTokenSource();

// Start loading
var task = _uiService.OpenUiAsync<Shop>(cts.Token);

// Cancel BEFORE await completes
cts.Cancel(); // ✅ Works if still loading

await task; // Already complete
cts.Cancel(); // ❌ Too late - no effect

Cause 3: Not Handling the Exception

var cts = new CancellationTokenSource();

try
{
    await _uiService.OpenUiAsync<Shop>(cts.Token);
}
catch (OperationCanceledException)
{
    // ✅ Handle cancellation
    Debug.Log("Loading was cancelled");
}

Backdrop Blur Does Nothing

Symptom: A presenter has UiBackdropBlurPresenterFeature attached, it opens normally, and nothing behind it is blurred. No error, warning, or log line appears.

Cause: UiBackdropBlurRendererFeature has not been added to the project's active URP Renderer asset. The presenter-side component only registers a request; the renderer feature is what actually renders the blur, and without it the request has no consumer.

Solution

  1. Select your Universal Renderer asset — not the Pipeline asset. In this repo that's Assets/Settings/URP-Mobile_Renderer.asset; the Pipeline asset (URP-Mobile.asset) is the one that points at it.
  2. Click Add Renderer FeatureUi Backdrop Blur Feature.
  3. Confirm the Shader field is populated (it auto-fills in the Editor; assign Runtime/Rendering/Shaders/UiBackdropBlur.shader if empty).

Verification: the renderer asset's m_RendererFeatures list is no longer [].

If it still does nothing, the per-camera gate is rejecting the camera. The blur deliberately skips:

Camera Why
Scene view / material preview Would blur the Editor's own views
A UiCameraStackFeature overlay camera Would blur the stacked UI, not the world behind it
A camera with a RenderTexture target Would blur the UI being captured

So a presenter that combines the blur with camera stacking on the same camera will never show it — that pairing is rejected by design. Also note one renderer feature covers only the cameras using that renderer; with multiple renderers, add it to each.

See URP Rendering Features for the full gating rules.


Common Mistakes

Opening Same UI Multiple Times

// ❌ BAD - Can open duplicates
void Update()
{
    if (Input.GetKeyDown(KeyCode.I))
        _uiService.OpenUiAsync<Inventory>().Forget();
}

// ✅ GOOD - Check visibility first
void Update()
{
    if (Input.GetKeyDown(KeyCode.I) && !_uiService.IsVisible<Inventory>())
        _uiService.OpenUiAsync<Inventory>().Forget();
}

Forgetting to Initialize

// ❌ WRONG - Service not initialized
private IUiServiceInit _uiService = new UiService();

async void Start()
{
    await _uiService.OpenUiAsync<Menu>(); // Throws!
}

// ✅ CORRECT - Call Init first
void Start()
{
    _uiService = new UiService();
    _uiService.Init(_uiConfigs);
}

Not Disposing

// ❌ WRONG - Memory leak
void OnDestroy()
{
    // Service still holds references
}

// ✅ CORRECT - Clean up
void OnDestroy()
{
    _uiService?.Dispose();
}

Getting Help

Before Reporting

  1. Check Unity Console - Look for warnings/errors from UiService
  2. Verify Dependencies - Ensure UniTask and Addressables are installed correctly
  3. Review CHANGELOG - Check if recent version introduced breaking changes
  4. Search Issues - Your issue may already be reported on GitHub

Reporting a Bug

Create an issue at GitHub Issues with:

  • Unity version (e.g., 6000.0.5f1)
  • Package version (from package.json)
  • Code sample reproducing the issue
  • Error logs (full stack trace)
  • Steps to reproduce

Feature Requests

Use GitHub Discussions to:

  • Suggest new features
  • Ask questions
  • Share how you're using the package

Debug Checklist

When something isn't working, check these in order:

  • UI Service is initialized with Init(uiConfigs)
  • Presenter type is registered in UiConfigs
  • Prefab is marked as Addressable
  • Addressable address matches UiConfigs entry
  • Prefab root GameObject is disabled
  • UniTask and Addressables packages are installed
  • No compilation errors in project
  • Feature components (if any) are attached and configured