Unity本地推送实战从零配置Android/iOS通知附常见问题解决方案在移动应用开发中推送通知是提升用户留存和活跃度的关键功能。作为Unity开发者你可能已经发现原生平台的通知系统与Unity引擎之间存在一定的鸿沟。本文将带你深入探索Unity官方提供的Mobile Notifications解决方案从环境配置到代码实现再到平台差异处理手把手教你构建稳定可靠的通知系统。1. 环境准备与基础配置1.1 必备组件检查清单在开始编码前确保你的开发环境满足以下要求Unity版本2020.3或更高推荐2021 LTS长期支持版目标平台Android 5.0API Level 21iOS 10.0Package安装# 通过Package Manager安装Mobile Notifications Window → Package Manager → Unity Registry → 搜索Mobile Notifications → Install注意如果项目已存在旧版推送插件建议先完全移除后再安装新版本避免冲突。1.2 Android特殊配置要点Android平台的通知系统较为复杂需要特别注意图标规范小图标(48x48px)纯白色透明背景大图标(192x192px)可包含色彩推荐使用Android Asset Studio生成合规图标渠道(Channel)配置var channel new AndroidNotificationChannel { Id default_channel, Name 默认通知, Importance Importance.High, Description 重要通知通道 }; AndroidNotificationCenter.RegisterNotificationChannel(channel);AndroidManifest检查确保uses-permission android:nameandroid.permission.POST_NOTIFICATIONS /已添加如果使用自定义Activity需在Mobile Notification设置中指定1.3 iOS特殊配置要点iOS平台配置相对简单但有几个关键点Capability添加在Xcode项目中添加Push Notifications capability确保开启Background Modes中的Remote notifications权限请求#if UNITY_IOS using Unity.Notifications.iOS; var authorizationOption AuthorizationOption.Alert | AuthorizationOption.Badge; iOSNotificationCenter.RequestAuthorization(authorizationOption); #endif图标尺寸AppIcon中必须包含29x29、40x40、60x60三种尺寸推荐使用Xcode的AppIcon资产目录管理2. 核心代码实现详解2.1 跨平台通知发送封装以下是一个完整的跨平台通知发送方案public class NotificationManager : MonoBehaviour { private const string ANDROID_CHANNEL_ID default_channel; void Start() { InitializeChannels(); RequestPermissions(); } void InitializeChannels() { #if UNITY_ANDROID var channel new AndroidNotificationChannel { Id ANDROID_CHANNEL_ID, Name 默认通知, Importance Importance.High }; AndroidNotificationCenter.RegisterNotificationChannel(channel); #endif } void RequestPermissions() { #if UNITY_IOS StartCoroutine(RequestIOSAuthorization()); #endif } #if UNITY_IOS IEnumerator RequestIOSAuthorization() { var authorizationOption AuthorizationOption.Alert | AuthorizationOption.Badge; using (var req new AuthorizationRequest(authorizationOption, true)) { while (!req.IsFinished) yield return null; } } #endif public void ScheduleNotification(string title, string content, DateTime fireTime) { #if UNITY_ANDROID var notification new AndroidNotification { Title title, Text content, FireTime fireTime, SmallIcon notify_icon_small, LargeIcon notify_icon_large }; AndroidNotificationCenter.SendNotification(notification, ANDROID_CHANNEL_ID); #elif UNITY_IOS var timeInterval fireTime.ToUniversalTime() - DateTime.UtcNow; var iOSNotification new iOSNotification { Identifier Guid.NewGuid().ToString(), Title title, Body content, ShowInForeground true, Trigger new iOSNotificationTimeIntervalTrigger { TimeInterval timeInterval, Repeats false } }; iOSNotificationCenter.ScheduleNotification(iOSNotification); #endif } }2.2 通知交互处理处理用户点击通知的场景void OnEnable() { #if UNITY_ANDROID AndroidNotificationCenter.OnNotificationReceived OnAndroidNotificationReceived; #elif UNITY_IOS iOSNotificationCenter.OnNotificationReceived OnIOSNotificationReceived; #endif } void OnDisable() { #if UNITY_ANDROID AndroidNotificationCenter.OnNotificationReceived - OnAndroidNotificationReceived; #elif UNITY_IOS iOSNotificationCenter.OnNotificationReceived - OnIOSNotificationReceived; #endif } #if UNITY_ANDROID void OnAndroidNotificationReceived(AndroidNotificationIntentData data) { var msg $收到通知ID:{data.Id}\n标题:{data.Notification.Title}; Debug.Log(msg); // 处理自定义数据 if(!string.IsNullOrEmpty(data.Notification.IntentData)) { ProcessNotificationData(data.Notification.IntentData); } } #endif #if UNITY_IOS void OnIOSNotificationReceived(iOSNotification notification) { var msg $收到通知ID:{notification.Identifier}\n标题:{notification.Title}; Debug.Log(msg); // 处理自定义数据 if(notification.Data.Count 0) { ProcessNotificationData(notification.Data); } } #endif2.3 高级功能实现2.3.1 重复通知#if UNITY_ANDROID var repeatNotification new AndroidNotification { Title 每日签到, Text 别忘了领取今日奖励, FireTime DateTime.Today.AddHours(20), // 每晚8点 RepeatInterval TimeSpan.FromDays(1), // 每天重复 SmallIcon reminder_icon }; AndroidNotificationCenter.SendNotification(repeatNotification, reminders); #endif2.3.2 带操作按钮的通知#if UNITY_IOS var notification new iOSNotification { Identifier action_notification, Title 新消息, Body 您有3条未读消息, CategoryIdentifier MESSAGE_CATEGORY, ThreadIdentifier message_thread }; iOSNotificationCenter.ScheduleNotification(notification); #endif3. 平台差异与适配技巧3.1 行为差异对照表功能特性Android表现iOS表现图标显示必须提供特定格式的小图标和大图标使用AppIcon中的图标权限获取安装后默认有权限需要显式请求用户授权后台限制较宽松可设置重要性级别严格限制需配置Background Modes本地通知数量限制无硬性限制最多64个未送达通知点击行为默认启动应用需处理OnNotificationReceived事件3.2 多设备适配经验Android碎片化问题测试不同厂商设备小米、华为等它们的通知系统可能有定制部分厂商需要手动开启应用的自启动权限iOS版本兼容iOS 12-15的通知API有细微差异使用Xcode 13确保对新系统的兼容性图标适配技巧!-- Android res/drawable/notification_icon.xml -- adaptive-icon xmlns:androidhttp://schemas.android.com/apk/res/android background android:drawablecolor/notify_bg/ foreground android:drawabledrawable/ic_notify_fg/ /adaptive-icon4. 疑难问题解决方案4.1 常见错误排查问题1Android通知不显示检查渠道是否成功创建AndroidNotificationCenter.GetNotificationChannels()验证图标资源是否放置在正确的drawable目录查看Logcat过滤Notification相关日志问题2iOS通知权限被拒绝首次请求被拒后需要引导用户到设置中手动开启使用iOSNotificationCenter.GetNotificationSettings()检查当前权限状态问题3通知点击无响应Android检查AndroidManifest中的Activity配置iOS确保AppDelegate处理了application:didReceiveRemoteNotification:方法4.2 性能优化建议批量操作// 批量取消通知比单个取消效率更高 AndroidNotificationCenter.CancelAllNotifications();资源管理避免使用过大的图标Android大图标不超过512x512及时清理已送达的通知频率控制重要通知使用High重要性级别普通通知使用Default级别避免打扰用户4.3 调试技巧Android调试命令adb shell dumpsys notificationiOS调试工具使用Xcode的Console.app查看通知日志模拟器支持测试本地通知xcrun simctl addmedia添加测试图片Unity编辑器扩展#if UNITY_EDITOR [MenuItem(Tools/Test Notification)] static void TestNotification() { // 编辑器模拟代码 } #endif5. 进阶应用场景5.1 游戏场景中的实践在RPG游戏中实现任务提醒public void ScheduleQuestReminder(Quest quest) { var dueTime quest.Deadline - DateTime.Now; if(dueTime.TotalHours 24) { // 提前24小时提醒 var reminderTime quest.Deadline.AddHours(-24); ScheduleNotification(任务即将到期, $「{quest.Name}」还剩24小时, reminderTime); } }5.2 电商应用案例商品降价通知实现方案public class PriceDropNotifier : MonoBehaviour { private Dictionarystring, float trackedItems new(); public void TrackItem(string itemId, float currentPrice) { trackedItems[itemId] currentPrice; } public void CheckPriceDrop(string itemId, float newPrice) { if(trackedItems.TryGetValue(itemId, out var oldPrice) newPrice oldPrice) { var dropPercent (oldPrice - newPrice) / oldPrice * 100; ScheduleNotification(价格下降, ${itemId}降价{dropPercent:0}%现仅需{newPrice:C}, DateTime.Now.AddMinutes(1)); } } }5.3 混合推送策略结合本地和远程推送的最佳实践本地推送适用场景定时提醒如每日签到离线功能提醒基于设备事件的触发远程推送适用场景实时消息通知服务端触发的活动用户间互动消息混合实现示例public class HybridPushManager : MonoBehaviour { void OnRemotePushReceived(PushPayload payload) { if(payload.type local_trigger) { // 由远程推送触发本地通知 ScheduleLocalNotification(payload.title, payload.content); } } }在实际项目中本地通知的稳定性和即时性往往比远程推送更可靠。特别是在网络状况不稳定的情况下合理利用本地通知可以显著提升用户体验。