Creation of a score system in unity - c#

I am currently developing a simple 2D game to learn many things about game development.
Nevertheless, I have some issues to create a score system.
I want to update the score every second, and adding 1 point for each second, and stop the count when the game is over.
I start to write this
public class scoremanager : MonoBehaviour {
public int score;
public GUIText distance;
void Start () {
score = 0;
}
void Update () {
StartCoroutine(updateScoreManager(1f, 1));
distance.text = score.ToString();
}
IEnumerator updateScoreManager(float totalTime, int amount) {
score += amount;
yield return new WaitForSeconds (totalTime);
}
}
The issues are that nothing shows up in the GUIText so I don't know if it works. And how can I stop the count when the game is over?

First off, I think you should use uGUI since that's Unity's accepted solution for UI now: http://blogs.unity3d.com/2014/05/28/overview-of-the-new-ui-system/
I can't really say what the problem is with your GUIText since I don't know if the position is off or whatever but I can tell you how to manage the counting better.
You don't need to use the Update function, using the update function defeats the purpose of using a Coroutine to update your text. Using a Coroutine gives you some control over when it starts Updating and when it stops. So one solution is to get rid of the Update function entirely so you can control it better:
public class scoremanager : MonoBehaviour {
public int score;
public GUIText distance;
private Coroutine scoreCoroutine;
void Start () {
score = 0;
scoreCoroutine = StartCoroutine(updateScoreManager(1f, 1));
}
IEnumerator updateScoreManager(float totalTime, int amount) {
while(true) {
score += amount;
distance.text = score.ToString();
yield return new WaitForSeconds (totalTime);
}
}
// example of ending game
void EndGame() {
StopCoroutine(scoreCoroutine);
scoreCoroutine = null;
}
}
This might look weird (why am I using an infinite loop)? But that's the beauty of Coroutines, you can write code like this since the yield statement allows you to return from the code and come back to the same spot later. Normally a while loop would cause your game to crash, but a yield statement let's your create a time while loop!
Hope this helped!

I can see few glitches in your code. Let's cover it first.
You are calling Coroutine in Update with delay time of 1 second. This means your Coroutine is executing 30 or 60 times per second.
You are assigning text in Update too. This may be the reason that it refreshes the text (Not sure about this)
In your Coroutine your delay i.e. WaitForSeconds is of no use here, as nothing is happening after that line of code.
I'm modifying your exact code so that you can understand that what you want can be achieved by this too :)
public class scoremanager : MonoBehaviour {
public int score;
public GUIText distance;
public bool isGameOver = false;
void Start () {
score = 0;
StartCoroutine(updateScoreManager(1f, 1));
}
void Update () {
}
IEnumerator updateScoreManager(float totalTime, int amount) {
while(!isGameOver){
score += amount;
distance.text = score.ToString();
yield return new WaitForSeconds (totalTime);
}
}
}
What are the changes...
No code in Update.
Call Coroutine only once.
In Coroutine it is changing the score and distance both, once per totalTime second(s). Until the isGameOver flag is false. Just make it true when your game is over.

