- Home /
Architecture for a turn based game
Hello again. I would like your opinion on an issue that has been troubling me for about a week.
I'm building a turn based game for unity but I've been running into some problems trying to find the correct code architecture to implement it. It roughly works like this:
Player starts his turn
Pre-turn calculations get done
A unit is activated
the player chooses the skill for that unit to use
the game runs a simulation and figures out which enemy units will see the current unit (if he tells the unit to run around a corner, enemies might see it)
the enemy units react and choose what to do
the "order" is executed and it's effects are applied (enemies shoot the player's unit, etc)
Player continues selecting units until his turn ends
repeat for another player
This is meant to later be used for multi player so I can't combine 6 and 7 for instance (the opponent decides how his own units react)
Each skill has a different way to handle the GUI: move asks the player to click and setup the unit's path, shoot asks him to click an enemy unit and choose what to use against it, so I created a GameGUI class which calls a "ProcessSkill" method unique to every skill.
Here's where it gets complicated: since I have coroutines to handle the turn structure and GameGUI using it's OnGUI method to handle steps 3,4 and 6 it's a synchronization nightmare.
was actually a bug, ignore this-->(Not to mention I'm starting to experiment with step 5 and coroutine is really weird with movement speed for some reason compared to a regular Update method.)
Does the Unity answers community have any tips on this? I'm a lot more used to linear programming where this isn't an issue...
I could post code snippets but I feel this post is already too long.
Edit: here we go:
This is what I put in GameGUI. It handles all GUI drawing:
public void OnGUI(){
GUI.TextField(new Rect(Screen.width-80,Screen.height-60,80f,20f),"Orders: "+GameLogic.instance.currentPlayer.numOrders);
//If no order is pending, do what we usually do
if(!GameLogic.instance.currentPlayer.ProcessOrder() ) {
//Handle unit selection, etc
MousePosition();
if (!GameLogic.instance.currentPlayer.turnComplete) {
if (GUI.Button(new Rect(Screen.width-100,Screen.height-40,100,40),"End turn"))
GameLogic.instance.currentPlayer.turnComplete=true;
}
}
//Display a help message (placeholder)
GUI.TextField(new Rect(0,Screen.height-40,500,40),"Message: "+msg);
}
ProcessOrder() calls the skill-dependant gui code. Here's what I'm using for Movement for instance:
public override bool ProcessingSkill(Order cont) {
if (pathComplete==false && remainingDistance>0) {
if (GUI.Button(new Rect(Screen.width-100,Screen.height-40,100,40),"Finish")) {
pathComplete=true;
}
GameLogic.instance.movementRadius.GetComponent<MovementRadius>().CreateSingleCircle(
path.lastWaypoint.marker,
remainingDistance
);
WaypointAdding();
return true;
}
else {
pathComplete=true;
GameLogic.instance.movementRadius.GetComponent<MovementRadius>().Disable();
return false;
}
}
And this is how I handle the rest of the game logic. ManageGame is a Coroutine which begins at the start of the game
IEnumerator ManageGame () {
for(;;) { //insert win condition here or something
Debug.Log("Turn cycle loop");
foreach(Player p in playerList) {
currentPlayer=p;
//Start our player loop, and wait for it to finish
//Before we continue.
yield return StartCoroutine(PlayerTurn(p));
}
//restart loop
}
}
IEnumerator PlayerTurn(Player player) {
player.ResetAndRecalculate();
while (!player.turnComplete) {
while (true/*player.activeOrder.complete==false*/) {
yield return null;
}
yield return null;
}
yield break;
}
Code snippets are always welcome...it's the run-away paste all you code that will surely have people close the tab as soon as it opens. :)
As for your statement that you OnGUI handles things in-game...well, don't do that! OnGUI should only draw you GUI; you should have no game-type logic in there because OnGUI is executed several times per-frame.
Coroutines play nice with other code, and work exactly like an Update loop (in fact, coroutines are injected into the Unity runtime just the same as update functions are). Let's see some code, and we might be able to get this ball rolling.
The reason I'm using OnGUI for "game logic" is because I have to raycast from the mouse position to detect what I'm clicking and I can't do it properly outside of an OnGUI call.
I'll post my code as soon as I get to my main PC then.
Your answer
Follow this Question
Related Questions
how do you create a grid to move your character within? one square a turn... 0 Answers
How To calculate the points of a curved movement path with steering constraints? (2D) 0 Answers
Networking and UI Buttons 1 Answer
turn-base rpg navmesh, plane,terrain, scene 0 Answers
Is it necessary to build my iphone app with armv7 architecture? 1 Answer