虚幻引擎 SDK - 数据隐私

文件

遵守数据隐私法

通过通知 Singular 用户同意 GDPR、CCPA 和其他消费者隐私法规的选择,实施符合隐私法规的数据收集。

当用户同意或拒绝与第三方共享其信息时,使用 Singular 的隐私方法来传达他们的选择。这将确保遵守《加州消费者隐私法案》(CCPA)等法规,并使合作伙伴尊重用户的隐私偏好。

了解更多信息:有关Singular如何处理隐私同意的详细信息,请参阅用户隐私和限制数据共享


限制数据共享

控制第三方数据共享

通知Singular用户是否同意使用LimitDataSharing方法与第三方合作伙伴共享个人数据。

方法签名

static void LimitDataSharing(bool shouldLimitDataSharing)

参数

  • false:用户已选择并同意共享其数据
  • true: true:用户已退出,不同意共享其数据

重要:虽然此方法是可选的,但它会影响属性数据的共享。一些合作伙伴只有在明确通知用户已选择加入时,才会共享完整的归因信息。

使用示例

C++
// User has opted in to share their data
void AYourGameMode::OnUserOptedInToDataSharing()
{
    USingularSDKBPLibrary::LimitDataSharing(false);
    UE_LOG(LogTemp, Log, TEXT("Data sharing enabled"));
}

// User has opted out and declined to share their data
void AYourGameMode::OnUserOptedOutOfDataSharing()
{
    USingularSDKBPLibrary::LimitDataSharing(true);
    UE_LOG(LogTemp, Log, TEXT("Data sharing limited"));
}

// Example: Set based on user preference
void AYourGameMode::HandlePrivacyConsent(bool bUserConsented)
{
    // Pass inverse: false = opted in, true = opted out
    USingularSDKBPLibrary::LimitDataSharing(!bUserConsented);

    UE_LOG(LogTemp, Log, TEXT("Data sharing: %s"), 
           bUserConsented ? TEXT("Enabled") : TEXT("Limited"));
}

如何使用

Singular 在用户隐私回邮中使用此设置,并将其传递给需要遵守法规的合作伙伴。


GDPR 合规方法

管理用户跟踪同意和控制SDK功能,以符合GDPR(通用数据保护条例)和其他隐私法规。

跟踪同意管理

跟踪同意

通过向 Singular 服务器发送 GDPR 选入事件,记录用户对跟踪的明确同意。

方法签名

static void TrackingOptIn()

何时使用

  • GDPR 合规性:当用户明确同意在受 GDPR 监管的地区进行跟踪时调用
  • 同意记录:在 Singular 系统中将用户标记为已提供 GDPR 同意
  • 默认行为:如果没有此调用,SDK 会继续跟踪,但不会明确记录同意信息
C++
// User accepted tracking consent
void AGDPRManager::OnUserAcceptedTracking()
{
    USingularSDKBPLibrary::TrackingOptIn();
    UE_LOG(LogTemp, Log, TEXT("User opted in to tracking"));
}

// Example: Call after consent dialog
void AGDPRManager::ShowGDPRConsentDialog()
{
    // Your consent dialog UI logic here
    // ...

    // If user accepts:
    OnUserAcceptedTracking();
}

跟踪控制方法

停止所有跟踪

完全禁用当前用户在此设备上的所有 SDK 跟踪活动。

方法签名

static void StopAllTracking()

严重警告:此方法会永久禁用 SDK,直到调用ResumeAllTracking() 。禁用状态会在应用程序重启时持续存在,只能通过编程方式逆转。

行为

  • 立即生效:立即停止所有跟踪、事件报告和数据收集功能
  • 持续状态:即使在应用程序关闭和重新打开后也会保持禁用状态
  • 无法自动重置:必须明确调用ResumeAllTracking() 才能重新启用
C++
// User declined all tracking
void ATrackingController::OnUserDeclinedTracking()
{
    USingularSDKBPLibrary::StopAllTracking();
    UE_LOG(LogTemp, Log, TEXT("All tracking stopped"));

    // Optionally store preference
    SaveBoolToConfig(TEXT("tracking_enabled"), false);
}