I guess simple solution to your problem is InvokeRepeating
//Invokes the method methodName in time seconds, then repeatedly every repeatRate seconds.
public void InvokeRepeating(string methodName, float time, float repeatRate);
So your transfomed code colud be
public class scoremanager : MonoBehaviour {
public int score;
public GUIText distance;
void Start () {
InvokeRepeating("updateScoreManager",1f,1f);
}
void Update () {
distance.text = score.ToString();
}
void updateScoreManager() {
score += 1;
}

The issues are that nothing shows up in the GUIText so I don't know if
it works
What happens? Is it always zero or nothing is displayed? If nothing - check coordinates, layer etc. to ensure you positioned it properly. Refere to http://docs.unity3d.com/Manual/class-GUIText.html
And how can I stop the count when the game is over?
Use StopCoroutine(updateScoreManager) on game over event and don't forget to set score to zero.
Actually saying your code design is not good. It would be great to implement State, Observer, Component patterns. With state you can implement game states like Game, GameOver. With Observer you can notify your scores component. With component you serve single responsibility principle by placing score logics to score component.
At least consider separate start game initialization, update component, and game over logics.

I'm going the skip the lecture on the pattern you are implementing because I don't know what the rest of your code looks like, but the source of your update problem is here:
IEnumerator updateScoreManager(float totalTime, int amount)
{
score += amount;
yield return new WaitForSeconds(totalTime);
}
In practice, when I run into these kinds of issues I separate the failing logic from the source application to help reduce the amount of noise.
So, when I prototype your algorithim (code below) what happens is that score is always zero because the StartCoroutine should be using the return value of updateScoreManager to do the updating when ever .Update() is called.
If my prototyping seems to match how you are trying to implement this code, then I can post how I would fix this later.
But basically, instead of returning IEnumerator return an int that updates the score and that might get you past this issue.
Unless you can describe the use-case where you need the IEnumerator somewhere else in the codes?
Execute Prototype:
class Program
{
static void Main(string[] args)
{
Ans34612672 Ans34612672 = new Ans34612672();
Ans34612672.Execute();
Console.ReadKey();
}
}
Prototype Wrapper Class:
public class Ans34612672
{
public Ans34612672()
{
}
public bool Execute()
{
bool retValue = false;
scoremanager Manager = new scoremanager();
Manager.Start();
while(Manager.score < 20)
{
Manager.Update();
}
Console.WriteLine(Manager.distance);
Console.ReadKey();
return retValue;
}
}
Prototype Classes:
public class scoremanager : MonoBehaviour
{
public int score;
public GUIText distance;
public void Start()
{
score = 0;
distance = new GUIText();
}
public void Update()
{
IEnumerator UpdateResults = updateScoreManager(1f, 1);
StartCoroutine(UpdateResults);
distance.text = score.ToString();
}
private void StartCoroutine(IEnumerator enumerator)
{
//Implement Logic
}
IEnumerator updateScoreManager(float totalTime, int amount)
{
score += amount;
yield return new WaitForSeconds(totalTime);
}
}
internal class WaitForSeconds
{
private float totalTime;
public WaitForSeconds(float totalTime)
{
this.totalTime = totalTime;
}
}
public class GUIText
{
internal string text;
}
public class MonoBehaviour
{
}

Related

How to Make power ups reusable in unity's karting microgame?

I'm modifying unity's karting microgame and I wanted to make the speed-pads able to be used more than once because the way they are programmed makes it so that they can only be used up until the MaxTime "x" amount of seconds is reached. The player can even pick up the power-up after the MaxTime is reached but it doesn't do anything...
I strongly suggest you download the karting microgame to have a better view of the issue but here is the code for the power-up:
using KartGame.KartSystems;
using UnityEngine;
using UnityEngine.Events;
public class ArcadeKartPowerup : MonoBehaviour {
public ArcadeKart.StatPowerup boostStats = new ArcadeKart.StatPowerup
{
MaxTime = 5f
};
public bool isCoolingDown { get; private set; }
public float lastActivatedTimestamp { get; private set; }
public float cooldown = 5f;
public bool disableGameObjectWhenActivated;
public UnityEvent onPowerupActivated;
public UnityEvent onPowerupFinishCooldown;
private void Awake()
{
lastActivatedTimestamp = -9999f;
}
private void Update()
{
if (isCoolingDown)
{
if (Time.time - lastActivatedTimestamp > cooldown)
{
//finished cooldown!
isCoolingDown = false;
onPowerupFinishCooldown.Invoke();
}
}
}
private void OnTriggerEnter(Collider other)
{
if (isCoolingDown) return;
var rb = other.attachedRigidbody;
if (rb) {
var kart = rb.GetComponent<ArcadeKart>();
if (kart)
{
lastActivatedTimestamp = Time.time;
kart.AddPowerup(this.boostStats);
onPowerupActivated.Invoke();
isCoolingDown = true;
if (disableGameObjectWhenActivated) this.gameObject.SetActive(false);
}
}
}
}
I'm did not manage to place the kart code here because it goes over the character limit, but you can easily check it out by downloading the karting microgame in Unity Hub! In this context, the Kart's script serves the function of provinding the stats that can be boosted.
The idea that I had that might (or not) work is to make it so that every time the "isCollingDown" returns just add another variable that controls how long the effect lasts to the MaxTime variable, something like "MaxTime = MaxTime + EffectDuration." But I don't know how to implement this...
I'm sorry if there is a very obvious answer to this issue but I really don't understand a lot about scripts!
It actually already has a function build in for what you want to achive so you do not have to code anything.
You see the property disableGameObjectWhenActivated. This one should be set true right now. Just set it false and it will have a cooldown instead of beeing disabled afterwards. Now if you want to get rid of the cooldown I would just set the cooldown to 0.

How can I tell when a number has finished increasing?

I feel like I'm missing some easy solution here, but I'm stuck on this. I'm calculating a score based on how far the player travels until they hit a building at the end of the course. The destruction score is separate from the distance score, and it increments until all of the building pieces have come to a rest.
I have an animation I want to play to add the distance score to the total destruction score and give the player's overall score, but I need the animation to trigger once the destruction score has stopped increasing. Right now, each piece of the building has code that checks if its moving and increments the score while true.
public class SkiLodgeScoreTracker : MonoBehaviour
{
Rigidbody rb;
private GameObject[] score;
private void Start()
{
rb = gameObject.GetComponent<Rigidbody>();
score = GameObject.FindGameObjectsWithTag("Score");
}
private void Update()
{
//check if lodgePiece is moving, while it is, add to Score object
if(rb.velocity.magnitude >= 2f && !rb.isKinematic)
{
score[0].GetComponent<SkiScore>().addToSkiScore(2f);
}
}
}
Here's where I want to have the animation trigger once that score has stopped (this was another attempt I made, the logic doesn't work)
public Animator moveScore;
...
if(skiScore > 0)
{
previousScore2 = previousScore1;
previousScore1 = skiScore;
if(previousScore1 == previousScore2 && !scoreMoved)
{
moveScore.SetTrigger("EndCourse");
addScoreToSkiScore();
}
}
public void addScoreToSkiScore()
{
scoreMoved = true;
for(float i = score; i>0; i--)
{
skiScore += 1;
}
}
I wanted to grab the score on one frame and see if it equals the score on the next frame and, if so, then trigger the animation, but I feel like that's not a valid option.
Any ideas?
In SkiScore, keep track of how many pieces are moving, and when a piece stops and the count becomes 0, do your thing:
public class SkiScore : MonoBehaviour
{
int movingCount;
void Start()
{
ResetMovingCount();
/* ... */
}
public void ResetMovingCount() {movingCount = 0;} // call as needed
public void OnStartedMoving() {++movingCount;}
public void OnStoppedMoving()
{
if (--movingCount == 0) OnNoneMoving();
}
void OnNoneMoving() {/* do the thing */}
/* ... */
}
For each piece, use a flag to remember if it has moved recently and if it has, and it's no longer moving, let your score manager know:
public class SkiLodgeScoreTracker : MonoBehaviour
{
Rigidbody rb;
private GameObject[] score;
// flag used to recognize newly stopped movement
bool recentlyMoving;
// cache for GetComponent
SkiScore mySkiScore
private void Start()
{
rb = gameObject.GetComponent<Rigidbody>();
score = GameObject.FindGameObjectsWithTag("Score");
// GetComponent is expensive, try not to call it in Update unless necessary
mySkiScore = score[0].GetComponent<SkiScore>();
}
private void Update()
{
//check if lodgePiece is moving, while it is, add to Score object
if(rb.velocity.magnitude >= 2f && !rb.isKinematic)
{
mySkiScore.addToSkiScore(2f);
recentlyMoving = true;
mySkiScore.OnStartedMoving();
}
else if (recentlyMoving)
{
recentlyMoving = false;
mySkiScore.OnStoppedMoving();
}
}
}

