So I want to add achievements to my game.
Basically there are around 40 achievements that can be awarded while using the app. (if while playing a game, and even while pressing some menu buttons).
I'm not sure how should I implement it, so I'll let you know what are the options I thought of so far :
Writing an AM (Achievements Manager) class which will have a addAchievment() function.
Inside every function in my app that can grant achievement I can allocate an Achievemnt object and call addAchievment() with that object.
What I don't like about this approach is first, you have do add lot's of achievments code to many many parts of the app. (and also checking not add the same achievement more than once).
One way to improve it would be maybe to call addAchievment() with a certain enum, and then inside addAchievment() implementation to check each enum and allocate the appropriate achievment object - however, a function with a switch of 40 cases doesn't sound good either.
2.
For every class that can report achievements I can write a function per achievement which return if that achievement should be granted.
for example is class A can report 2 achivments I can write 2 functions :
-(BOOL) shouldGrantA1
-(BOOL) shouldGrantA2
When I init class A, I call the achievements manger and add those 2 function to an array of function the AM will hold.
Every time I want to check if I should grant achievments I just call the AM CheckAchievements() and what it will do is run through all the function and add achievements
where the function return TRUE.
Problem with this approach - Let's say in class A I reach a place where I change a value that I know can grant achievemetn. I can call AM's CheckAchievements() but that will go through all the achivements functions, even though probably currently only class A's achivement would be granted. seems like a bit overhead.
Any way to solve that ?
I would love to here other suggestion as well.
Thanks!!
I would not add any achievement like code to your existing game classes. No booleans or whatsoever because this creates too tight a coupling between your game classes and your achievement system. Better to create a separate "AchievementManager" that manages several AchievementListeners, these listen to the state of objects and when a relevant state changes the unlock condition is checked. I think this idea is best illustrated in code.
For example if you have the achievement "Player walks 100 kilometers". the PlayerWalksAchievementListener would look like this.
private AchievementManager manager;
private Player player.
private Vector2 previousPlayerPosition;
private float distanceWalked;
Update()
{
float dist = Vector2.Distance(player.Position, previousPlayerPosition);
if(dist > 0)
{
distanceWalked += dist;
CheckUnlockCondition();
}
}
CheckUnlockCondition()
{
if(distanceWalked * conversionFactor > 100) { manager.UnlockAchivement(achievementID); }
}
Related
I am making a quiz game in Unity and I've come across architectural problem.
I want the game to have few game modes, like standard, faster answer - more points, etc. Each of which will behave in its own specific way but some things will be very similar like answering questions, starting timer, etc.
Currently its structured based on this. There is a QuizSystem that holds reference to QuestionDatabase, UIReferences(buttons,score text, etc) and GameSettings (questions per game/per mode etc).
To start the game you need to call QuizSystem.Start() and it starts its current GameMode which derives from abstract StateMachine and is a monobehaviour (dont know if neccesary). I also have abstract State class from which different game states will derive from. It has a constructor with (GameMode owner) as paramenter and 3 functions: Start(), Tick(), End().
So, this way I can have Standard game mode which will instatiate lets say StandardPreparationState, which on end will call StandardAnswerState which will start the timer and wait for user input and again call StandardPreparationState. Cycle will repeat until questions per mode amount is reached and then delegate next action to QuizSystem.
The advantage of this approach is that every mode can behave in its own way like add additional steps in between but it kinda limits reusability. What I mean by that is if some OtherMode would have the same preparation functionality but different action afterwards, it wouldn't work beacause
StandardPreparationState would transition to StandardAnswerState.
I could add another parameter such as (GameMode owner, State transitionTo) to the State constructor but that somehow seems wrong I don't know why xD
What I want to know is how do you guys implement different game modes for your games? Do you make each mode as separate scene? Or maybe use States Machine pattern and have Manager class that takes care of starting/swaping modes?
I know that each game is different but are there maybe some common approaches for that?
Thanks in advance!
This question is quite open and opinion-based. However there are few "common" approaches, one of the most important is to make game "data-driven".
What? Why? How?
Imagine you are having space shooter, where you have your ship flying around and picking guns. Each time you add new gun, you will have to code its damage, kind of projectiles and how many of them you shoot, their color, in what pattern they spawn, speed, size, ...
Everytime you would want to add a new gun, you would need to enter the code and change it there, compile, ... Lot of work.
Instead people thought, "why don't we create simple class that holds all the parameters? We will make it editable from Unity, instatiate it in the project and we won't need to code that much."
This is when Unity brought Scriptable objects.
Scriptable objects
A ScriptableObject is a data container that you can use to save large amounts of data, independent of class instances. One of the main use cases for ScriptableObjects is to reduce your Project’s memory usage by avoiding copies of values.
The idea is to create scriptable object for your mode and set up multiple kinds of modifiers that will the mode use. Folder structure might look like:
> ScriptableObjects
| |--> Modes
| |-> NormalSO (instance)
| |-> HardWithLotOfExpSO (instance)
| |-> EasyWithLowerExpSO (instance)
> Script
|--> ScriptableObjects
|-> ModeSO
ScriptableObject is class that doesn't really have the logic inside, just creates "structure" for keeping data. Example of such class would be:
public class ModeSO : ScriptableObject
{
public string modeName;
public float scoreMultiplier;
public int numberOfEnemiesMaxAlive;
public int numberOfEnemiesTotal;
public Vector3[] spawnPoints;
}
In the Unity itself you would then create instance of such objects. And what about interaction with other classes? Well, they would just work as:
Game manager hold single instance of active mode
Class that would be handling score (e.g. player / scoreboard) or Enemy would ask GameManager what is current multiplier for score
WorldSpawner would ask GameManager how many enemies should he spawn, where, and when to spawn next ones
At the beginning of the game you would be able to select difficulty by its name
Example of one of the classes (Scoreboard):
public class ScoreBoard: MonoBehavior
{
GameManager manager;
private float totalScore;
OnEnemyDestroyed(float scoreForEnemy)
{
totalScore += scoreForEnemy * (manager?.activeMode?.modifier ?? 1);
}
}
And the best is, whenever you will change some data, you will just modify the existing instance in the Unity. No need to go into code. No need to recompile whole game.
I think having different scenes for each game mode, especially if the modes are very similar save for a few settings, is unnecessary. I'd have to see more of your design to know how your game logic is being handled (is it all managed in one GameManager script? Or are there multiple scripts in the scene that take values from this manager script to handle game mechanics?)
One way I've handled different game modes before is to use a public int value in the GameManager that represents the different modes (i.e 1 = easy, 2 = medium, 3 = hard). I would then use a switch statement in any scripts whose behavior/values depend on this mode and reference that public int to determine game settings.
Game Manager:
public class GameManager: MonoBehavior
{
public int gameMode = 0; //set to 1,2, or 3 by UI
[...] //rest of game manager code
}
Example Behavior Script:
public class EnemySpawn: MonoBehavior
{
public GameObject enemy;
GameManager gm;
private float spawnRate;
Start()
{
switch(gm.gameMode)
{
case 1:
spawnRate = 15f;
break;
case 2:
spawnRate = 10f;
break;
case 3:
spawnRate = 5f;
break;
default:
spawnRate = 10000f;
Debug.log("invalid mode");
break;
}
}
Awake()
{
InvokeRepeating("SpawnEnemy", spawnRate, 0f);
}
[...] //rest of EnemySpawn code, including a SpawnEnemy() function.
}
This example would reference the GameManager's gameMode int to determine what speed to spawn enemies at, assuming there is a SpawnEnemy() function somewhere down in the code. I can't verify if this example is syntactically correct, but it's just to show one way to handle game modes.
I have a lot of Game Objects I need to Instantiate and put on scene on possible positions.
I have a list of rules where GameObject can be put by player (e.g. small box only at big box, sphere only on small box etc.)
I know I can put every rule into an "if", but I think it's not the most efficienty way. How should I keep a list of rules where can user put GameObjects? How my scripts should check and show possible positions? I will be thankful for any ideas how to start, to make it elegant and efficient.
There are many ways to do this.
What i would prefer is to keep everything organized and configurable per object (looking at the object oriënted programming structure).
I suggest defining per object where it can be placed. Here an example.
public yourClass
{
public GameObject ObjectToPlace;
public List<GameObject> ObjectToPlaceOnList;
public bool CanObjectBePlaced(GameObject targetObjectToPlaceUpon)
{
if (ObjectToPlaceOnList.Contains(targetObjectToPlaceUpon))
{
return true;
}
return false;
}
}
Your script may look different ofcourse, based on your current scripts.
I would like to populate the UI when I load a scene, with the correct data, instead of placeholders.
When I call "LoadSceneAsync", what would be the first object that is called, so I can fill the UI label with the correct data? I know that there is a scene GameObject, but I am not sure if that would fit my needs.
I am looking for some sort of constructor, called when a new scene object is loaded; to plug in my setup function.
You say
Indeed I did use "onlevelwasloaded" but the UI element may not be there, ready to go, when I invoke it, which lead to errors
That would be an incredibly sever bug in Unity! :)
Could it be that you are mixing-up Awake and Start somewhere?
One way to think of it is once you call Start, you know all the Awake have already run.
When I call "LoadSceneAsync", what would be the first object that is called, so I can fill the UI label with the correct data
You are still within the same frame.
Once you see LoadSceneAsync you can be absolutely assured everything is Awake 'd.
Or indeed once you use Start you can be absolutely assured everything is Awake 'd.
1) could it be that in some of your UI elements (or whatever) you are doing something in Start which you should do in Awake?
2) if (for some reason) you want to "wait until the next frame", perhaps just during development - then do that, wait a frame. You'll see a flicker, but if that's what you want to do (for some reason) do that.
3) note that if you mean you want to go to the net to get something, well of course you have to wait frames (use Update/coroutine) until the information comes back from the net, obviously. (How else could it be?)
Note that in practice, one should be using UnityEngine.Events.UnityEvent everywhere.
Maybe this is what you are looking for http://docs.unity3d.com/ScriptReference/MonoBehaviour.OnLevelWasLoaded.html
Relying on Unity internal functioning is not always the way to go. Particularly when dealing with RESTApi (which is somehow what you are dealing with here).
You cannot assume one object will be ready before another except if you control it.
Add a Controller script that uses Awake. In the Awake, call all the methods you are needing and use some callback to generate secondary code when primary is ready.
public class MyController: MonoBehaviour{
private ServerRequestController serverCtrl = null;
private UIController uiCtrl = null;
private void Awake(){
serverCtrl = this.gameObject.AddComponent<ServerRequestController>();
uiCtrl =this.gameObject.AddComponent<UIController>();
serverCtrl.GetData(uiCtrl.SetUI);
}
}
public class UIController:MonoBehaviour{
public void SetUI(Data data)
{
SetTopImage(data.topImage);
SetBottomImage(data.bottomImage);
// And so on
}
}
public class ServerRequestController:MonoBehaviour{
public void GetData(Action onCompletion){
// This may be a coroutine if you fetch from server
Data data = GetDataFromSomewhere();
// At this point, your data is ready
onCompletion(data);
}
}
Thanks to this, you are now able to know exactly when a piece of code is ready.
A friend and myself are creating a Goosebumps-style adventure game, where at each stage the user is presented with a potential set of 4 choices, and the user's choice affects the outcome of the story.
What data structure should I use for this?
This is my main idea -- Objects
In trying to keep the game as close to the real life idea of these cards as possible, create one 'card' base class, and have lots of other cards inherit from this - superclass would contain Stringx5( x1story x4choiceStories) intx5 (x1CardIDNumber x4CardIDChoices).
This would then allow me to pump out objects easily with the material we already have, and have a system class controlling all the processing for user choices and displaying information onscreen. And again with the system in place and a base card class, it would allow for different stories in the future and whatnot. Trying to make this as reusable as possible and write as little code as possible (I'm not writing over a thousand if Statements.)
One thing that isn't clear to me (and the actual reason I'm posting this question in my inability to find the answer): isn't inheritance meant to be for other classes that are similar but with slight differences, e.g. managers and employees, making my idea completely wrong and a massive waste of memory?
I have looked into the following:
Hash tables: the examples seem to be more phone book oriented, and I don't think it would suit my needs
Abstraction to define a story type: also doesn't seem to suit my needs
No real need for inheritance as the cards are exactly the same, just the data on them changes. I'd use inheritance if there were special cards that need to behave differently to all the rest.
You can do what you want with something like this pseudo code:
class Card {
Card getChoice(int i); // returns choices[i]
string storyText;
Card[] choices; // Use an stl collection rather than an array for ease of addition.
}
Basically you create each card so it links to all the other cards (trick here is making sure you create the cards in the right order - easy solution: create them with no choices and add the different choices via an addChoice(Card) method later.
Your Game class starts with the first card (basically the head of a tree to all the cards), and does something like:
Card runCard(Card card)
{
Card nextCard = null;
showStoryText(card);
// Display a line for each choice in the card and get the user's response.
// Convert the response to the correct index.
int selection = promptForAction(card);
if (selection >= 0 && selection < card.numChoices()) {
nextCard = card.getChoice(selection);
}
return nextCard;
}
void run()
{
Card card = firstCard;
while(card != null) {
card = runCard(card);
}
}
This shouldn't be too bad. Essentially you need a tree structure.
Your main class could look like (forgive my lack of knowledge of c++)
class Node {
Node option1;
Node option2;
Node option3;
Node option4;
}
So your Node instances can point to other instances of Node.
It's probably better to have some sort of collection of Node instances, that way you can have as many or as few as you want. You can add a field to Node that indicates which option it is (1, 2, etc).
The only other thing you need is reference to the initial Node.
Let me see if I can articulate what I'm trying to do... I'll distill it to the core issue.
I have an objective-c program and a c callback function. The context is I am using cocos2d and chipmunk physics with the iphone sdk. What I am trying to do is update "score" upon a collision between a bullet and a monster. Everything works fine except for updating the score.
the game logic is in obj-c but the actual collision logic is done in a c function that gets called when things collide. For example, it is there that I render the flames/explosion of the collision. It is also there that I want to update the score.
Here's the problem:
But score is an instance variable of the "GAME" object and I do not have visibility into that instance variable. I suppose I can pass into the c function another parameter by reference called &addscore or something, but was wondering if there is a more obvious way to do it since there might be a bunch of other variables beyond 'score' that must be updated upon the collission.
the net is I need variables in the object to be seen by the c function, and vice versa: those variables set in the function to be seen in the object.
thanks in advance.
Your knowledge and thoughts about gaining access to Obj-C instance variables within C code by passing them by reference seems correct.
If you need to pass a number of variables I assume they collectively make up some kind of "game state" description. Perhaps these could be grouped into a seperate object or structure and passed into the C function via a single parameter?
As an example, the following class:
typedef struct GameState {
int score;
int numberOfBulletsLeft;
} GameState;
#interface GAME : NSObject {
GameState state;
}
...
#end
Would work well with a C function such as the following
void myCFunctionThatDoesCollisiondetectionEtc(GameState * state) {
NSLog(#"You have %d bullets left", state->numberOfBulletsLeft);
}
If your existing GAME object has suitable properties or messages, you may even be able to do something like the following, where you simply pass your entire Objective-C object:
void myCFunctionThatDoesCollisionDetectionEtc(GAME * myGame) {
if (...)
[myGame increaseScore:50];
else
[myGame decreaseScore:50];
}
A third alternative would be to change the return value of your C function to indicate if a collision has been detected and then leave it up to the Objective-C code within the GAME class to update the score and any other actions which may need to occur.
To improve on that last answer a bit more, you can do the following:
cpSpaceAddCollisionPairFunc( space, 1, 2, (cpCollFunc)functionName, game);
void functionName( cpShape *a, cpShape *b, cpContact *contacts, int numContacts, cpFloat normal_coef, GameClass *game) {
[game doSomethingToScoreSomething];
}
No need to cast the pointer inside of the function, you can cast the function pointer instead. That's what I've done internally with the Chipmunk source and it's a lot cleaner.
No, you do not need variables in your object to be visible by the function. That breaks encapsulation, and it's a bad idea. When you want an object to do something (like changing some internal value such as the score) you should provide a method to accomplish that effect.
If you allow code outside your class to alter your instance variables, then you're throwing away a key advantage of object-oriented programming.
If the game object is a singleton you can access it from any scope (which includes your C callback). You would make a singleton if you only ever want one instance of some object to exist. A singleton can always be reached from anywhere by sending a message to the class to retrieve the singleton instance:
[Game sharedGameInstance];
Alternatively, chipmunk allows for you to pass a void * data to the callback. This is to accommodate the programmer to send information he needs to the callback.
You can send a pointer to your game object instance in that void * to the callback, like so:
cpSpaceAddCollisionPairFunc( space, 1, 2, &functionName, (void *)game );
void functionName( cpShape *a, cpShape *b, cpContact *contacts, int numContacts, cpFloat normal_coef, void *data ) {
GameClass * game = (GameClass *)data;
// do whatever you need here. You can call messages on game as per usual.
}