- Home /
What is a general strategy for making a multiplayer scoring system using in-game sprites instead of UI elements?
I am making a basketball shooting game, and in the Scene there is a Scoreboard
GameObject that shows 1-4 players' scores in real-time as they score two-pointers. The scores for each player will consist of 3 numbers (so, starting by default at 000), and increments by 2 for every time OnGoal
event is triggered, by changing the first 0 sprite into a 2 sprite, and so on.
So, in contrast to many multiplayer scoring scripts, mine will not be working with Text
UI objects representing score numbers, but with in-game sprites / GameObjects that are Instantiated from number prefabs.
Each of the 3 sprites is parented to a field
transform (attached to an empty GameObject) which sits on the Scoreboard
. This is used to determine the position of a digit, as well as which digit is to be incremented to increase the score by 2. Here is my current ScoreManager
script:
public class ScoreManager : MonoBehaviour
{
[SerializeField]
GameObject[] loadedNumbers; // load the number sprite prefabs
List<GameObject> numbers; // instantiate the loaded numbers
public Transform[] field; // 3 fields for a max score of 999
GameObject[] activeObj; // the objects being currently used to represent a score
int scores = 0; // the current score
public static ScoreManager data;
// Score Colors
[SerializeField] private Material[] scoreColorMats;
// Start is called before the first frame update
void Start()
{
data = this;
activeObj = new GameObject[field.Length];
numbers = new List<GameObject>();
for (int i = 0; i < loadedNumbers.Length; i++)
{
numbers.Add(Instantiate(loadedNumbers[i], new Vector3(100,100,100), Quaternion.identity, transform));
}
for (int i = 0; i < numbers.Count; i++) // this is just used to color the sprites according to the different players
{
numbers[i].GetComponent<SpriteRenderer>().material = scoreColorMats[0];
}
SetValue(scores);
}
public void Inc() //increments the player score by 2
{
Clear();
if (scores < 999)
{
scores += 2;
}
SetValue(scores);
}
public void Dec() //decrements the player score
{
if (scores > 0)
{
scores--;
}
SetValue(scores);
}
void Clear()
{
for (int i = 0; i < field.Length; i++)
{
Destroy(activeObj[i]);
}
}
void SetValue(int scores)
{
int Convert = 1;
for (int i = 0; i < field.Length; i++)
{
int scoreConvert = (scores / Convert) % 10;
Print(i, scoreConvert, i);
Convert *= 10;
}
}
void Print(int activeObj, int scores, int field)
{
this.activeObj[activeObj] = Instantiate(this.numbers[scores], this.field[field].position, this.field[field].rotation);
this.activeObj[activeObj].name = this.field[field].name;
this.activeObj[activeObj].transform.parent = this.field[field];
}
// Update is called once per frame
void Update()
{
}
}
And here is where the Inc
method is actually called from a separate script called ShootManager
. We instantiate the class ScoreManager
script as a variable sm
:
void Goal(float distance, float height, bool floored, bool clear, bool special, PhotonView view)
{
Debug.Log("SCORED");
sm.Inc(); // increment score
showTwoPoints(view);
}
I am using Photon
to send this player score data across a network, so I will also need to use RPCPun
and RaiseEvent
calls. But just knowing how to handle all these sprites will be a good start if you are not familiar with Photon
.
The reason I ask for a "general" strategy is that I know that there are potentially multiple ways to go about this. Scoping and access are also not my strong suit, and so I would like to get a picture of how my ScoreManger script might handle the changing of sprite numbers for multiple players across a Photon network. Thanks in advance for any guidance!