public static int pscore = 0;
void Start()
{
InvokeRepeating("AddToMoney",1, 1);
}
void AddToMoney ()
{
pscore++;
}
I have this code to add a point to integer pscore every second. But right now it adds 2 points instead of one. Is it because it's static? And if so, how can I fix it? Or how can I transfer one variable from script to another script without using static?
Note: I couldn't get answer in the unity3d forums, that's why I'm asking here.
add a point to integer pscore every second
bool keepIncrementing = false;
public static int pscore = 0;
void Start()
{
StartCoroutine(IncementEachSecond());
}
IEnumerator IncementEachSecond()
{
keepIncrementing = true;
while (keepIncrementing)
{
pscore++;
yield return new WaitForSeconds(1);
}
}
void stopIncrementing()
{
keepIncrementing = false;
}
how can I transfer one variable from script to another script without
using static
public class ScriptA : MonoBehaviour{
public int pscore = 0;
void Start()
{
}
}
Access variable pscore in ScriptA from ScriptB.
public class ScriptB : MonoBehaviour{
ScriptA scriptInstance = null;
void Start()
{
GameObject tempObj = GameObject.Find("NameOfGameObjectScriptAIsAttachedTo");
scriptInstance = tempObj.GetComponent<ScriptA>();
scriptInstance.pscore = 5;
}
}
Related
i'm trying to make a timer to control gameObject display,i found t doesn't change when it become zero,
how can i fix it or another better solution?
public class randomGopher : MonoBehaviour
{
// Use this for initialization
public int t;
public bool active;
void Start()
{
t = Random.Range(30, 150);
}
// Update is called once per frame
void Update()
{
Debug.Log(t);
if (t == 0)
{
active = this.gameObject.activeSelf;
this.gameObject.SetActive(!active);
t = Random.Range(30, 150);
}
else
{
t = t - 1;
}
}
}
So your problem is that Update is not called anymore if the GameObject your script is attached to is inactive after
gameObject.SetActive(false);
(Not 100% sure and can't test it right now as typing on smartphone.)
Afaik Invoke is still working also on a disabled MonoBehaviour or inactive GameObject (at least I know that it is the case for InvokeRepeating) so you could probably simply use something like
public class randomGopher : MonoBehaviour
{
// Adjust these in seconds
[SerializeField] private float minDelay = 1f;
[SerializeField] private float maxDelay = 3f;
private void Start()
{
Invoke(nameof(SwitchActiveState), Random.Range(minDelay, maxDelay);
}
private void SwitchActiveState ()
{
gameObject.SetActive(! gameObject.activeSelf);
Invoke(nameof(SwitchActiveState), Random.Range(minDelay, maxDelay);
}
}
The best way is executing your script in a separated GameObject, and only activate or deactivate the TargetObject.
public class randomGopher : MonoBehaviour
{
// Use this for initialization
public int t;
public bool active;
public GameObject TargetObj;
void Start()
{
t = Random.Range(30, 150);
}
// Update is called once per frame
void Update()
{
Debug.Log(t);
if (t == 0)
{
active = TargetObj.activeSelf;
TargetObj.SetActive(!active);
t = Random.Range(30, 150);
}
else
{
t = t - 1;
}
}
}
In my game, there is a profit count which is controlled by the addMoney variable in my money script ex. profitcount = addMoney.
When I add the player pref regarding my addMoney Variable it defaults the profitCount to 0 when it should in fact be 1. This is my first game, so it could be be very easily a small thing that I have misunderstood or overlooked.
moneyCount
public class moneyCount : MonoBehaviour
{
float timeTillAdd = 1;
public int addMoney = 1;
public int money;
public Text txt;
// Start is called before the first frame update
void Start()
{
money = PlayerPrefs.GetInt("Money");
addMoney = PlayerPrefs.GetInt("addmoney");
}
// Update is called once per frame
void Update()
{
PlayerPrefs.SetInt("addmoney", addMoney);
if (Time.time >= timeTillAdd)
{
money += addMoney;
timeTillAdd++;
}
txt.text = money.ToString();
PlayerPrefs.SetInt("Money", money);
}
}
profit count
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class profitCount : MonoBehaviour
{
public int profitAmount;
public GameObject moneyManagerObj;
moneyCount mc;
public Text txt;
// Start is called before the first frame update
void Start()
{
mc = moneyManagerObj.GetComponent<moneyCount>();
// profitAmount = PlayerPrefs.GetInt("profitamount");
}
// Update is called once per frame
void Update()
{
profitAmount = mc.addMoney;
txt.text = profitAmount.ToString();
// PlayerPrefs.SetInt("profitamount", profitAmount);
}
}
shopManager
public class ShopManager : MonoBehaviour
{
public int item1_cost = 50;
public int item1_upgrade = 5;
public int item1_tier = 1;
public int item2_cost = 50;
public int item2_upgrade = 5;
public GameObject moneyManagerObj;
moneyCount mc;
public Text txt;
public Text item1;
public Text item1_text;
// Start is called before the first frame update
void Start()
{
mc = moneyManagerObj.GetComponent<moneyCount>();
item1_cost = PlayerPrefs.GetInt("Item1_cost");
//item1_upgrade = PlayerPrefs.GetInt("Item1_upgrade");
item1_tier = PlayerPrefs.GetInt("Item1_tier");
}
// Update is called once per frame
void Update()
{
item1.text = item1_tier.ToString();
PlayerPrefs.SetInt("Item1_cost", item1_cost);
// PlayerPrefs.SetInt("Item1_upgrade", item1_upgrade);
PlayerPrefs.SetInt("Item1_tier", item1_tier);
if (item1_tier > 0)
{
item1_text.text = ("Upgrade");
}
}
public void on_click()
{
{
if (mc.money >= item1_cost)
{
mc.money -= item1_cost;
mc.addMoney += item1_upgrade;
item1_tier += 1;
item1.text = item1_tier.ToString();
item1_cost += 50 * item1_tier;
}
}
}
}
Two things:
Don't use PlayerPrefs to store save data. It isn't meant for that. Its meant for saving player preferences such as volume, full screen mode, or input type. The file used by PlayerPrefs is plain text and can't support complex data types.
If no save data exists, the values read out are zero (at least from PlayerPrefs). You need to account for this and currently you are not. When you move to a different method of saving, you'll get other errors, like null pointers or file not founds. You have to determine if a save exists and only if it does, should you read from it.
Ok so you were assigning default value to addMoney during initialization i.e public int addMoney = 1;
But then in your start you were again assigning it a value that has not been saved yet addMoney = PlayerPrefs.GetInt("addmoney");
If you want to create a record do it like this PlayerPrefs.SetInt("addmoney",addmoney);
So I put the object in the scene and then I made it "invisible" (deactivate if you will) from the inspector (the checkmark box next to the object's name) and after waiting 8 seconds it doesn't become visible. I am using Unity 2d and C#.
I have the game start paused for three seconds then plays after that which works. The first script is that one. The item is supposed to reappear after 8 seconds so after the game resumes, which doesn't work.
//delay before level starts script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class countDown : MonoBehaviour
{
public GameObject CountDown;
private void Start()
{
StartCoroutine("StartDelay");
}
void Update()
{
}
IEnumerator StartDelay()
{
Time.timeScale = 0;
float pauseTime = Time.realtimeSinceStartup + 3f;
while (Time.realtimeSinceStartup < pauseTime)
yield return 0;
CountDown.gameObject.SetActive(false);
Time.timeScale = 1;
}
{
//script for the flower to appear
IEnumerator Start()
{
print(Time.time);
yield return new WaitForSeconds(8);
print(Time.time);
flowerInScene.gameObject.SetActive(true);
}
[SerializeField] Transform flowerInScene;
}
I still don't really get your two methods called Start
You can simply call a StartCoroutine at the end of another Coroutine so you can chain them together (though there are surely better ways to do what you want in general):
using System.Collections;
using UnityEngine;
public class CountDown : MonoBehaviour
{
public GameObject CountDownObject;
public GameObject flowerObject;
private void Start()
{
StartCoroutine(Delay());
}
private IEnumerator Delay()
{
yield return new WaitForSeconds(3);
HideCountdown();
StartCoroutine(FlowerDelay());
}
private void HideCountdown()
{
CountDownObject.SetActive(false);
}
private IEnumerator FlowerDelay()
{
yield return new WaitForSeconds(8);
ShowFlower();
}
private void ShowFlower()
{
flowerObject.SetActive(true);
}
}
I personaly don't like Coroutines .. they are not so easy to debug sometimes. I would prefer doing something like this with simple timers (though in the first moment it does look worse). Advantage is I can now directly watch the timer count down in the inspector:
using UnityEngine;
public class SimpleCountDown : MonoBehaviour
{
[Header("The Objects")]
public GameObject CountDownObject;
public GameObject FlowerObject;
[Header("Settings")]
// Here you can adjust the delay times
public float StartOffset = 3;
public float FlowerOffset = 8;
[Header("Debug")]
public float startTimer;
public float flowerTimer;
public bool isStartDelay;
public bool isFlowerDelay;
private void Start()
{
startTimer = StartOffset;
flowerTimer = FlowerOffset;
isStartDelay = true;
}
private void Update()
{
if (!isStartDelay && !isFlowerDelay) return;
if (isStartDelay)
{
startTimer -= Time.deltaTime;
if (startTimer <= 0)
{
HideCountdown();
isStartDelay = false;
isFlowerDelay = true;
}
}
if (isFlowerDelay)
{
flowerTimer -= Time.deltaTime;
if (flowerTimer <= 0)
{
ShowFlower();
isFlowerDelay = false;
this.enabled = false;
}
}
}
private void HideCountdown()
{
CountDownObject.SetActive(false);
}
private void ShowFlower()
{
FlowerObject.SetActive(true);
}
}
Hellos guys I am a beginner and have 2 classes. Class A has an Array that I need to access in Class B. I've searched through here for the past 36 hours trying different methods and this is what I ended up with any help?
This is the first Class with the Array
[System.Serializable]
public class Cli
{
public string name;
public int money;
};
public class BankManager : MonoBehaviour
{
private static BankManager _instance;
public static BankManager Instance
{
get
{
if (_instance == null)
{
GameObject go = new GameObject("BankManager");
go.AddComponent<BankManager>();
}
return _instance;
}
}
public GameObject player;
private string NaMe;
public Bank[] banks = new Bank[1];
public Cli[] clients = new Cli[1];
void Awake()
{
_instance = this;
}
void Start()
{
banks[0] = new Bank("In But Not Out", 10000);
player = GameObject.Find("Player");
clients[0].money = 1000;
}
void Update()
{
PlayerController pName = player.GetComponent<PlayerController>();
clients[0].name = pName.name;
}
}
The array I am trying to access is the clients[]
public class AccessAtm : MonoBehaviour
{
public Bank bank;
public int clams;
private void OnTriggerEnter2D(Collider2D other)
{
bank = BankManager.Instance.banks[0];
if (other.tag == "Player")
{
clams = Array.IndexOf(BankManager.Instance.clients,
other.GetComponent<PlayerController>().name);
Debug.Log(other.GetComponent<PlayerController>().name);
}
}
}
The debug.log properly tells me I'm getting the player.name I believe my error is in either getting that instance of the array or in the indexof command
The problem is IndexOf expects you to pass a instance of Bank for the 2nd parameter of
clams = Array.IndexOf(BankManager.Instance.clients,
other.GetComponent<PlayerController>().name);
you are passing it a string.
You need to use something else to search for it, the easist solution would be use a for loop.
var clients = BankManager.Instance.clients;
var otherName = other.GetComponent<PlayerController>().name;
int foundAt = -1;
for(int i = 0; i < clients.Length; i++)
{
if(clients[i].name == otherName)
{
foundAt = i;
break;
}
}
claims = foundAt;
I have a list of enemys. so i want each enemy have their turn.
First of all :
Player turn --> enemys turn ("here each enemy move one by one untill the end then player move again"). how do i making some waiting time here and forcus on enemy turn?
Any help would be appreciated.
void Start()
{
// find list enemy
enemy = GameObject.FindGameObjectsWithTag("Enemy");
}
void Update()
{
//enemy turn reference to player. after move all enemy we change it to false to change the player turn.
if(StaticClass.enemyTurn == true )
{
for(int i=0;i<enemy.length;i++)
{
// how do i making some waiting time here and forcus on enemy turn?
EnemyTurn(i);
}
}
}
public void EnemyTurn(int id)
{
ChessMoveMent chessMoveScript = enemy[id].GetComponent<ChessMoveMent>();
chessMoveScript.ProcessMove();
id++;
if(id>=enemy.Length)
{
isMove = false;
}
}
I usually use StartCoroutine in this case.
Please try the below code:
public IEnumerator EnemyTurn(int id)
{
yield return null;
ChessMoveMent chessMoveScript = enemy[id].GetComponent<ChessMoveMent>();
chessMoveScript.ProcessMove();
id++;
if(id>=enemy.Length)
{
isMove = false;
}
}
When you want to use it, please use with "StartCoroutine()"
StartCoroutine(EnemyTurn(i));
More details here
You might have a coordinator, who tells the participants when it's their turn.
public class GameCoordinator : MonoBehaviour
{
public List<Participant> participants;
private int currentParticipantIdx = -1;
private Participant CurrentParticipant
{
get { return participants[currentParticipantIdx]; }
}
private void Start()
{
PlayNextMove();
}
private void PlayNextMove()
{
ProceedToNextParticipant();
CurrentParticipant.OnMoveCompleted += OnMoveCompleted;
CurrentParticipant.BeginMove();
}
private void OnMoveCompleted()
{
CurrentParticipant.OnMoveCompleted -= OnMoveCompleted;
StartCoroutine(PlayNextMoveIn(2.0f));
}
private IEnumerator PlayNextMoveIn(float countdown)
{
yield return new WaitForSeconds(countdown);
PlayNextMove();
}
private void ProceedToNextParticipant()
{
++currentParticipantIdx;
if (currentParticipantIdx == participants.Count)
currentParticipantIdx = 0;
}
}
public class Participant : MonoBehaviour
{
public event Action OnMoveCompleted;
public void BeginMove()
{
//
}
}