// Example: Handle user opt-out from settings menu
void ATrackingController::HandlePrivacySettingsChange(bool bTrackingEnabled)
{
    if (!bTrackingEnabled)
    {
        USingularSDKBPLibrary::StopAllTracking();
        UE_LOG(LogTemp, Log, TEXT("Privacy settings: Tracking disabled"));
    }
}

恢复所有跟踪

在使用StopAllTracking() 停止跟踪后重新启用跟踪。

方法签名

static void ResumeAllTracking()

使用案例

  • 同意更改:用户更改隐私偏好并选择恢复跟踪
  • 隐私设置:用户通过应用程序设置菜单更新同意
  • 地区合规性:当用户转移到非监管区域时重新启用跟踪功能
C++
// User opted back in to tracking
void ATrackingController::OnUserResumedTracking()
{
    USingularSDKBPLibrary::ResumeAllTracking();
    UE_LOG(LogTemp, Log, TEXT("Tracking resumed"));

    // Optionally update stored preference
    SaveBoolToConfig(TEXT("tracking_enabled"), true);
}

// Example: Handle consent update from settings
void ATrackingController::HandlePrivacySettingsChange(bool bTrackingEnabled)
{
    if (bTrackingEnabled)
    {
        USingularSDKBPLibrary::ResumeAllTracking();
        UE_LOG(LogTemp, Log, TEXT("Privacy settings: Tracking enabled"));
    }
}

IsAllTrackingStopped

检查当前用户是否已禁用跟踪功能。

方法签名

static bool IsAllTrackingStopped()

