docs.unity3d.com
Search Results for

    Show / Hide Table of Contents

    Use case: Track when users view annotation replies

    Before you start

    Before you track read receipts for annotations, ensure you have completed the following prerequisites:

    1. Project Access: Ensure you have the necessary permissions to access and update annotations in the target project.
    2. Understand Read Receipts: Read receipts track when a user last viewed the replies to an annotation thread, enabling "unread" indicators in your UI.
    3. Time Synchronization: Ensure your system time is accurate, as timestamps are used to determine which replies are unread.
    4. Set Up SDK Environment: Confirm that your Unity environment is correctly configured with the Collaboration SDK.
    5. User Context: The read receipt is associated with the authenticated user making the request.

    How do I...?

    Record when a user views annotation replies

    To track that a user has viewed an annotation's replies at a specific time, follow these steps:

    1. Prepare the Project Identifier: Ensure you have the correct project identifier (GUID) for the project containing the annotation.
    2. Prepare the Annotation Identifier: Ensure you have the correct annotation identifier (GUID) for the annotation thread.
    3. Capture the Timestamp: Record the exact time when the user viewed the replies. Use the current time if tracking a real-time view.
    4. Upsert the Read Receipt: Use the SDK to record the read receipt timestamp for the annotation.
    5. Update UI: Use this timestamp to determine which replies are "new" or "unread" in your user interface.

    Example:

    var projectId = new ProjectId("87cf845f-8ca7-4b2f-9cc1-c3d731335810");
    var annotationId = new AnnotationId("a1b2c3d4-e5f6-7890-abcd-ef1234567890");
    var annotationReference = new annotationReference(projectId, annotationId);
    
    // Record the current time as when the user viewed the replies
    var timestamp = DateTime.UtcNow;
    
    await annotationManagement.UpsertReadReceiptAsync(
        annotationReference,
        timestamp,
        cancellationToken);
    
    Debug.Log($"Read receipt recorded for annotation {annotationId} at {timestamp}");
    

    Mark an annotation thread as read when user opens it

    When a user opens an annotation thread in your UI, record the read receipt:

    public async Task OnAnnotationThreadOpened(ProjectId projectId, AnnotationId annotationId)
    {
        try
        {
            // Record that the user has now seen all replies up to this moment
            await annotationManagement.UpsertReadReceiptAsync(
                annotationReference,
                DateTime.UtcNow,
                cancellationToken);
    
            // Update your UI to reflect that all replies are now "read"
            UpdateUIReadStatus(annotationId, allRead: true);
        }
        catch (Exception ex)
        {
            Debug.LogError($"Failed to update read receipt: {ex.Message}");
        }
    }
    

    Determine which replies are unread

    Combine read receipts with annotation data to identify unread replies:

    // First, get the annotation with reply information
    var annotationResult = await annotationManagement.ReadAnnotationAsync(
        annotationReference,
        cancellationToken: cancellationToken);
    
    var annotation = annotationResult.Annotation;
    
    // Check if there are replies newer than the user's last read timestamp
    if (annotation.ReplyLastReadTimestamp.HasValue && annotation.LatestReply.HasValue)
    {
        if (annotation.LatestReply.Value > annotation.ReplyLastReadTimestamp.Value)
        {
            Debug.Log("This annotation has unread replies!");
    
            // Show unread indicator in UI
            int unreadCount = annotation.ReplyUnreadCount ?? 0;
            Debug.Log($"Unread replies count: {unreadCount}");
        }
        else
        {
            Debug.Log("All replies have been read.");
        }
    }
    
    // When user views the thread, update the read receipt
    await annotationManagement.UpsertReadReceiptAsync(
        annotationReference,
        DateTime.UtcNow,
        cancellationToken);
    

    Record read receipt with specific historical timestamp

    If you need to record that replies were read at a specific point in the past:

    var projectId = new ProjectId("87cf845f-8ca7-4b2f-9cc1-c3d731335810");
    var annotationId = new AnnotationId("a1b2c3d4-e5f6-7890-abcd-ef1234567890");
    var annotationReference = new annotationReference(projectId, annotationId);
    
    // Record that the user viewed replies at a specific historical time
    var historicalTimestamp = new DateTime(2024, 3, 15, 14, 30, 0, DateTimeKind.Utc);
    
    await annotationManagement.UpsertReadReceiptAsync(
        annotationReference,
        historicalTimestamp,
        cancellationToken);
    

    Understanding read receipts

    Read receipts enable "unread" functionality in annotation threads:

    • Per-User Tracking: Each user has their own read receipt timestamp for each annotation thread
    • Upsert Operation: Calling this method creates a new read receipt if none exists, or updates the existing one
    • UTC Timestamps: Always use UTC timestamps for consistency across time zones
    • Automatic Calculation: The server automatically calculates unread counts based on reply timestamps versus read receipt timestamps
    • UI Integration: Use the ReplyLastReadTimestamp and ReplyUnreadCount properties from annotation data to build unread indicators

    Best practices

    1. Record on View: Update read receipts when users actually view the thread, not when they receive notifications
    2. Use Current Time: In most cases, use DateTime.UtcNow when recording real-time views
    3. Handle Offline: Queue read receipt updates when offline and sync when connection is restored
    4. Batch Updates: If updating multiple read receipts, consider batching the operations
    5. Error Handling: Handle errors gracefully as read receipt updates should not block the user experience

    For related annotation operations, see documentation on finding replies to an annotation and reading annotations.

    See the API documentation for more details on the UpsertReadReceiptAsync method.

    In This Article
    Back to top
    Copyright © 2026 Unity Technologies — Trademarks and terms of use
    • Legal
    • Privacy Policy
    • Cookie Policy
    • Do Not Sell or Share My Personal Information
    • Your Privacy Choices (Cookie Settings)