Getting print to only print once when countdown Deltatime reaches certain number (Unity)

I have a 10-second countdown script that runs on DeltaTime.
In my Update function, I'm trying to make it print, only once, "Hello" whenever it reaches second 8.
The problem is that deltaTime is repeatedly printing "Hello" while it hangs on the 8th second, rather than only printing once, and I don't know how to stop that behavior.
I kept trying to introduce triggers in the if-block that set to 0 as soon as the block is entered but it still keeps continuously printing "Hello" so long as the timer is on second 8.
Countdown Timer
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class CountdownTimer : MonoBehaviour
{
float currentTime = 0f;
float startingTime = 10f;
public int n = 0;
public int switcher = 0;
// Start is called before the first frame update
void Start()
{
currentTime = startingTime;
}
// Update is called once per frame
void Update()
{
currentTime -= 1 * Time.deltaTime; //does it each frame
n = Convert.ToInt32(currentTime);
if (n == 8)
{
switcher = 1;
}
}
}
Update Method in different class
if (CountdownTimer.switcher == 1)
{
CountdownTimer.switcher = 0;
print("hey");
}
Any ideas on how to make print("hey") only happen once? It's important because later I would replace the print code with an important method and I need to make sure the method happens only once.
This is where you want to implement a system of subscriber with event/listener.
Add an event to the countdown, if countdown is meant to be unique, you can even make it static. Also, if the update is no longer needed after the setting of switcher to 1 then you can convert that to coroutine
public class CountdownTimer : MonoBehaviour
{
float currentTime = 0f;
float startingTime = 10f;
public static event Action RaiseReady;
// Start is called before the first frame update
void Start()
{
currentTime = startingTime;
StartCoroutine(UpdateCoroutine());
}
// Update is called once per frame
IEnumerator UpdateCoroutine()
{
while(true)
{
currentTime -= 1 * Time.deltaTime; //does it each frame
int n = Convert.ToInt32(currentTime);
if (n == 8)
{
RaiseReady?.Invoke();
RaiseReady = null; // clean the event
yield break; // Kills the coroutine
}
yield return null;
}
}
}
Any component that needs to know:
public class MyClass : MonoBehaviour
{
void Start()
{
CountdownTimer.RaiseReady += CountdownTimer_RaiseReady;
}
private void CountdownTimer_RaiseReady()
{
Debug.Log("Done");
// Remove listener though the other class is already clearing it
CountdownTimer.RaiseReady -= CountdownTimer_RaiseReady;
}
}
The solution #Everts provides is pretty good, but as you are using unity I would recommend a couple of tweaks to play nicer with the editor. Instead of a generic event I recommend using a UnityEvent from the UnityEngine.Events namespace. I would also advise against statics due to how unity goes about serializing them across scenes. There are some weird edge cases you can get into if you aren't familiar with how unity handles their serialization. If you just need to send a message to another object in the same scene I would actually recommend a game manager. You can safely do a GameObject.Find() in onvalidate() and link your variables to avoid a performance hit at runtime doing the find. If that data needs to carry across to a different scene for this message then use a ScriptableObject instead. It would look something like below.
Put this component on the scene's "Game Manager" GameObject
public class CountingPassthrough : MonoBehaviour
{
public CountdownTimer countdownTimer;
}
put this component on the scene's "Timer" GameObject
public class CountdownTimer : MonoBehaviour
{
public float startingTime = 10f;
public UnityEvent timedOut = new UnityEvent();
private void OnValidate()
{
if(FindObjectOfType<CountingPassthrough>().gameObject.scene == gameObject.scene && FindObjectOfType<CountingPassthrough>() != new UnityEngine.SceneManagement.Scene())
FindObjectOfType<CountingPassthrough>().countdownTimer = this;
}
private void Start()
{
StartCoroutine(TimerCoroutine());
}
// Coroutine is called once per frame
private IEnumerator TimerCoroutine()
{
float currentTime = 0f;
while (currentTime != 0)
{
currentTime = Mathf.Max(0, currentTime - Time.deltaTime);
yield return null;//wait for next frame
}
timedOut.Invoke();
}
}
Put this component on the GameObject you want to use the timer
public class user : MonoBehaviour
{
[SerializeField, HideInInspector]
private CountingPassthrough timerObject;
private void OnValidate()
{
if(FindObjectOfType<CountingPassthrough>().gameObject.scene == gameObject.scene && FindObjectOfType<CountingPassthrough>() != new UnityEngine.SceneManagement.Scene())
timerObject = FindObjectOfType<CountingPassthrough>();
}
private void OnEnable()
{
timerObject.countdownTimer.timedOut.AddListener(DoSomething);
}
private void OnDisable()
{
timerObject.countdownTimer.timedOut.RemoveListener(DoSomething);
}
private void DoSomething()
{
//do stuff here...
}
}
This workflow is friendly to prefabs too, because you can wrap the find() in onvalidate() with if(FindObjectOfType<CountingPassthrough>().gameObject.scene == gameObject.scene) to prevent grabbing the wrong asset from other loaded scenes. And again, if you need this to carry data across scenes then have CountingPassthrough inherit from ScriptableObject instead of MonoBehaviour, create the new ScriptableObject to your project folder somewhere, and ignore that extra if check to constrain scene matching. Then just make sure you use a function to find it that includes assets if you use the cross-scene ScriptableObject approach.
EDIT:Forgot nested prefabs edgecase in unity 2018+ versions. You need to add this to account for it: && FindObjectOfType<CountingPassthrough>() != new UnityEngine.SceneManagement.Scene() I've updated the code snippet above. Sorry about that.
Since Updtade() is called once per frame, then switcher is set to 1 once per frame during the 8th second (and there is a lot of frames in 1 sec).
An answer could be something like this to prevent it from printing again :
if (CountdownTimer.switcher == 1)
{
if (!AlreadyDisplayed)
{
print("hey");
AlreadyDisplayed = true;
}
}
Where AlreadyDisplayed is a Boolean set to false when declared.
This should do what you want to achieve. :)