返回 返回 返回 返回值值值值

  • true:当前已通过StopAllTracking()停止跟踪
  • false:跟踪处于活动状态(从未停止或恢复
C++
// Check current tracking status on startup
void APrivacySettingsUI::BeginPlay()
{
    Super::BeginPlay();
    UpdatePrivacyUI();
}

// Check current tracking status
bool APrivacySettingsUI::IsTrackingEnabled()
{
    return !USingularSDKBPLibrary::IsAllTrackingStopped();
}

// Example: Display privacy status in settings
FString APrivacySettingsUI::GetPrivacyStatusText()
{
    if (USingularSDKBPLibrary::IsAllTrackingStopped())
    {
        return TEXT("Tracking: Disabled");
    }
    else
    {
        return TEXT("Tracking: Enabled");
    }
}

// Example: Sync UI with tracking state
void APrivacySettingsUI::UpdatePrivacyUI()
{
    bool bIsStopped = USingularSDKBPLibrary::IsAllTrackingStopped();

    if (TrackingToggle != nullptr)
    {
        TrackingToggle->SetIsChecked(!bIsStopped);
    }

    if (StatusText != nullptr)
    {
        FString StatusString = bIsStopped ? TEXT("Stopped") : TEXT("Active");
        StatusText->SetText(FText::FromString(
            FString::Printf(TEXT("Current tracking state: %s"), *StatusString)
        ));
    }

    UE_LOG(LogTemp, Log, TEXT("Current tracking state: %s"), 
           bIsStopped ? TEXT("Stopped") : TEXT("Active"));
}

// Handle toggle change from UI
void APrivacySettingsUI::OnTrackingToggleChanged(bool bEnabled)
{
    if (bEnabled)
    {
        USingularSDKBPLibrary::ResumeAllTracking();
    }
    else
    {
        USingularSDKBPLibrary::StopAllTracking();
    }

    UpdatePrivacyUI();
}

儿童隐私保护

13 岁以下用户跟踪

通知 Singular 用户未满 13 周岁,以遵守 COPPA(儿童在线隐私保护法案)和其他儿童隐私法规。

方法签名

static void TrackingUnder13()

合规要求

  • COPPA 合规性:收集美国 13 岁以下儿童数据的应用程序必须遵守
  • 有年龄限制的内容:当用户在注册或年龄验证时表明自己未满 13 岁时使用
  • 限制跟踪:限制数据收集,以遵守儿童隐私保护法
C++
// User identified as under 13
void ACOPPAManager::OnUserUnder13()
{
    USingularSDKBPLibrary::TrackingUnder13();
    UE_LOG(LogTemp, Log, TEXT("COPPA mode enabled for user under 13"));
}

// Example: Call after age verification
void ACOPPAManager::OnAgeVerified(int UserAge)
{
    if (UserAge < 13)
    {
        USingularSDKBPLibrary::TrackingUnder13();
        UE_LOG(LogTemp, Log, TEXT("COPPA restrictions applied"));

        // Also limit data sharing for children
        USingularSDKBPLibrary::LimitDataSharing(true);
    }
}

// Example: Age gate implementation
void AAgeGateWidget::OnAgeSubmitted(int UserAge)
{
    if (UserAge < 13)
    {
        // Apply COPPA protections
        USingularSDKBPLibrary::TrackingUnder13();
        USingularSDKBPLibrary::LimitDataSharing(true);

        UE_LOG(LogTemp, Warning, TEXT("Child user detected - privacy protections enabled"));

        // Show age-appropriate content
        ShowChildSafeContent();
    }
    else
    {
        // Standard tracking for users 13+
        UE_LOG(LogTemp, Log, TEXT("Adult user - standard tracking enabled"));
        InitializeStandardTracking();
    }
}

重要提示:在确定用户未满 13 周岁后尽早调用此方法,最好是在应用程序初始化期间或年龄验证后立即调用。这样可确保所有后续跟踪都遵守儿童隐私保护法规。


实施最佳实践

完整隐私管理示例

实施全面的隐私控制,尊重用户偏好并遵守相关法规。

C++
// ComprehensivePrivacyManager.h
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "ComprehensivePrivacyManager.generated.h"

UCLASS()
class YOURGAME_API AComprehensivePrivacyManager : public AActor
{
    GENERATED_BODY()

public:
    AComprehensivePrivacyManager();

protected:
    virtual void BeginPlay() override;

public:
    // Initialize privacy settings on app startup
    UFUNCTION(BlueprintCallable, Category = "Privacy")
    void InitializePrivacySettings();

    // User accepts tracking via consent dialog
    UFUNCTION(BlueprintCallable, Category = "Privacy")
    void OnUserAcceptedTracking();

    // User declines tracking
    UFUNCTION(BlueprintCallable, Category = "Privacy")
    void OnUserDeclinedTracking();

    // User updates data sharing preference
    UFUNCTION(BlueprintCallable, Category = "Privacy")
    void SetDataSharingEnabled(bool bEnabled);

    // Check if tracking is currently enabled
    UFUNCTION(BlueprintCallable, Category = "Privacy")
    bool IsTrackingEnabled();

    // Get current privacy status as readable text
    UFUNCTION(BlueprintCallable, Category = "Privacy")
    FString GetPrivacyStatus();

private:
    // Helper methods for config storage
    bool GetUserConsent();
    void SaveUserConsent(bool bConsent);
    bool GetDataSharingPreference();
    void SaveDataSharingPreference(bool bEnabled);

    // Config keys
    static const FString PREF_USER_CONSENT;
    static const FString PREF_DATA_SHARING;
};

// ComprehensivePrivacyManager.cpp
#include "ComprehensivePrivacyManager.h"
#include "SingularSDKBPLibrary.h"
#include "Kismet/GameplayStatics.h"

const FString AComprehensivePrivacyManager::PREF_USER_CONSENT = TEXT("privacy_user_consent");
const FString AComprehensivePrivacyManager::PREF_DATA_SHARING = TEXT("privacy_data_sharing");

AComprehensivePrivacyManager::AComprehensivePrivacyManager()
{
    PrimaryActorTick.bCanEverTick = false;
}

void AComprehensivePrivacyManager::BeginPlay()
{
    Super::BeginPlay();

    // Initialize privacy settings on app start
    InitializePrivacySettings();
}

void AComprehensivePrivacyManager::InitializePrivacySettings()
{
    bool bHasUserConsent = GetUserConsent();
    bool bAllowDataSharing = GetDataSharingPreference();

    // Apply stored tracking preference
    if (bHasUserConsent)
    {
        USingularSDKBPLibrary::TrackingOptIn();
        USingularSDKBPLibrary::ResumeAllTracking();
        UE_LOG(LogTemp, Log, TEXT("Privacy initialized: Tracking enabled with consent"));
    }
    else
    {
        USingularSDKBPLibrary::StopAllTracking();
        UE_LOG(LogTemp, Log, TEXT("Privacy initialized: Tracking disabled"));
    }

    // Set data sharing preference (inverse logic)
    USingularSDKBPLibrary::LimitDataSharing(!bAllowDataSharing);

    UE_LOG(LogTemp, Log, TEXT("Privacy initialized: consent=%s, sharing=%s"), 
           bHasUserConsent ? TEXT("true") : TEXT("false"),
           bAllowDataSharing ? TEXT("true") : TEXT("false"));
}

void AComprehensivePrivacyManager::OnUserAcceptedTracking()
{
    SaveUserConsent(true);

    USingularSDKBPLibrary::TrackingOptIn();
    USingularSDKBPLibrary::ResumeAllTracking();

    UE_LOG(LogTemp, Log, TEXT("User accepted tracking"));
}

void AComprehensivePrivacyManager::OnUserDeclinedTracking()
{
    SaveUserConsent(false);

    USingularSDKBPLibrary::StopAllTracking();

    UE_LOG(LogTemp, Log, TEXT("User declined tracking"));
}

void AComprehensivePrivacyManager::SetDataSharingEnabled(bool bEnabled)
{
    SaveDataSharingPreference(bEnabled);

    // Note: LimitDataSharing uses inverse logic
    // false = data sharing enabled, true = data sharing limited
    USingularSDKBPLibrary::LimitDataSharing(!bEnabled);

    UE_LOG(LogTemp, Log, TEXT("Data sharing: %s"), 
           bEnabled ? TEXT("Enabled") : TEXT("Limited"));
}

bool AComprehensivePrivacyManager::IsTrackingEnabled()
{
    return !USingularSDKBPLibrary::IsAllTrackingStopped();
}

FString AComprehensivePrivacyManager::GetPrivacyStatus()
{
    bool bIsEnabled = !USingularSDKBPLibrary::IsAllTrackingStopped();
    bool bDataSharingEnabled = GetDataSharingPreference();

    return FString::Printf(TEXT("Tracking: %s\nData Sharing: %s"),
                          bIsEnabled ? TEXT("Enabled") : TEXT("Disabled"),
                          bDataSharingEnabled ? TEXT("Enabled") : TEXT("Limited"));
}

// Private helper methods for config storage

bool AComprehensivePrivacyManager::GetUserConsent()
{
    // Implement your config storage retrieval here
    // Example using GameInstance or SaveGame system
    return false; // Default to no consent
}

void AComprehensivePrivacyManager::SaveUserConsent(bool bConsent)
{
    // Implement your config storage here
    // Example using GameInstance or SaveGame system
}

bool AComprehensivePrivacyManager::GetDataSharingPreference()
{
    // Implement your config storage retrieval here
    return false; // Default to limited sharing
}

void AComprehensivePrivacyManager::SaveDataSharingPreference(bool bEnabled)
{
    // Implement your config storage here
}

最佳实践

  • 持久存储:使用虚幻引擎的 SaveGame 系统或自定义配置文件保存用户首选项。
  • 早期初始化:尽可能在SDK初始化之前的BeginPlay()过程中应用隐私设置
  • UI 同步:使用IsAllTrackingStopped()保持设置 UI 与实际 SDK 状态同步
  • 清晰交流:在应用设置中提供清晰、易用的隐私控制
  • 反向逻辑:请记住,LimitDataSharing(false) 意味着启用数据共享,而true 则意味着限制数据共享
  • 合规文档:保留用户何时以及如何提供或撤销同意的记录

方法参考摘要

方法 说明 何时使用
LimitDataSharing(bool) 根据用户同意控制第三方数据共享 CCPA 合规性、用户隐私偏好
TrackingOptIn() 记录明确的 GDPR 跟踪同意 欧盟地区的 GDPR 合规性
StopAllTracking() 完全禁用 SDK 跟踪 用户拒绝所有跟踪同意
ResumeAllTracking() 停止后重新启用跟踪 用户更改同意重新选择
IsAllTrackingStopped() 检查当前跟踪状态 同步用户界面,操作前检查状态
TrackingUnder13() 启用 COPPA 儿童保护 用户被识别为 13 岁以下