既然在0篇章中谈过了解锁成就系统,就按着每个类的顺序来研究。如果在某个类中涉及到后续的类内容,我会简单解释,然后在后边的内容中解决这一问题。
ChickenAchievementManager继承自Object。
关于这个类中要涉及的成就用Enum来罗列。
enum EAchievement { EA_HIGH_SCORE_200, EA_CHAIN_5, EA_CHAIN_10, EA_5_MINUTES, EA_2_MINUTES, EA_CHICKEN_LIFE_30, EA_CHICKEN_LIFE_70, EA_FOX_PICKUP_60, EA_MAX };
这一部分交代了成就,分别有高分。链条的长度,坚持的时间,小鸡的生命,抓住的狐狸数目。以及最后抓住的总和。
enum EAchievementCheckSet { EAC_CHAIN_LENGTH, EAC_HIGH_SCORE, EAC_TOTAL_PLAYTIME, EAC_CHICKEN_LIFE, EAC_FOX_PICKUP };
上面是一个枚举检测器,可能后便需要这个检测条件来解锁某些成就。、
struct EAchievementEntry { var string AchievementTitle; var bool hasUnlocked; };
字符串来表述成就的标题和成就是否被解除。当然每个成就都有这个表述,是否被解锁,解锁的名字是什么?因此我们需要一个成就数组。
var array<EAchievementEntry> EAchievementEntries;
当然解锁一项成就可能会标注颜色
var color AchievementUnlockedColor,AchievementColor;
接下来我进入了一个神秘的系统OnlineSubSystem,偶尔编译运行的时候我都会被提示OnlineSubSystem错误,这种错误多发生在UDK打开的时候还在编译程序。于是我查了一下API手册,里面阐述到这个类和平台和网络有些关系,有些底层。毕竟是在Object类里面继承的(尽管我认为Actor类也可以写计分系统,但是可能无法存储到对应的设备上,但愿我的人是没有错误)
我继续挖掘了一下该类,里面有一个结构
struct AchievementDetails { var const string AchievementName; var const bool bIsSecret; var const bool bWasAchievedOffline; var const bool bWasAchievedOnline; var const string Description; var const int GamerPoints; var const string HowTo; var const int Id; var Surface Image; };
这个结构记录了一些成就名,id积分之类的东西。看来OnlineSubSystem先天就是和这些内容打交道的类,并且牵扯到设备。
在这里有一个局部的OnlineSubsystem.PlayerInterface。文档中对PlayerInterface的解释是访问online玩家的途径。预备功课做足了,我们上代码
function Initialize() { local OnlineSubSystem OnlineSub; local array<AchievementDetails>theDetails; //AchievementDetails是一个结构 local int iter; OnlineSub=class'GameEngine'.Static.GetOnlineSubsystem(); if(OnlineSub!=none&&OnlineSub.PlayerInterface!=none) { OnlineSub.PlayerInterface.GetAchievements(0,theDetails); //GetAchievements是一个方法,可能是获取一些数组中的内容 for(iter=0;iter<theDetails.length;iter++) { if(theDetails[iter].bWasAchievedOnline||theDetails[iter].bWasAchievedOnlien) { AchievementEntries[theDetails[iter].id].hasUnlocked=true; } } } }
对这个类才接触有许多让人犯糊涂的地方,不过我相信多回头看最终就能掌握这部分的意义。
这个类相对比较底层,我们将会发现即使GameInfo也可以在这个类中定义变量被使用,因为他将保存游戏中的一些数据。
function UnlockAchievement(EAchievement achievementToUnlock) { local OnlineSubsystem OnlineSub; local ChickenGame theGame; OnlineSub=class'GameEngine'.Static.GetOnlineSubsystem(); if(!AchievementEntries[achievementToUnlock].hasUnlock) //achievementToUnlock是参数,看准啦 { if(Onlinesub!=none&&OnlineSub.PlayerInterface=none) { theGame=ChickenGame(class'WorldInfo'.static.GetWorldInfo().Game); theGame.AddFloatingTextEntry(theGame.gameSpawnManager.NotificationTextPos,"Achievement Unlocked!!!",AchievementUnlockedColor,1.6,3.4,0,70); theGame.AddFloatingTextEntry(theGame.gameSpawnManager.NotificationTextPos,AchievementEntries[achievementToUnlock].AchievementTitle,AchievementColor,1.6,3.5,60,70); AchievementEntries[achievementToUnlock].hasUnlocked=true; class'WorldInfo'.static.GetWorldInfo().PlaySound(AchievementUnlockedSound,true); OnlineSub.PlayerInterface.UnlockAchievement(0,int(achievementToUnlock)); } } }
还是新建了OnlineSubsystem子类,theGame获取游戏类,然后堆起执行操作至于游戏类中定义的gameSpawnManager和blabla的东西等回头遇上了在分析。
UnlockAchievement也是新类。
function CheckToUnlockAchievement(EAchievementCheckSet achievementSetCheck,int valueToCheck) { switch(achievementSetCheck) { case EAC_FOX_PICKUP: if(valueToCheck>=120) { UnLockAchievement(EA_FOX_PICKUP_60); } break; case EAC_CHICKEN_LIFE: if(EAC_CHICKEN_LIFE>=210) { UnlockAchievement(EA_CHICKEN_LITE_120); } if (valueToCheck >= 120) { UnlockAchievement(EA_CHICKEN_LIFE_70); } if (valueToCheck >= 30) { UnlockAchievement(EA_CHICKEN_LIFE_30); } break; case EAC_TOTAL_PLAYTIME: if (valueToCheck >= 240) { UnlockAchievement(EA_5_MINUTES); } if (valueToCheck >= 120) { UnlockAchievement(EA_2_MINUTES); } break; case EAC_CHAIN_LENGTH: if (valueToCheck >= 15) { UnlockAchievement(EA_CHAIN_10); } else if (valueToCheck >= 10) { UnlockAchievement(EA_CHAIN_5); } break; case EAC_HIGH_SCORE: if (valueToCheck >= 10000) { UnlockAchievement(EA_HIGH_SCORE_200); } }; }
注意看参数等内容。
最后学习一下怎么给前面的struct命名。
AchievementEntries(EA_HIGH_SCORE_200)=(AchievementTitle="Top of the Pecking Order")