My project has become unmanageable. I have a question for the elite. Should i break all my code down (currently in 3 scripts) down into a script per function ? Would this allow better organization and better coding practices ?
You should not have one script for each function. Instead, you should have each class be self-contained for what you are trying to achieve. If you are making a Pong style game, that would mean a script for the player controls, a script for the ball, a script for the scoreboard, a script for the sound, etc. Breaking down your code so its one script per function would arguably make your code even harder to manage.
Can you provide us the scripts you are using? That will be very beneficial in teaching you a better way to split them apart.
using UnityEngine;
using UnityEngine.UI;
public class SceneController : MonoBehaviour
{
public enum HighHands
{
None,
One_Pair,
Three_Of_A_Kind,
Two_Pair,
Four_Of_A_Kind,
Three_Pair,
Full_House,
Two_Sets_Of_Three,
Five_Of_A_Kind,
Straight,
Six_Of_A_Kind,
}
public Dice[] dices;
public Text handText;
int onepair = 100;
int threekind = 150;
int twopair = 250;
int fourKind = 400;
int threepair = 1000;
int fullhouse = 1000;
int twosets = 1500;
int fivekind = 1500;
int straight = 2500;
int sixkind = 5000;
public bool HasOnePair = false;
public bool HasTwoPair = false;
public bool HasThreePair = false;
public bool HasTwoSets = false;
public bool HasFullhouse = false;
public bool HasThreeKind = false;
public bool HasFourKind = false;
public bool HasFiveKind = false;
public bool HasSixKind = false;
public bool HasStraight = false;
public void RollDice_Click()
{
for (int i = 0; i < dices.Length; i++)
{
if (dices[i].hold == false)
dices[i].ShowRandomFace();
}
HighHands hand = DetectHighHands(dices);
handText.text = hand.ToString();
}
int[] repeats;
private HighHands DetectHighHands(Dice[] dices)
{
repeats = new int[6];
int stars = 0;
// find out how many times each number is repeated
for (int i = 0; i < dices.Length; i++)
{
if (dices[i].faceIndex == 0) // star dice
stars++;
else // regular dice
repeats[dices[i].faceIndex - 1]++;
}
return _DetectHighHandRecursive(repeats, stars);
}
private HighHands _DetectHighHandRecursive(int[] repeats, int stars)
{
// if it has stars then we should check all posibility for every star we have
if (stars > 0)
{
// we keep the best hand possible in this variable
HighHands bestHand = HighHands.None;
for (int i = 0; i < 6; i++)
{
// consider the first star a number (i) and check with that
repeats[i]++;
HighHands HypotheticalHand = _DetectHighHandRecursive(repeats, stars - 1);
// get back that hypothetical number to check the next number
repeats[i]--;
// if the this hand is better than the best hand, then we have a new best hand
if (HypotheticalHand > bestHand)
bestHand = HypotheticalHand;
}
return bestHand;
}
else // if we don't have any stars, then we check the hand old fashioned way
return DetectHighHandsWithHypotheticalNumbers(repeats);
}
private HighHands DetectHighHandsWithHypotheticalNumbers(int[] repeats)
{
bool four = false;
bool two = false;
int threes = 0;
for (int i = 0; i < repeats.Length; i++)
{
// is there a number with 4 repeats?
if (repeats[i] == 4)
four = true;
// is there a number with 2 repeats?
if (repeats[i] == 2)
two = true;
// how many sets of threes do we have?
if (repeats[i] == 3)
threes++;
}
if (four && two) // 4 twos and 2 threes
{
HasFullhouse = true;
return HighHands.Full_House;
}
if (threes == 2)// 2 sets of three
{
HasTwoSets = true;
HasSixKind = false;
HasFullhouse = false;
return HighHands.Two_Sets_Of_Three;
}
// detect if there is one of each number - straight
bool DoesHaveStraight = true;
for (int i = 0; i < repeats.Length; i++)
{
if (repeats[i] != 1)
{
DoesHaveStraight = false;
break;
}
}
if (DoesHaveStraight)
{
HasStraight = true;
return HighHands.Straight;
}
// detect if it is a straight hand
for (int i = 0; i < repeats.Length; i++)
{
if (repeats[i] == 6)
{
HasSixKind = true;
return HighHands.Six_Of_A_Kind;
}
else
{
}
if (repeats[i] == 5)
{
HasFiveKind = true;
return HighHands.Five_Of_A_Kind;
}
else
{
}
if (repeats[i] == 4)
{
HasFourKind = true;
return HighHands.Four_Of_A_Kind;
}
else
{
}
if (repeats[i] == 3)
{
HasThreeKind = true;
return HighHands.Three_Of_A_Kind;
}
else
{
}
}
// find the number of pairs
int pairs = 0;
for (int i = 0; i < repeats.Length; i++)
{
if (repeats[i] == 2)
pairs++;
}
if (pairs == 3)
return HighHands.Three_Pair;
else if (pairs == 2)
return HighHands.Two_Pair;
else if (pairs == 1)
return HighHands.One_Pair;
else
return HighHands.None;
}
public void BankScore()
{
if (HasSixKind)
{
Debug.Log("Has Six of A Kind");
AddScore.score += sixkind;
}
else if (HasFullhouse)
{
Debug.Log("Has Full House");
AddScore.score += fullhouse;
}
else if (HasStraight)
{
Debug.Log("Has Straight");
AddScore.score += straight;
}
else if (HasTwoSets)
{
Debug.Log("Has Two Sets of three");
AddScore.score += twosets;
}
else if (HasTwoPair)
{
Debug.Log("Has Two pair");
AddScore.score += twopair;
}
else if (HasThreePair)
{
Debug.Log("Has Three Pair");
AddScore.score += threepair;
}
else if (HasFiveKind)
{
Debug.Log("Has Five of A Kind");
AddScore.score += fivekind;
}
else if (HasFourKind)
{
Debug.Log("Has Four of A Kind");
AddScore.score += fourKind;
}
else if (HasThreeKind)
{
Debug.Log("Has Three of A Kind");
AddScore.score += threekind;
}
}
}
using UnityEngine;
using UnityEngine.UI;
public class Dice : MonoBehaviour
{
public Image myImage;
public Color holdColor;
public Sprite[] faceSprites;
public int faceIndex = 0;
public bool hold = false;
public bool IsLocked = false;
public void Dice_Click()
{
hold = !hold;
if (hold)
myImage.color = holdColor;
else
myImage.color = Color.white;
}
public void DiceIsLocked()
{
if (hold)
IsLocked = true;
myImage.color = Color.red;
}
public void ResetDice()
{
hold = false;
myImage.color = Color.white;
faceIndex = 0;
myImage.sprite =faceSprites[faceIndex];
}
public void ShowRandomFace()
{
faceIndex = Random.Range(0, 7);
myImage.sprite = faceSprites[faceIndex];
}
// for testing
public void ShowNumber(int p)
{
faceIndex = p;
myImage.sprite = faceSprites[faceIndex];
}
}
Organization looks OK at a very quick first glance.
I usually have one class called GameController that understands the complete rules of the game and then I create smaller classes for individual objects within the game. That looks pretty much what you have done here. Splitting out your game rules into multiple files is not going to help organisation at all. Use intelligent naming of functions and have a quick way to search for references to functions and get to a particular function by name quickly to help stay organized in large classes/files.
Definitely don’t break down your code into one script per function. There is no hard and fast rule for breaking down functions into scripts, you have to figure out for yourself the best way of organising your code. You said you have 3 scripts and you’ve posted two which aren’t that big. They look ok to me, how is it that it’s become unmanageable?
I like to have a single script for a specific set of related tasks. Everything in that script should be related in some core way to everything else in the script. If you find that you have a single script that is doing a few completely different and unrelated things, that is a good candidate for splitting it up. From the other direction, if you have a couple scripts on the same gameobject that are very interrelated, and are both needed to perform most tasks from either script, that is a candidate for combining them into a single script.