How to achieve awareness of "kill" events in a scene

I have been doing a RPG game in Unity with C # and when doing a system of quests, specifically those of killing a certain number of enemies, I found the problem of having 3 enemies in the scene and being the target of the quest: Kill 3 enemies. If I kill them before activating the quest and later active the quest does not give me the reward (in this case experience). How can I tell the enemies and make that if the quest detects that I have already killed the necessary enemies to get the quest give me the reward equally?
Here the two needed scripts i think:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class QuestObject : MonoBehaviour {
public int questNumber;
public QuestManager qManager;
public string startText;
public string endText;
public bool isItemQuest;
public string targetItem;
public bool isEnemyQuest;
public string targetEnemy;
public int enemiesToKill;
private int enemyKillCount;
private PlayerStats playerStats;
public int EXPToGive;
void Start () {
playerStats = FindObjectOfType <PlayerStats> ();
}
void Update () {
if (isItemQuest) {
if (qManager.itemCollected == targetItem) {
qManager.itemCollected = null;
EndQuest ();
}
}
if (isEnemyQuest) {
if (qManager.enemyKilled == targetEnemy) {
qManager.enemyKilled = null;
enemyKillCount++;
}
if (enemyKillCount >= enemiesToKill) {
EndQuest ();
}
}
}
public void StartQuest (){
qManager.ShowQuestText (startText);
}
public void EndQuest (){
qManager.ShowQuestText (endText);
playerStats.AddEXP (EXPToGive);
qManager.questCompleted [questNumber] = true;
gameObject.SetActive (false);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyHealth : MonoBehaviour {
public int startingHealth;
public int currentHealth;
public GameObject damageBurst;
private PlayerStats playerStats;
public int EXPToGive;
public string enemyQuestName;
private QuestManager qManager;
void Start ()
{
// Setting up the references.
//anim = GetComponent <Animator> ();
//enemyAudio = GetComponent <AudioSource> ();
//enemyMovement = GetComponent <EnemyMovement> ();
//enemyAttacking = GetComponentInChildren <EnemyAttack> ();
// Set the initial health of the player.
currentHealth = startingHealth;
playerStats = FindObjectOfType <PlayerStats> ();
qManager = FindObjectOfType <QuestManager> ();
}
void Update ()
{
if (currentHealth <= 0) {
qManager.enemyKilled = enemyQuestName;
Destroy (gameObject);
playerStats.AddEXP (EXPToGive);
}
}
public void TakeDamage (int amountDamage)
{
// Reduce the current health by the damage amount.
currentHealth -= amountDamage;
Instantiate (damageBurst, transform.position, transform.rotation);
}
public void SetMaxHelth () {
currentHealth = startingHealth;
}
}
One Aproach would be to create some type of "WorldManager" which counts every Enemy which has been slain. And when Starting a quest this quest could check the WorldManagers kill count and add it to it's own count.
public void StartQuest (){
qManager.ShowQuestText (startText);
this.enemyKillCount += worldManager.GetKillCount();
}
In your enemy class you have to add a kill to your worldManager.
void Update ()
{
if (currentHealth <= 0) {
qManager.enemyKilled = enemyQuestName;
this.worldManager.AddKill(this)
Destroy (gameObject);
playerStats.AddEXP (EXPToGive);
}
}
Alternative:
Make your QManager be aware of every kill in a Scene.
You can achieve this through many ways.
One of them is passing your EnemyObject an reference of your Qmanager and do the same as with the "WorldManager" provided above, or you use Messaging and fire a Message targeting the QManager when an enemy is slain.
Alternative 2:
Throw an Event when an enemy has been slain and subscribe to it on your QManager/WorldManager. This way u can reuse your enemy class in every game. From my point of view static dependencies are evil, but there are many discussions and SO and everywhere on the internet about that.
You can several approach. The most straight-forward is to use static.
The purpose of static is for the variable/method to belong to the class instead of an instance of the class.
In your case, you want each enemy to have its own health, this cannot be static.
And you want to count how many instances there are in the scene from the class. So static is fine.
public class Enemy:MonoBehaviour
{
private static int enemyCount = 0;
public static int EnemyCount {get{ return enemyCount;} }
public event Action<int> RaiseEnemyDeath;
public static void ResetEnemyCount(){
enemyCount = 0;
}
private int health;
public void Damage(int damage)
{
CheckForDamage(); // here you check that damage is not neg or too big...
this.health -= damage;
if(this.health <= 0)
{
OnDeath();
}
}
void OnActivate()
{
enemyCount++;
this.health = 20;
}
void OnDeath()
{
enemyCount--;
RaiseEnemyDeath(enemyCount); // Should check for nullity...
}
}
This one is fairly simple. The first part is all static and is relevant to the class. The second part is relevant to the instance. If you use a pool of enemy and then reuse the same instance multiple times, the OnActivate method is called when you make the enemy alive in the scene (it may have been there for a while as inactive). Then when the health is down, kill the enemy (there are not all the required actions there...) and trigger the event.
Using the public static property, you can know what is the enemy count from a GameManager (Enemy should not affect the gameplay, only takes care of the enemy).
public class GameManager:MonoBehaviour
{
void Start()
{
Enemy.RaiseEnemyDeath += Enemy_RaiseEnemyDeath;
}
void Enemy_RaiseEnemyDeath(int count)
{
if(count < 0){ // End of level }
// You can also access enemyCount
int count = Enemy.EnemyCount;
}
}
The good point of using this principle is that Enemy has no clue about GameManager and can be reused in another game without any modification. The GameManager is a higher level entity and knows about it.

How do I pause GameObject for a couple of seconds and unpause after a couple of seconds in unity3d

I need the gameobject to pause on its own in my scene for 7f or 8f and un-pause at 2f on its own. The script I have is letting my pause by key. Here is my script :
{
sing UnityEngine;
using System.Collections;
public class star : MonoBehaviour {
GameObject[] pauseObjects;
void Start () {
pauseObjects = GameObject.FindGameObjectsWithTag("Player");
}
void pauseGameobject()
{
if()
{
start coroutine("wait");
}
}
public ienumenator wait()
{
time.timescale = 0;
yield return new waitforsceonds(7);
time.timesale = 1;
}
void pauseGameobject()
{
if()
{
start coroutine("wait");
}
}
public ienumenator wait()
{
time.timescale = 0;
yield return new waitforsceonds(7);
time.timesale = 1;
}
}
You can use coroutines to insert delays in the update() loop. Coroutines use generators, which "yield", rather than functions/methods which "return". What this allows for is code that operates asynchronously while still being written in a linear fashion.
The built in coroutine you're most likely looking for is WaitForSeconds. To start a coroutine you simply call StarCoroutine() and pass in any method of type IEnumerator. This method will yield periodically. In the following example, WaitForSeconds(5) will yield after 5 seconds. Fractions of a second can also be used, represented by floats, for example 2.5 would be two and a half seconds.
using UnityEngine;
using System.Collections;
public class WaitForSecondsExample : MonoBehaviour {
void Start() {
StartCoroutine(Example());
}
IEnumerator Example() {
Debug.Log(Time.time); // time before wait
yield return new WaitForSeconds(5);
Debug.Log(Time.time); // time after wait
}
}
It's not too clear what you mean by pause on it's one, however I'm going to answer broadly, to try and help you.
If you whant to pause a single game object externally you can deactivate it and activate it accordingly with this code: gameObject.SetActive(false);
Instead if you want to pause the game object internally you can make a bool and in the update test wether or not it's true:
using UnityEngine;
using System.Collections;
bool update = false
public class ActiveObjects : MonoBehaviour
{
void Start ()
{
//Do stuff
}
void Update ()
{
if(update){
//Do stuff
}
//decide wether or not to pause the game object
}
}
If you want to pause the game you can set the Time.timeScale to 0, or just pause all game objects.
Here you can find how to make a timer, all you need to do is count down a variable using timeLeft -= Time.deltaTime;.
Hope I helped you,
Alex
Edit:
Ok, here is the script, keep in mind I have no way to test it ;)
using UnityEngine;
using System.Collections;
public class star : MonoBehaviour {
GameObject[] pauseObjects;
public float timer = 7;
float t = 0;
bool pause = false;
void Start () {
pauseObjects = GameObject.FindGameObjectsWithTag("Player");
t = timer;
}
void Update() {
if(pause){
if(t<0){
t=timer;
pause = false;
time.timescale = 1;
}else{
t -= Time.deltaTime;
time.timescale = 0;
}
}
}

Categories