public class green : MonoBehaviour
{
private AudioSource source;
public AudioClip sound;
static int result = 0;
void Start()
{
StartCoroutine("RoutineCheckInputAfter3Minutes");
Debug.Log("a");
}
IEnumerator RoutineCheckInputAfter3Minutes()
{
System.Random ran = new System.Random();
int timeToWait = ran.Next(1, 50) * 1000;
Thread.Sleep(timeToWait);
source = this.gameObject.AddComponent<AudioSource>();
source.clip = sound;
source.loop = true;
source.Play();
System.Random r = new System.Random();
result = r.Next(1, 4);
Debug.Log("d");
yield return new WaitForSeconds(3f * 60f);
gm.life -= 1;
Debug.Log("z");
}
public void Update()
{
if (result == 1 && gm.checka == true)
{
Debug.Log("e");
StopCoroutine("RoutineCheckInputAfter3Minutes");
gm.life += 1;
source.Stop();
gm.checka = false;
Debug.Log("j");
}
if (result == 2 && gm.checkb == true)
{
Debug.Log("f");
StopCoroutine("RoutineCheckInputAfter3Minutes");
gm.life += 1;
source.Stop();
gm.checkb = false;
Debug.Log("z");
}
else if (result == 3 && gm.checkc == true)
{
StopCoroutine("RoutineCheckInputAfter3Minutes");
Debug.Log("g");
gm.life += 1;
source.Stop();
gm.checkc = false;
Debug.Log(gm.life);
}
}
}
There are two problems
I want to make music stop and life variable decrease -1, if the user doesn't push any buttons for 3 minutes. But if the user pushes the right button, life variable will be increased + 1. but I don't know how to get null input from the user for 3 minutes.
If I use while for this program, this shuts down… until life is below 0, I want to repeat music which is played on irregular time.
Edit: Don't use Thread in Unity
How Unity works
Alternative to Thread
Couroutine Example 1
Coroutine Example 2
* To put it simple, Thread.Sleep hangs to Unity and Unity can't operate for the time, and that's why it looks like running slow.
You can use coroutines for this problem.
void Start()
{
StartCoroutine("RoutineCheckInputAfter3Minutes");
}
IEnumerator RoutineCheckInputAfter3Minutes()
{
yield return new WaitForSeconds(3f*60f);
gm.life -= 1;
}
void RightButtonClicked()
{
gm.life += 1;
StopCoroutine("RoutineCheckInputAfter3Minutes");
StartCoroutine("RoutineCheckInputAfter3Minutes");
}
Or, you can just turn your a function into a coroutine, if the other code sections work.
void Start()
{
StartCoroutine(a());
}
public IEnumerator a()
{
while (gm.life >= 0)
{
System.Random ran = new System.Random();
int timeToWait = ran.Next(1, 50) * 1000;
yield return new WaitForSeconds(timeToWait);
source = this.gameObject.AddComponent<AudioSource>();
source.clip = sound;
source.loop = true;
source.Play();
System.Random r = new System.Random();
result = r.Next(1, 4);
Debug.Log("d");
}
}
This is an example usage of coroutine based on your code More than this is out of scope:
A pastebin link to code
Related
The cards with the Button component and an onClick listener require numerous erratic clicks to trigger and fail to invoke after just one click.
The first two cards will always invoke via the first click. Afterwards, the other cards often require multiple clicks (between 2 and 7 clicks) before their listener is invoked, and they are flipped over. This occurs at random as sometimes even the first three pairs will flip after just one click, and then the rest won´t.
If I wait for a set time of five seconds, the next card I click will turn over with just one click. So the issue appears to depend on the interval between clicks, as opposed to the number of clicks. Although this behaviour is inconsistent, as clicking just once on a new card and then waiting those 5 seconds doesn´t always work and the card will stay unflipped; assuming because I clicked too soon.
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;
public class GameController : MonoBehaviour
{
[SerializeField] private Sprite bgImage;
public Sprite[] puzzles;
public List<Sprite> gamePuzzles = new List<Sprite>();
public List<Button> btns = new List<Button>();
private bool firstGuess, secondGuess;
private int countGuesses;
private int countCorrectGuesses;
private int gameGuesses;
private int firstGuessIndex, secondGuessIndex;
private string firstGuessPuzzle, secondGuessPuzzle;
void Awake()
{
puzzles = Resources.LoadAll<Sprite>("Sprites/Cards");
}
void Start()
{
GetButtons();
AddListeners();
AddGamePuzzles();
Shuffle(gamePuzzles);
gameGuesses = gamePuzzles.Count / 2;
}
void GetButtons()
{
GameObject[] objects = GameObject.FindGameObjectsWithTag("Puzzle Button");
for (int i = 0; i < objects.Length; i++)
{
btns.Add(objects[i].GetComponent<Button>());
btns[i].image.sprite = bgImage;
}
}
void AddGamePuzzles()
{
int looper = btns.Count;
int index = 0;
for (int i = 0; i < looper; i++)
{
if (index == looper / 2)
{
index = 0;
}
gamePuzzles.Add(puzzles[index]);
index++;
}
}
void AddListeners()
{
foreach (Button btn in btns)
{
btn.onClick.AddListener(() => PickAPuzzle());
}
}
public void PickAPuzzle()
{
string name = UnityEngine.EventSystems.EventSystem.current.currentSelectedGameObject.name;
Debug.Log("You are clicking a button named" + name);
if (!firstGuess)
{
firstGuess = true;
firstGuessIndex =
int.Parse(UnityEngine.EventSystems.EventSystem.current.currentSelectedGameObject.name);
firstGuessPuzzle = gamePuzzles[firstGuessIndex].name;
btns[firstGuessIndex].image.sprite = gamePuzzles[firstGuessIndex];
}
else if (!secondGuess)
{
secondGuess = true;
secondGuessIndex =
int.Parse(UnityEngine.EventSystems.EventSystem.current.currentSelectedGameObject.name);
secondGuessPuzzle = gamePuzzles[secondGuessIndex].name;
btns[secondGuessIndex].image.sprite = gamePuzzles[secondGuessIndex];
countGuesses++;
StartCoroutine(CheckIfThePuzzlesMatch());
}
}
IEnumerator CheckIfThePuzzlesMatch()
{
yield return new WaitForSeconds(2f);
if (firstGuessPuzzle == secondGuessPuzzle && firstGuessIndex != secondGuessIndex)
{
yield return new WaitForSeconds(1f);
btns[firstGuessIndex].interactable = false;
btns[secondGuessIndex].interactable = false;
btns[firstGuessIndex].image.color = new Color(0, 0, 0, 0);
btns[secondGuessIndex].image.color = new Color(0, 0, 0, 0);
CheckIfTheGameIsFinished();
}
else
{
yield return new WaitForSeconds(1f);
btns[firstGuessIndex].image.sprite = bgImage;
btns[secondGuessIndex].image.sprite = bgImage;
}
yield return new WaitForSeconds(1f);
firstGuess = secondGuess = false;
}
void CheckIfTheGameIsFinished()
{
countCorrectGuesses++;
if (countCorrectGuesses == gameGuesses)
{
Debug.Log("Game Finished");
}
}
void Shuffle(List<Sprite> list)
{
for (int i = 0; i < list.Count; i++)
{
Sprite temp = list[i];
int randomIndex = Random.Range(i, list.Count);
list[i] = list[randomIndex];
list[randomIndex] = temp;
}
}
}
I am making a badminton simulator in unity, where the opponent is a set of video clips. I am trying to add some delay to my update method so theres some time between two clips of the opponent. However this delay only applies to the video clips and not the shuttle that arrives from behind the video.
My Code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Video;
public class Video_Player : MonoBehaviour
{
public VideoPlayer activeCam, otherCam;
public List<VideoClip> playlist = new List<VideoClip>();
public GameObject shuttle;
VideoClip nextClip;
private bool Timer;
void Start()
{
Shuffle(playlist);
// play the first video in the playlist
PrepareNextPlaylistClip();
SwitchCams(activeCam);
Timer=false;
// setup an event to automatically call SwitchCams() when we finish playing
activeCam.loopPointReached += SwitchCams;
otherCam.loopPointReached += SwitchCams;
shuttle.SetActive(false);
}
void Update()
{
if (playlist.Count == 0)
return;
if(!Timer)
{
StartCoroutine(CountDown(5));
if (nextClip == null && activeCam.time >= activeCam.clip.length - 0.1)
{
PrepareNextPlaylistClip();
shuttle.SetActive(false);
}
if(activeCam.time >= 1.0f && activeCam.time <= 2.95f)
{
Debug.Log("start:"+activeCam.time);
shuttle.SetActive(true);
}
else
//if(activeCam.time >= 2.95f || activeCam.time <= 1.0f)
{
Debug.Log("end:"+activeCam.time);
shuttle.SetActive(false);
}
}
}
void SwitchCams(VideoPlayer thisCam)
{
activeCam = otherCam;
otherCam = thisCam;
activeCam.targetCameraAlpha = 1f;
otherCam.targetCameraAlpha = 0f;
Debug.Log("new clip: " + nextClip.name);
nextClip = null;
}
void PrepareNextPlaylistClip()
{
nextClip = playlist[0];
otherCam.clip = nextClip;
otherCam.Play();
playlist.RemoveAt(0);
}
//delay couroutine
IEnumerator CountDown(float delay)
{
Timer = true;
yield return new WaitForSeconds(delay);
Timer= false;
}
// randomize the video playlist
public static void Shuffle<T>(IList<T> playlist)
{
int n = playlist.Count;
while (n > 1)
{
n--;
int k = Random.Range(0, n);
T value = playlist[k];
playlist[k] = playlist[n];
playlist[n] = value;
}
}
}
Forgive me if I'm misunderstanding your code but rather than having it all in Update() couldn't you just have it in an IEnumerator like this?
void Start()
{
Shuffle(playlist);
// play the first video in the playlist
PrepareNextPlaylistClip();
SwitchCams(activeCam);
activeCam.loopPointReached += SwitchCams;
otherCam.loopPointReached += SwitchCams;
shuttle.SetActive(false);
//Run the function on start
StartCoroutine(Function());
}
IEnumerator Function()
{
while(true)
{
if(playlist.Count == 0)
{
//If you have no clips left exit out of the loop
break;
}
if(nextClip == null)
{
//If you have clips left load the next clip
shuttle.SetActive(false);
PrepareNextPlaylistClip();
}
yield return new WaitForSeconds(1); //This is your delay
//Execute the code you want to run after the delay here
}
}
I'm trying to make a little game in the Console App and i want an enemy to move at a constantly while moving the player. The code looks like this right now:
public static int y = 5;
public static string player = "O";
public static int enemyX = 10;
static void Main(string[] args)
{
while (true)
{
Console.SetCursorPosition(enemyX, 10);
Console.Write("X");
enemyX = enemyX - 1;
Console.CursorVisible = false;
Console.SetCursorPosition(5, y);
Console.Write(player);
var move = Console.ReadKey(true);
switch (move.Key)
{
case ConsoleKey.W:
y = y - 1;
break;
case ConsoleKey.S:
y = y + 1;
break;
}
if (y <= 0)
{
y = 1;
}
if (y >= 25)
{
y = 24;
}
Console.Clear();
}
}
From what I understand you want the enemy to move regardless of if the player moves or not and to do that you could use Threads
Example:
bool BreakThread = false; //you need this to break the thread loop
Thread enemyThread = new Thread(()=>
{
while(!BreakThread)
{
//do Enemy Actions
}
});
enemyThread.Start();
//then execute your main game loop
but remember to set the BreakThread value to true when ever you
are closing the game.
public class green : MonoBehaviour
{
private AudioSource source;
public AudioClip sound;
static int result = 0;
// Use this for initialization
void Start()
{
StartCoroutine("RoutineCheckInputAfter3Minutes");
Debug.Log("a");
}
IEnumerator RoutineCheckInputAfter3Minutes()
{
System.Random ran = new System.Random();
int timeToWait = ran.Next(1, 50) * 1000;
Thread.Sleep(timeToWait);
source = this.gameObject.AddComponent<AudioSource>();
source.clip = sound;
source.loop = true;
source.Play();
System.Random r = new System.Random();
result = r.Next(1, 4);
Debug.Log("d");
yield return new WaitForSeconds(3f * 60f);
gm.life -= 1;
Debug.Log(gm.life + "값");
source.Stop();
Debug.Log("z");
if (gm.life >= 0)
{
StartCoroutine("RoutineCheckInputAfter3Minutes");
}
}
// Update is called once per frame
public void Update()
{
if (result == 1 && gm.checkeat == true)
{
Debug.Log("e");
gm.life += 1;
Debug.Log("j");
Debug.Log(gm.life + "값");
source.Stop();
gm.checkeat = false;
StopCoroutine("RoutineCheckInputAfter3Minutes");
StartCoroutine("RoutineCheckInputAfter3Minutes");
}
if (result == 2 && gm.checkshit == true)
{
Debug.Log("f");
gm.life += 1;
Debug.Log("o");
Debug.Log(gm.life + "값");
source.Stop();
gm.checkshit = false;
StopCoroutine("RoutineCheckInputAfter3Minutes");
StartCoroutine("RoutineCheckInputAfter3Minutes");
}
else if (result == 3 && gm.checksleep == true)
{
Debug.Log("g");
gm.life += 1;
Debug.Log(gm.life);
Debug.Log(gm.life + "값");
source.Stop();
gm.checksleep = false;
StopCoroutine("RoutineCheckInputAfter3Minutes");
StartCoroutine("RoutineCheckInputAfter3Minutes");
}
}
}
public class gm : MonoBehaviour
{
static public int life = 0;
static public bool checkeat = false;
static public bool checkshit = false;
static public bool checksleep = false;
// Use this for initialization
void Start()
{
}
// Update is called once per frame
void Update()
{
}
public void eating(string eat)
{
Debug.Log(life + "값");
checkeat = true;
}
public void shitting(string shit)
{
Debug.Log(life + "값");
checkshit = true;
}
public void sleeping(string sleep)
{
Debug.Log(life + "값");
checksleep = true;
}
}
when i click a button , program stops for a while and then works... i think it is because of thread or something...
please share your opinion..
.when i click a button , program stops for a while and then works... i think it is because of thread or something...
please share your opinion..
Stop using :
Thread.Sleep(timeToWait);
This stalls the entire thread, in this case Unity completely from running.
Since your using routines anyway, use this instead :
yield return new WaitForSeconds(timeToWait);
And change this line :
int timeToWait = ran.Next(1, 50) * 1000;
To this :
int timeToWait = ran.Next(1, 50);
Good Day! I have this code but I have an error, for example (I set two players me, and 1 computer). I take the first turn, and the dice respawn with a value of 4 (just an example), the game piece then move from 1st to 4th tile when I touch the screen, when computer turns, it also move from 1st to 4th tile (because I set the result to 4 just an example). Now its my turn again, the dice never respawn and it doesn't wait to touch the screen if (Input.GetMouseButtonDown(0)) and move again by 4...
public class singlePlay : MonoBehaviour {
//Player
public GameObject[] playerprefab;
//Player Clone
public GameObject[] playerprefabC;
//Game Cards and Dice
public GameObject[] situationCard;
public GameObject dice;
int diceresult;
//Game Cards and Dice clone
public GameObject diceclone;
public int currentPlayer;
public int compPlayer;
public int playerTurn;
public string compPlayerstring;
public string playerTurnstring;
//GUI Boolean
bool play = false;
//Game Boolean
bool pieces = false;
bool giveturn = false;
bool myturn = false;
bool diceSpawn = false;
bool moving = false;
bool routine = false;
bool checking = false;
bool compturn = false;
//icon1
public GameObject[] icon;
//population
int[] population = new int[3];
//Tile
public GameObject[] Tile;
int[] playerTile = new int[3]; //current location
int[] playerTileUp = new int [3]; // updated location after dice roll
bool endTurn = false;
void Update ()
{
if (giveturn == true) {
int h = 0;
Giveturn(h);
giveturn = false;
}
if (play == true) {
if (pieces == true){
SpawnPlayer();
pieces = false;
}
if (myturn == true){
compturn = false;
if(diceSpawn == true) {
dice.transform.position = new Vector3(0,0,-1);
diceclone = Instantiate(dice, dice.transform.position, Quaternion.identity) as GameObject;
diceSpawn = false;
}
if (Input.GetMouseButtonDown(0))
{
Debug.Log("click");
diceresult = 4;
Destroy(diceclone);
moving = true;
Updateposition(diceresult);
}
}
else
{
Debug.Log("comp");
myturn = false;
diceresult = 4;
moving = true;
Updateposition(diceresult);
}
}
}
void Giveturn(int k)
{
Debug.Log("" + k);
currentPlayer = k;
if (k == playerTurn) {
Debug.Log("Yes");
compturn = false;
myturn = true;
diceSpawn = true;
moving = false;
}
else
{
Debug.Log("No");
compturn = true;
myturn = false;
moving = false;
}
}
void Updateposition(int diceresult)
{
if (moving == true) {
playerTileUp[currentPlayer] = playerTile[currentPlayer] + diceresult;
Debug.Log("" + playerTileUp[currentPlayer]+ " " +currentPlayer);
routine = true;
StartCoroutine(MyMethod());
}
moving = false;
}
IEnumerator MyMethod()
{
if (routine == true) {
if (myturn == true) {
compturn = false;
}
else
{
myturn = false;
}
int f = playerTile[currentPlayer] + 1;
Debug.Log(" " + currentPlayer );
while (f <= playerTileUp[currentPlayer]) {
Debug.Log("waiting");
yield return new WaitForSeconds(1);
Debug.Log(" " + Tile[f]);
playerprefabC[currentPlayer].transform.position = Tile[f].transform.position;
Debug.Log(" " + currentPlayer);
f++;
}
checking = true;
TrapCheck();
}
routine = false;
}
void TrapCheck()
{
if (checking == true) {
if (playerTileUp[currentPlayer] == 8) {
Debug.Log("Trap spawning");
Instantiate(situationCard[0], situationCard[0].transform.position, Quaternion.identity);
population[currentPlayer] = population[currentPlayer] -1;
}
playerTile[currentPlayer] = playerTileUp[currentPlayer];
Endturn();
myturn = false;
compturn = false;
checking = false;
}
}
void Endturn()
{
currentPlayer++;
Debug.Log(" " + currentPlayer);
if (currentPlayer > compPlayer) {
currentPlayer = 0;
}
Giveturn(currentPlayer);
}
}
There are few things that I could see wrong there already. First while the coroutine is running, it seems you are not preventing the update from running since play remains true. In TrapCheck, you call EndTurn which call GiveTurn and sets myTurn (true) and compTurn (false) booleans. But those two are reset in TrapCheck, myTurn is set back to false. You need to rethink the logic of your class.
A solution would be to use delegate. This would remove many of your boolean that you set and reset. Here is a basic idea:
Action currentUpdate;
bool playerTurn = true;
void Start(){
SetTurn();
}
void Update(){
if(currentUpdate != null)currentUpdate();
}
void SetTurn(){
// Prepare initial setting for moving
if(playerTurn == true){ currentUpdate = PlayerTurn; }
else{ currentUpdate = CompTurn; }
playerTurn = !playerTurn;
}
void PlayerTurn(){
// Check input
// Get dice value
currentUpdate = Move;
}
void CompTurn(){
// Get dice value
currentUpdate = Move;
}
void Move(){
if(position != target){
}else{
SetTurn();
}
}
This is fairly simplified but once you get the thing about delegate (maybe you already know), this will make it all so much more flexible.