Unity之一天一个技术点(三)---判断当前运行的平台

3:判断当前运行的平台
因为PC端的操控和移植到手游上的操控不同,所以要写两套操控方式。
方法一: 判断当前的平台
        switch (Application.platform)
        {
            case RuntimePlatform.WindowsEditor://PC端
                print("aaaa");
                break;
 
            case RuntimePlatform.Android://android手机
                print("cccc");
                break;
        }
 方法二:通过宏定义判断
#if UNITY_IPHONE || UNITY_ANDROID
public static bool  isAndroid = true;
#else
public static bool  isAndroid = false;
#endif


<think> 我们正在Unity中实现一个7连续签到系统。根据引用[1]中的描述,我们需要解决两个主要问题: 1. 判断是否已经签到 2. 判断签到数是否连续以及是否已完成7连续签到(如果中断或完成7,则重置) 实现思路如下: ### 1. 数据存储 我们需要存储以下数据: - 最近一次签到的日期:用于判断连续签到的中断 - 当前连续签到的数:记录已经连续签到了几 我们可以使用PlayerPrefs来存储这些数据,但注意PlayerPrefs不适合存储敏感数据,对于签到系统足够。 ### 2. 签到逻辑 - 当玩家点击签到按钮时,获取当前系统时间(注意时区问题,一般使用本地时间或UTC时间,需保持一致)。 - 判断当前日期与最近一次签到日期是否连续(即是否在第二0点之后且不超过24小时?但通常我们按自然日判断,即只要日期是下一就算连续)。 - 如果连续,则连续签到数加1;如果不连续(比如中间断了一或更多),则重置连续签到数为1。 - 如果连续签到数达到7,则在签到后重置连续签到数为0(或者记录为已完成,根据需求决定是否重置)。 ### 3. 判断是否已经签到 比较当前日期和最近一次签到日期,如果相同则说明今已经签到。 ### 4. 重置条件 根据引用[1]的描述,当签到不连续或者已经完成了7连续签到,需要清除数据重新计算。但通常,完成7连续签到后,我们可能会重置为0,然后重新开始下一轮,或者停止直到活动结束。具体需求可以根据策划调整。 ### 实现步骤 #### 定义存储的键 ```csharp private const string LastSignInDateKey = "LastSignInDate"; // 存储最近一次签到的日期字符串 private const string ConsecutiveDaysKey = "ConsecutiveDays"; // 存储连续签到的数 ``` #### 获取当前日期(使用本地日期,不考虑时间) ```csharp DateTime currentDate = DateTime.Now.Date; ``` #### 检查今是否已经签到 ```csharp public bool HasSignedToday() { if (PlayerPrefs.HasKey(LastSignInDateKey)) { string lastDateStr = PlayerPrefs.GetString(LastSignInDateKey); DateTime lastDate = DateTime.Parse(lastDateStr); return lastDate == currentDate; } return false; } ``` #### 执行签到 ```csharp public void SignIn() { DateTime currentDate = DateTime.Now.Date; // 如果今已经签到,则返回 if (HasSignedToday()) { Debug.Log("今已经签到过了!"); return; } // 获取上次签到日期和连续签到数 DateTime lastSignInDate = DateTime.MinValue; int consecutiveDays = 0; if (PlayerPrefs.HasKey(LastSignInDateKey)) { lastSignInDate = DateTime.Parse(PlayerPrefs.GetString(LastSignInDateKey)); consecutiveDays = PlayerPrefs.GetInt(ConsecutiveDaysKey, 0); } // 判断是否连续:上次签到日期是否是昨(自然日连续) if (lastSignInDate.Date == currentDate.AddDays(-1).Date) { consecutiveDays++; } else { // 如果不是连续的(可能是中断,也可能是第一次签到),重置为1 consecutiveDays = 1; } // 如果已经连续签到7,可以在签到后重置(这里根据需求,重置为0,然后重新开始连续签到) // 或者也可以保留为7,并标记为已完成,直到活动重置(比如每月重置) // 这里我们假设连续签到7后重置为0,重新开始 if (consecutiveDays > 7) { // 实际上不应该超过7,因为我们在每次7后重置 consecutiveDays = 1; } // 更新签到日期和连续数 PlayerPrefs.SetString(LastSignInDateKey, currentDate.ToString()); PlayerPrefs.SetInt(ConsecutiveDaysKey, consecutiveDays); PlayerPrefs.Save(); // 根据连续数发放奖励 GrantReward(consecutiveDays); Debug.Log($"签到成功!连续签到{consecutiveDays}"); } // 发放奖励的函数 private void GrantReward(int days) { // 根据连续签到数发放奖励 } ``` #### 重置逻辑 在什么情况下重置? - 我们可以在每次签到后检查,如果连续签到数达到7,则重置连续签到数为0(或者1?根据需求,通常重置为0,然后下一次签到重新开始计数为1)。但是上面的代码在达到7后,如果下一次签到(第8次)会判断为中断(因为上次签到是7前,不是昨),所以会自动重置为1。因此不需要额外重置。 但是引用[1]提到:不连续或者已经完成了7连续签到,需要清除数据重新计算。我们上面的代码已经处理了不连续的情况(重置为1)。对于完成了7连续签到,我们并没有在完成7的瞬间重置,而是等到下一次签到(第8)时,由于中断(因为中间隔了超过一)而重置为1。所以如果我们希望玩家在完成7连续签到后,即使他后面继续连续签到也不增加数(保持在7),那么我们需要修改逻辑。 ### 另一种需求:7一个循环 如果需求是7一个循环,连续签到7后,下一次签到重新从第1开始(即使中间没有中断),那么我们就需要在达到7后的下一次签到重置。 在上面的签到函数中,我们可以在签到后判断,如果连续签到数为7,那么重置连续签到数为0(注意,重置为0后,下一次签到就会变成1)。但是注意,如果连续签到7后,玩家第二又来签到,此时应该是新的一轮的第一。我们可以这样修改: ```csharp // 在更新连续数之前,我们先判断 // 如果连续数已经达到7,那么今签到应该是新的一轮的第一 if (consecutiveDays >= 7) { consecutiveDays = 1; } else { // 否则,按照正常连续签到逻辑 if (lastSignInDate.Date == currentDate.AddDays(-1).Date) { consecutiveDays++; } else { consecutiveDays = 1; } } ``` 但是注意,连续数达到7的情况,通常是在上一次签到后连续数已经为7,那么这次签到(第8)时,因为上一次签到是前或更早,所以不会进入连续增加的分支,而是进入重置为1的分支。所以上面的代码中,我们实际上不会遇到consecutiveDays>=7的情况,因为每次签到后我们保存的都是1~7。 因此,我们可以在签到后立即重置(如果当签到后连续数达到7,则重置为0,这样下次签到就会重新开始)?但是这样会导致当签到后连续数立即被重置为0,显示会有问题。 所以,我们可以在签到后发放奖励,然后并不立即重置,而是等到下一次签到的时候再重置。那么下一次签到的时候,由于上一次签到日期是7前(或者任意一,只要不是昨),就会重置为1。这样,连续签到数会显示为7,直到下一次签到(然后变成1)。 ### 总结 根据需求,我们有两种处理方式: 1. 连续签到达到7后,下一次签到自动重新开始(即使中断一也会重置为1)。这种方式下,玩家在完成7后的第8来签到,会重新从1开始。 2. 连续签到达到7后,系统重置连续签到数为0(或-1),然后玩家再次签到就从1开始。但是这种方式需要在下一次签到之前就重置,可以在每检查的时候重置?但这样会增加复杂度。 我们通常采用第一种方式,即每次签到都根据上一次签到日期判断是否连续,不连续则重置为1。 ### 注意事项 1. **时区问题**:使用本地时间,但要注意玩家修改系统时间的问题。如果玩家修改系统时间,可能会作弊。对于防作弊,可能需要服务器验证,但这超出了本问题的范围。 2. **存储格式**:存储日期时,使用`ToString()`和`DateTime.Parse`,但要注意文化差异。最好使用固定格式,例如: ```csharp string dateStr = currentDate.ToString("yyyy-MM-dd"); DateTime date = DateTime.ParseExact(dateStr, "yyyy-MM-dd", null); ``` 3. **跨时间点**:有些游戏将凌晨5点作为刷新点,而不是0点。这时需要调整日期的计算。 ### 完整代码示例(使用自然日,刷新点为0点) ```csharp using UnityEngine; using System; public class DailySignInSystem : MonoBehaviour { private const string LastSignInDateKey = "LastSignInDate"; private const string ConsecutiveDaysKey = "ConsecutiveDays"; // 检查今是否已经签到 public bool HasSignedToday() { if (!PlayerPrefs.HasKey(LastSignInDateKey)) return false; string lastDateStr = PlayerPrefs.GetString(LastSignInDateKey); DateTime lastDate = DateTime.ParseExact(lastDateStr, "yyyy-MM-dd", null); DateTime currentDate = DateTime.Now.Date; return lastDate == currentDate; } // 执行签到 public void SignIn() { DateTime currentDate = DateTime.Now.Date; if (HasSignedToday()) { Debug.Log("今已经签到过了!"); return; } int consecutiveDays = 1; // 默认今签到是第一 if (PlayerPrefs.HasKey(LastSignInDateKey) && PlayerPrefs.HasKey(ConsecutiveDaysKey)) { string lastDateStr = PlayerPrefs.GetString(LastSignInDateKey); DateTime lastDate = DateTime.ParseExact(lastDateStr, "yyyy-MM-dd", null); consecutiveDays = PlayerPrefs.GetInt(ConsecutiveDaysKey); // 检查是否连续:上次签到日期是否是昨 if (lastDate == currentDate.AddDays(-1)) { consecutiveDays++; // 如果连续数超过7,则重置为1(实际上连续签到7后的下一次应该是重新开始,所以这里我们也可以重置) // 但注意:连续签到7后,第8来签到,由于上次签到日期是前,所以不会进入这个分支,而是进入else分支重置为1 // 所以这里我们不需要处理超过7的情况 } else { // 不是连续的,重置为1(注意:如果上次签到是前或更早,重置为1) consecutiveDays = 1; } } // 保存数据 PlayerPrefs.SetString(LastSignInDateKey, currentDate.ToString("yyyy-MM-dd")); PlayerPrefs.SetInt(ConsecutiveDaysKey, consecutiveDays); PlayerPrefs.Save(); // 发放奖励 GrantReward(consecutiveDays); Debug.Log($"签到成功!连续签到{consecutiveDays}"); } // 获取当前连续签到数(用于显示) public int GetConsecutiveDays() { if (PlayerPrefs.HasKey(ConsecutiveDaysKey)) return PlayerPrefs.GetInt(ConsecutiveDaysKey); return 0; } // 发放奖励 private void GrantReward(int days) { // 根据数发放奖励 // 例如:第1奖励A,第2奖励B...第7奖励G } } ``` ### 说明 - 该代码使用自然日(0点刷新)判断连续签到。 - 存储日期时使用"yyyy-MM-dd"格式,避免文化差异导致的解析错误。 - 每次签到都会更新日期和连续数,并发放对应奖励。 ### 相关问题 1. 如何防止玩家通过修改系统时间作弊? 2. 如果游戏需要跨时区运行,如何统一签到时间? 3. 如何设计7签到奖励的数据结构(配置表)? </think> 在Unity中实现7日连续签到功能需要解决**签到状态判断**、**日期连续性验证**和**数据存储**个核心问题。以下是完整实现方案: --- ### 一、核心实现代码 ```csharp using System; using UnityEngine; public class DailySignInSystem : MonoBehaviour { // 存储键名 private const string LAST_SIGN_DATE_KEY = "LastSignDate"; private const string CONSECUTIVE_DAYS_KEY = "ConsecutiveDays"; // 检查并执行签到 public void TrySignIn() { DateTime now = DateTime.Now.Date; DateTime lastSignDate = GetLastSignDate(); int consecutiveDays = GetConsecutiveDays(); // 检查今是否已签到 if (lastSignDate == now) { Debug.Log("今日已签到"); return; } // 检查是否连续(间隔是否为1) bool isConsecutive = (now - lastSignDate).TotalDays == 1; // 更新连续数 consecutiveDays = isConsecutive ? consecutiveDays + 1 : 1; // 如果完成7则重置 if (consecutiveDays > 7) consecutiveDays = 1; // 保存数据 PlayerPrefs.SetString(LAST_SIGN_DATE_KEY, now.ToString("yyyy-MM-dd")); PlayerPrefs.SetInt(CONSECUTIVE_DAYS_KEY, consecutiveDays); Debug.Log($"签到成功!连续签到: {consecutiveDays}"); GrantReward(consecutiveDays); // 发放奖励 } // 获取上次签到日期 private DateTime GetLastSignDate() { if (PlayerPrefs.HasKey(LAST_SIGN_DATE_KEY)) { return DateTime.Parse(PlayerPrefs.GetString(LAST_SIGN_DATE_KEY)); } return DateTime.MinValue; // 从未签到 } // 获取连续数 private int GetConsecutiveDays() { return PlayerPrefs.GetInt(CONSECUTIVE_DAYS_KEY, 0); } // 发放奖励(示例) private void GrantReward(int day) { // 根据数发放不同奖励 switch(day) { case 1: /* 第1奖励 */ break; case 7: /* 第7奖励 */ break; } } } ``` --- ### 二、关键逻辑解析 1. **连续签到判断** 通过计算当前日期与上次签到日期的差值: ```csharp bool isConsecutive = (now - lastSignDate).TotalDays == 1; ``` - `=1`:昨签过到,连续签到 - `>1`:中断后重新开始 - `<1`:同一重复签到 2. **7周期重置** 当连续数超过7时自动重置: ```csharp if (consecutiveDays > 7) consecutiveDays = 1; ``` 3. **数据存储优化** - 使用`DateTime.ToString("yyyy-MM-dd")`存储标准化日期字符串 - 使用`PlayerPrefs`持久化存储(适合小型数据) --- ### 、防作弊设计 1. **防止修改系统时间** ```csharp // 添加时间校验(示例) if(now < lastSignDate) { Debug.LogError("系统时间异常!"); return; } ``` 2. **云端验证(增强版)** ```csharp IEnumerator ValidateWithServer() { UnityWebRequest req = UnityWebRequest.Get("https://api.yourserver.com/time"); yield return req.SendWebRequest(); if(req.result == UnityWebRequest.Result.Success) { DateTime serverTime = DateTime.Parse(req.downloadHandler.text); // 使用服务器时间替代本地时间 } } ``` --- ### 四、界面集成示例 ```csharp // UI控制器 public class SignInUI : MonoBehaviour { [SerializeField] Button signButton; [SerializeField] Text daysText; void Start() { signButton.onClick.AddListener(() => { FindObjectOfType<DailySignInSystem>().TrySignIn(); }); // 更新UI显示 daysText.text = $"连续签到: {GetConsecutiveDays()}"; } } ``` --- ### 五、注意事项 1. **时区处理** 使用`DateTime.Now`获取的是本地时间,如需全球统一改用UTC时间: ```csharp DateTime now = DateTime.UtcNow.Date; ``` 2. **跨时间点** 如需凌晨5点刷新(而非0点): ```csharp DateTime now = DateTime.Now.AddHours(-5).Date; // 偏移5小时 ``` 3. **数据加密** 对敏感数据使用加密存储: ```csharp string encrypted = Convert.ToBase64String(Encoding.UTF8.GetBytes(now.ToString())); ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值