I am making a TDS so it's time to make a mechanism to be able to pick up and drop weapons. I made it for the player and a new script for bots was based on player's one. So the problem is: I created an enemy prefab to be able to make as much of them as needed and if it is only one enemy while game is running then everything is fine: enemy passes through waypoins, picks up a weapon, then meets a better one and picks it up aswell dropping a worse one. But when I add a couple of new enemies things become weird as enemies don't pick up weapons (basically, a picked-up weapon doesn't become active) but just ignore them. At the same time the weapons on ground which are used to disappear when picked actually disappear so it doesn't make any sense. Here's the code of my realization. I hope we'll find a solution to this problem.
Thanks for you attention and sorry for my disgusting english!
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class EnemyDrop : MonoBehaviour
{
//Current amount of ammo
public int currentAmmo;
private Vector3 offset;
//Weapons which are active in inventory.
//LABEL0
public GameObject _activeMelee;
public static GameObject activeMelee;
public GameObject _activeBottle;
public static GameObject activeBottle;
public GameObject _activeGun;
public static GameObject activeGun;
public GameObject _activePistol;
public static GameObject activePistol;
[HideInInspector]
//ID of weapon which was active last time.
public int activeId;
//ID of weapon which is ready to be picked up.
private int activeQuestion;
//Weapon that is equipped before function ChangeWeapon().
private GameObject currentChange;
//Weapon that is ready to be picked up in function ChangeWeapon().
private GameObject groundWeapon;
public Transform enemy;
[HideInInspector]
private bool ifThereIsSmthInHand;
[HideInInspector]
//Can we move to next step? This becomes true when enemy's trigger works.
public bool mightDoNextTurn;
[HideInInspector]
private string nameOfActive;
private string nameOfWeapon;
public GameObject[] arrayOfObjects;
public int[] arrayOfIds;
public int[] arrayOfAmmo;
[HideInInspector]
public bool isFlying;
[HideInInspector]
public float speed;
private float timeWhileFlying;
[HideInInspector]
public float timing;
public int[] arrayOfValues;
private bool pickedAnEmptyWeapon;
public string nameactive;
public string nameWeapon;
public int question;
public static string getActiveWeapon () //LABEL1
{
if (activeGun.activeSelf) {
return "Gun";
}
if (activeMelee.activeSelf) {
return "Melee";
}
if (activeBottle.activeSelf) {
return "Bottle";
}
if (activePistol.activeSelf) {
return "Pistol";
}
return "empty";
}
public static bool ifThereIsSomethingInHand ()//LABEL2
{
if (activeMelee.activeSelf || activeGun.activeSelf || activeBottle.activeSelf || activePistol.activeSelf)
return true;
else
return false;
}
void Start ()
{ //LABEL3
activeMelee = _activeMelee;
activeGun = _activeGun;
activeBottle = _activeBottle;
activePistol = _activePistol;
activeBottle.SetActive (false);
activeMelee.SetActive (false);
activeGun.SetActive (false);
activePistol.SetActive (false);
offset = new Vector3 (0f, 0.9f, -0.5f);
mightDoNextTurn = false;
speed = 2;
timeWhileFlying = 2;
activeId = 26;
}
void Update ()
{
ifThereIsSmthInHand = ifThereIsSomethingInHand ();
nameOfActive = getActiveWeapon ();
if (ifThereIsSmthInHand) {
if (mightDoNextTurn)
ChangeWeapon ();
else
actionDrop ();
} else if (mightDoNextTurn)
actionPick ();
nameactive = nameOfActive;
nameWeapon = nameOfWeapon;
question = activeQuestion;
}
private void actionDrop () //LABEL4
{
if (currentAmmo == 0 && nameOfActive == "Gun") {
activeGun.SetActive (false);
arrayOfObjects [activeId].SetActive (true);
arrayOfValues [activeId] = 0;
DropPos ();
activeId = 26;
}
if (currentAmmo == 0 && nameOfActive == "Pistol") {
activePistol.SetActive (false);
arrayOfObjects [activeId].SetActive (true);
arrayOfValues [activeId] = 0;
DropPos ();
activeId = 26;
}
}
public void deathDrop ()
{
arrayOfObjects [activeId].SetActive (true);
DropPos ();
}
private void actionPick ()//LABEL5
{
switch (nameOfWeapon) {
case "FireWeapon":
activeGun.SetActive (true);
break;
case "MeleeWeapon":
activeMelee.SetActive (true);
break;
case "BottleWeapon":
activeBottle.SetActive (true);
break;
case "PistolWeapon":
activePistol.SetActive (true);
break;
default:
break;
}
arrayOfObjects [activeQuestion].SetActive (false);
activeId = activeQuestion;
mightDoNextTurn = false;
}
private void DropPos ()
{
arrayOfObjects [activeId].transform.position = enemy.transform.position - offset;
arrayOfObjects [activeId].transform.rotation = enemy.transform.rotation;
}
private void ChangeWeapon ()//LABEL6
{
if (arrayOfValues [activeQuestion] > arrayOfValues [activeId]) {
if (activeMelee.activeSelf)
currentChange = activeMelee;
if (activeGun.activeSelf)
currentChange = activeGun;
if (activeBottle.activeSelf)
currentChange = activeBottle;
if (activePistol.activeSelf)
currentChange = activePistol;
currentChange.SetActive (false);
arrayOfObjects [activeId].SetActive (true);
DropPos ();
activeId = 26;
arrayOfObjects [activeQuestion].SetActive (false);
activeId = activeQuestion;
mightDoNextTurn = false;
if (nameOfWeapon == "BottleWeapon") {
activeBottle.SetActive (true);
}
if (nameOfWeapon == "MeleeWeapon") {
activeMelee.SetActive (true);
}
if (nameOfWeapon == "FireWeapon") {
activeGun.SetActive (true);
}
if (nameOfWeapon == "PistolWeapon") {
activePistol.SetActive (true);
}
}
}
void OnTriggerEnter (Collider other)//LABEL7
{
if (other.gameObject.tag == "Weapon") {
groundWeapon = other.gameObject;
activeQuestion = other.gameObject.GetComponent<IdOfWeapon> ().localId;
if (arrayOfValues [activeQuestion] == 0)
activeQuestion = 26;
if (activeQuestion >= 0 && activeQuestion <= 1000 && activeQuestion != 26) {
if (activeQuestion < 31) {
nameOfWeapon = "MeleeWeapon";
}
if (activeQuestion < 61 && activeQuestion >= 31) {
nameOfWeapon = "BottleWeapon";
}
if (activeQuestion >= 61 && activeQuestion < 91) {
nameOfWeapon = "FireWeapon";
}
if (activeQuestion >= 121 && activeQuestion < 151) {
nameOfWeapon = "PistolWeapon";
}
}
mightDoNextTurn = true;
}
}
void OnTriggerStay (Collider other)//LABEL8
{
if (other.gameObject.tag == "Weapon") {
groundWeapon = other.gameObject;
activeQuestion = other.gameObject.GetComponent<IdOfWeapon> ().localId;
if (arrayOfValues [activeQuestion] == 0)
activeQuestion = 26;
if (activeQuestion >= 0 && activeQuestion <= 1000 && activeQuestion != 26) {
if (activeQuestion < 31) {
nameOfWeapon = "MeleeWeapon";
}
if (activeQuestion < 61 && activeQuestion >= 31) {
nameOfWeapon = "BottleWeapon";
}
if (activeQuestion >= 61 && activeQuestion < 91) {
nameOfWeapon = "FireWeapon";
}
if (activeQuestion >= 121 && activeQuestion < 151) {
nameOfWeapon = "PistolWeapon";
}
}
mightDoNextTurn = true;
}
}
void OnTriggerExit (Collider other)
{
if (other.gameObject.tag == "Weapon") {
mightDoNextTurn = false;
nameOfWeapon = "";
}
activeQuestion = 26;
}
}
Note: enemy is allowed to drop a weapon for only two reasons: currentAmmo is equal to 0 or if he meets a better one (based on value).
the keyword static will mean this variable is shared with all instances of the script. This is what is causing you problems. – Catwood 1 hour ago - that's the solution
Related
I would like to istantiate multiple dices (you should be able to add and substract dices) and roll them.
For now I can roll a dice and get the readout in the console.
My problem: I can't get multiple dice to work...
These are the scripts:
the dice controller:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DiceController : MonoBehaviour
{
public Dice dice;
public GameObject dicePre;
public int count = 1;
void Update()
{
GameObject[] dices = GameObject.FindGameObjectsWithTag("Dice");
if(count - 1 == dices.Length){
for (int i = 0; i < count; i++)
{
Instantiate(dicePre, new Vector3(i * 1.1F, 0, 0), Quaternion.identity);
}
}
else if(count -1 < dices.Length){
return;
}
}
public void Throw()
{
GameObject[] dices = GameObject.FindGameObjectsWithTag("Dice");
foreach(GameObject dic in dices){
dice = dic.GetComponent<Dice>();
dice.RollDice();
}
}
public void Plus(){ //add dice
count++;
}
public void Minus(){ //substract dice
count--;
}
}
the dice sides:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DiceSide : MonoBehaviour
{
bool onGround;
public int sideValue;
void OnTriggerStay(Collider col) {
if(col.tag == "ground"){
onGround = true;
}
}
void OnTriggerExit(Collider col) {
if(col.tag == "ground"){
onGround = false;
}
}
public bool OnGround(){
return onGround;
}
}
the main dice script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Dice : MonoBehaviour
{
Rigidbody rb;
bool hasLanded;
bool thrown;
Vector3 initPos;
public int diceValue;
public DiceSide[] diceSides;
private void Start(){
rb = GetComponent<Rigidbody>();
initPos = transform.position;
rb.useGravity = false;
}
private void Update(){
if(Input.GetKeyDown(KeyCode.T)){
RollDice();
}
if(rb.IsSleeping() && !hasLanded && thrown){
hasLanded = true;
rb.useGravity = false;
rb.isKinematic = true;
SideValueCheck();
}
else if(rb.IsSleeping() && hasLanded && diceValue == 0){
RollAgain();
}
}
public void RollDice(){
if(!thrown && !hasLanded){
thrown = true;
rb.useGravity = true;
rb.AddTorque(Random.Range(0,500), Random.Range(0,500), Random.Range(0,500));
}
else if(thrown && hasLanded){
Reset();
}
}
void Reset(){
transform.position = initPos;
thrown = false;
hasLanded = false;
rb.useGravity = false;
rb.isKinematic = false;
}
void RollAgain(){
Reset();
thrown = true;
rb.useGravity = true;
rb.AddTorque(Random.Range(0,500), Random.Range(0,500), Random.Range(0,500));
}
void SideValueCheck(){
diceValue = 0;
foreach(DiceSide side in diceSides){
if(side.OnGround()){
diceValue = side.sideValue;
Debug.Log("Eine " + diceValue + " wurde gewürfelt!");
}
}
}
}
How can I get this to work?
also here you can download the unitypackage with everything i got right now:
https://workupload.com/file/7brN4gTCeLu
First as said I would directly make the prefab field of type
public Dice dicePre;
then I would not use FindGameObjectsWithTag all the time to get current instances.
I would rather keep track of them in a List like e.g.
public class Dice : MonoBehaviour
{
// every instance will add itself to this list
private static List<Dice> instances = new List<Dice>();
// public read only access
public static ReadOnlyCollection<Dice> Instances => instances.AsReadOnly();
// Add yourself to the instances
private void Awake()
{
instances.Add(this);
}
// Remove yourself from the instances
private void OnDestroy()
{
instances.Remove(this);
}
}
So later you can simply use
foreach(var dice in Dice.Instances)
{
dice.RollDice();
}
The main issue
Then currently you are checking
if(count - 1 == dices.Length)
and if so you instantiate count dices.
So what if your dices is empty and your count is 3? -> nothing would happen
Or what if you already have 2 dices but count is 3 -> you spawn 3 dices and end up with 5!
You would need to actually check the difference between the dices amount and count and either add or remove only the difference.
In order to fix this I would not do this in Update but rather using a property like
[SerializeField] private int _count;
public int Count
{
get => _count;
set
{
// Count can not be negative
_count = Mathf.Max(0, value);
// Now do something with this new value
// check difference
var dif = Dice.Instances.Count - _count;
// if 0 -> nothing to do
if(dif == 0)
{
return;
}
// if smaller then 0 -> need more dices
if(dif < 0)
{
for(var i = dif; i < 0; i++)
{
Instantiate(dicePre, Vector3.right * Dice.Instances.Count, Quaternion.identity);
}
}
// dif bigger then 0 -> have to many dices
else
{
for(var i = 0; i < dif; i++)
{
DestroyImmediate(Dice.Instances[Dice.Instances.Count - 1]);
}
}
}
}
[ContextMenu(nameof(Plus))]
public void Plus()
{
Count++;
}
[ContextMenu(nameof(Minus))]
public void Minus()
{
Count--;
}
i do not know unity... so if this is off base with regards to that then i will gladly delete.
public class DiceController : MonoBehaviour
{
public List<Dice> dices;
void DiceController()
{
dices = new list<Dice>();
dices.add(new Dice); //ensure always have at least 1 on start
}
public void Plus()
{
dices.Add(new Dice);
}
//caller can decided, could be random which one get removed.
//assume they all equal
public void Minus(Dice dice){
dices.Remove(dice);
}
public void Throw()
{
foreach(Dice dice in dices){
dice.RollDice();
}
}
}
I encountered a problem with this code. The "Killer" teleports to the location and immediately goes back to the starting position. I have 7 locations for the "Killer" to teleport to (around the player). Whats wrong with this code? (I am a newbie) If possible could you add a sound to every point collected? example. When I get 1 points a sound/audio file plays. Thanks for answers!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FpsScoreScript : MonoBehaviour
{
public int points;
bool isTeleported1 = false;
bool isTeleported2 = false;
bool isTeleported3 = false;
bool isTeleported4 = false;
bool isTeleported5 = false;
bool isTeleported6 = false;
bool isTeleported7 = false;
bool isTeleported8 = false;
public GameObject Killer;
public GameObject Player;
public Transform Destination;
public Transform KillerDestFarBack;
public Transform KillerDestCloseBack;
public Transform KillerDestRight;
public Transform KillerDestLeft;
public Transform KillerDestRightFront;
public Transform KillerDestLeftFront;
public Transform KillerDestFront;
public void Update()
{
if (points == 1 && !isTeleported1)
{
Teleport1();
}
if (points == 2 && !isTeleported2)
{
Teleport2();
}
if (points == 3 && !isTeleported3)
{
Teleport3();
}
if (points == 4 && !isTeleported4)
{
Teleport4();
}
if (points == 5 && !isTeleported5)
{
Teleport5();
}
if (points == 6 && !isTeleported6)
{
Teleport6();
}
if (points == 7 && !isTeleported7)
{
Teleport7();
}
if (points == 8 && !isTeleported8)
{
Teleport8();
}
}
void Teleport1()
{
isTeleported1 = true;
Killer.transform.position = KillerDestFront.transform.position;
}
void Teleport2()
{
isTeleported2 = true;
Killer.transform.position = KillerDestRightFront.transform.position;
}
void Teleport3()
{
isTeleported3 = true;
Killer.transform.position = KillerDestLeftFront.transform.position;
}
void Teleport4()
{
isTeleported4 = true;
Killer.transform.position = KillerDestRight.transform.position;
}
void Teleport5()
{
isTeleported5 = true;
Killer.transform.position = KillerDestLeft.transform.position;
}
void Teleport6()
{
isTeleported6 = true;
Killer.transform.position = KillerDestFarBack.transform.position;
}
void Teleport7()
{
isTeleported7 = true;
Killer.transform.position = KillerDestCloseBack.transform.position;
}
void Teleport8()
{
isTeleported8 = true;
Player.transform.position = Destination.transform.position;
}
}
Instead of using many Transform vars, I would prefer using a transform array, also I have used an array of bools has teleported. I would prefer you to follow some tutorials or get a book. Add a collider to your player and the coin.
[SerializeField] Transform[] teleportPoints;
[SerializeField]Transform coin;
bool[] hasTeleported;
AudioSource source;
int points = 0 ;
void Awake()
{
source = GetComponent<AudioSource>();
hasTeleported = new bool[teleportPoints.Length];
}
private void Update()
{
for(int i = 0; i <= teleportPoints.Length; i++)
{
if (points == i && !hasTeleported[i])
{
Teleport(i);
}
}
}
void Teleport(int index)
{
transform.position = teleportPoints[index].position;
hasTeleported[index] = true;
}
void IncreasePoints()
{
source.Play();
points++;
}
private void OnCollisionEnter(Collision collision)
{
if(collision.gameObject == coin.gameObject)
{
IncreasePoints();
}
}
I am trying to get part of my game working but having trouble solving this problem!
I have boosters that remove game pieces if the user has enough in game coins to use. It is working to an extent and once a booster has been used the coins will decrement but upon exiting and reloading the game it does not update the correct value!
For example, the boosters can be used at a cost of 50 coins, if I have 200 coins and use 4 boosters the value updates to 0 and this works. However if I restart then the value of 200 is still there!
I have a coin manager script set up with playerprefs that gives the user 50 coins after each level, this is linked to the booster script.
Booster class:
public class Booster : MonoBehaviour, IDragHandler, IBeginDragHandler, IEndDragHandler {
Image m_image;
RectTransform m_rectXform;
Vector3 m_startPosition;
Board m_board;
Tile m_tileTarget;
public static GameObject ActiveBooster;
public Text instructionsText;
public string instructions = "drag over game piece to remove";
public bool isEnabled = false;
public bool isDraggable = false;
public bool isLocked = false;
public List<CanvasGroup> canvasGroups;
public UnityEvent boostEvent;
public int boostTime = 15;
//coin test
CoinManager coinManager;
private void Awake()
{
m_image = GetComponent<Image> ();
m_rectXform = GetComponent<RectTransform> ();
m_board = Object.FindObjectOfType<Board> ().GetComponent<Board> ();
coinManager = GameObject.Find ("CoinManager").GetComponent<CoinManager> ();
}
void Start ()
{
EnableBooster (false);
}
public void EnableBooster(bool state)
{
isEnabled = state;
if (state)
{
DisableOtherBoosters ();
Booster.ActiveBooster = gameObject;
}
else if(gameObject == Booster.ActiveBooster)
{
Booster.ActiveBooster = null;
}
m_image.color = (state) ? Color.white : Color.gray;
if (instructionsText != null)
{
instructionsText.gameObject.SetActive (Booster.ActiveBooster != null);
if (gameObject == Booster.ActiveBooster)
{
instructionsText.text = instructions;
}
}
}
void DisableOtherBoosters()
{
Booster[] allBoosters = Object.FindObjectsOfType<Booster> ();
foreach (Booster b in allBoosters)
{
if (b != this)
{
b.EnableBooster (false);
}
}
}
public void ToggleBooster()
{
EnableBooster (!isEnabled);
}
public void OnBeginDrag (PointerEventData eventData)
{
if (isEnabled && isDraggable && !isLocked)
{
m_startPosition = gameObject.transform.position;
EnableCanvasGroups (false);
}
}
public void OnDrag (PointerEventData eventData)
{
if (isEnabled && isDraggable && !isLocked && Camera.main != null)
{
Vector3 onscreenPosition;
RectTransformUtility.ScreenPointToWorldPointInRectangle (m_rectXform, eventData.position,
Camera.main, out onscreenPosition);
gameObject.transform.position = onscreenPosition;
RaycastHit2D hit2D = Physics2D.Raycast (onscreenPosition, Vector3.forward, Mathf.Infinity);
if (hit2D.collider != null)
{
m_tileTarget = hit2D.collider.GetComponent<Tile> ();
}
else
{
m_tileTarget = null;
}
}
}
public void OnEndDrag (PointerEventData eventData)
{
if (isEnabled && isDraggable && !isLocked)
{
gameObject.transform.position = m_startPosition;
EnableCanvasGroups (true);
if (m_board != null && m_board.isRefilling)
{
return;
}
if (m_tileTarget != null)
{
if (boostEvent != null)
{
boostEvent.Invoke (); //can do things here like play a sound effect
}
EnableBooster (false);
m_tileTarget = null;
Booster.ActiveBooster = null;
}
}
}
void EnableCanvasGroups(bool state)
{
if (canvasGroups != null && canvasGroups.Count > 0)
{
foreach (CanvasGroup cGroup in canvasGroups)
{
if (cGroup != null)
{
cGroup.blocksRaycasts = state;
}
}
}
}
public void RemoveOneGamePiece()
{
if (m_board != null && m_tileTarget != null)
{
if (coinManager.currentCoinCount >= 50)
{
m_board.ClearAndRefillBoard (m_tileTarget.xIndex, m_tileTarget.yIndex);
coinManager.AddCoins (-50);
coinManager.SetCoinCount();
coinManager.ShowCoinCount ();
}
}
}
public void AddTime()
{
if (GameManager.Instance != null)
{
if (coinManager.currentCoinCount >= 50){
GameManager.Instance.AddTime (boostTime);
coinManager.AddCoins (-50);
coinManager.SetCoinCount();
coinManager.ShowCoinCount ();
}
}
}
public void DropColorBomb() //big bomb
{
if (m_board != null && m_tileTarget != null)
{
if (coinManager.currentCoinCount >= 50)
{
m_board.MakeColorBombBooster (m_tileTarget.xIndex, m_tileTarget.yIndex);
coinManager.AddCoins (-50);
coinManager.SetCoinCount();
coinManager.ShowCoinCount ();
}
}
}
}
CoinManager class:
public class CoinManager : Singleton<CoinManager>{
// reference to the UI Text element
public Text coinText;
// current number of coins earned during gameplay
public int currentCoinCount = 0;
// because we don't have a key set, we should create it and initialize its value to 0
public void InitCoinCount()
{
if (!PlayerPrefs.HasKey("TotalCoins"))
{
PlayerPrefs.SetInt("TotalCoins",0);
}
}
// returns the number of coins stored in PlayerPrefs
public int GetCoinCount()
{
if (PlayerPrefs.HasKey("TotalCoins"))
{
return PlayerPrefs.GetInt("TotalCoins");
}
// if we don't have the key set, so return 0
return 0;
}
// sets a number of coins into PlayerPrefs if the current coin count is greater
public void SetCoinCount()
{
if (PlayerPrefs.HasKey("TotalCoins"))
{
int oldCoins = PlayerPrefs.GetInt("TotalCoins");
if (currentCoinCount > oldCoins)
{
PlayerPrefs.SetInt("TotalCoins", currentCoinCount);
}
}
}
// display the coin count as a TextUI
public void ShowCoinCount()
{
if (coinText != null)
{
coinText.text = currentCoinCount.ToString();
}
}
//new method for oldcoin count
public void AddCoins(int coins)
{
currentCoinCount = currentCoinCount + coins;
}
}
// sets a number of coins into PlayerPrefs if the current coin count is greater
Well, this comment basically tells you the problem. If the coin count isn't greater than what was saved previously, it doesn't save!
Change this:
// sets a number of coins into PlayerPrefs if the current coin count is greater
public void SetCoinCount()
{
if (PlayerPrefs.HasKey("TotalCoins"))
{
int oldCoins = PlayerPrefs.GetInt("TotalCoins");
if (currentCoinCount > oldCoins)
{
PlayerPrefs.SetInt("TotalCoins", currentCoinCount);
}
}
}
To this:
// sets a number of coins into PlayerPrefs
public void SetCoinCount()
{
PlayerPrefs.SetInt("TotalCoins", currentCoinCount);
}
i am adding medals in my game like flappy bird, everything was working then i just stoped , and dont know what to do it gives me a error messege
NullReferenceException: Object reference not set to an instance of an object
ScoreManager.Start () (at Assets/scripts/ScoreManager.cs:27)
I`ve checked code lines and they were working fine until one moment ,with the same code.
But if i delete that object it shows me that the next isnt correct
Score script
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class ScoreManager : MonoBehaviour
{
private float score = 0f;
public Text Scoretext;
public MenuController deathmenu;
public GameObject IntroGUI, DeathGUI, Canvas;
private GameObject bronze;
private GameObject bronzesilver;
private GameObject silver;
private GameObject silvergold;
private GameObject gold;
void Start()
{
bronze = GameObject.Find("bronze");
bronzesilver = GameObject.Find("bronzesilver");
silver = GameObject.Find("silver");
silvergold = GameObject.Find("silvergold");
gold = GameObject.Find("gold");
bronze.GetComponent<Image>().enabled = false;
bronzesilver.GetComponent<Image>().enabled = false;
silver.GetComponent<Image>().enabled = false;
silvergold.GetComponent<Image>().enabled = false;
gold.GetComponent<Image>().enabled = false;
}
void Update()
{
//handle back key in Windows Phone
if (Input.GetKeyDown(KeyCode.Escape))
Application.Quit();
if (GameStateManager.GameState == GameState.Intro)
{
if (WasTouchedOrClicked())
{
GameStateManager.GameState = GameState.Playing;
IntroGUI.SetActive(false);
Canvas.SetActive(true);
}
}
else if (GameStateManager.GameState == GameState.Playing)
{
score += Time.deltaTime;
Scoretext.text = ((int)score).ToString();
if (PlayerPrefs.GetFloat("Highscore") < score)
PlayerPrefs.SetFloat("Highscore", score);
if (score > 2)
{
bronze.GetComponent<Image>().enabled = true;
}
if (score > 4)
{
bronzesilver.GetComponent<Image>().enabled = true;
}
if (score > 7)
{
silver.GetComponent<Image>().enabled = true;
}
if
(score > 9)
{
silvergold.GetComponent<Image>().enabled = true;
}
if
(score > 12)
{
gold.GetComponent<Image>().enabled = true;
}
deathmenu.ToggleEndMenu(score);
}
}
void FixedUpdate()
{
//just jump up and down on intro screen
if (GameStateManager.GameState == GameState.Intro)
{
}
else if
(GameStateManager.GameState == GameState.Playing || GameStateManager.GameState == GameState.Dead)
{
}
}
bool WasTouchedOrClicked()
{
if (Input.GetButtonUp("Jump") || Input.GetMouseButtonDown(0) ||
(Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began))
return true;
else
return false;
}
void OnCollisionEnter2D(Collision2D col)
{
if (GameStateManager.GameState == GameState.Playing)
{
if (col.gameObject.tag == "CARS")
{
PlayerDies();
}
}
}
void PlayerDies()
{
GameStateManager.GameState = GameState.Dead;
DeathGUI.SetActive(true);
}
}
My code works perfectly in the player class, but when I try to put it in a different class, it does nothing. My player doesn't lose lifes, and he doesn't die.
Here it doesn't work:
Spikes class
using UnityEngine;
using System.Collections;
public class Spikes : MonoBehaviour
{
SimplePlayer0 player = new SimplePlayer0();
Animator anim;
private bool isDead;
void OnCollisionEnter2D(Collision2D other)
{
if (other.gameObject.tag == "spike" && !isDead && player.Lives <= 1 && !player.IsImmune)
{
player.Lives = 0;
isDead = true;
}
else if (other.gameObject.tag == "spike" && player.Lives >= 1 && !player.IsImmune)
{
player.Lives--;
anim.SetBool("Immume", true);
player.IsImmune = true;
}
}
void OnTriggerStay2D(Collider2D other)
{
if (other.tag == "spike" && !isDead && player.Lives <= 1 && !player.IsImmune)
{
player.Lives = 0;
isDead = true;
}
else if (other.gameObject.tag == "spike" && player.Lives >= 1 && !player.IsImmune)
{
player.Lives--;
anim.SetBool("Immume", true);
player.IsImmune = true;
}
}
void OnCollisionStay2D(Collision2D other)
{
if (other.gameObject.tag == "spike" && !isDead && player.Lives <= 1 && !player.IsImmune)
{
player.Lives = 0;
isDead = true;
}
else if (other.gameObject.tag == "spike" && player.Lives > 1 && !player.IsImmune)
{
player.Lives--;
anim.SetBool("Immune", true);
player.IsImmune = true;
}
else if (other.gameObject.tag == "Underground")
{
isDead = true;
}
}
void Dead()
{
if (isDead == true)
{
Application.LoadLevel(8);
}
}
}
Player class
using UnityEngine;
using System.Collections;
public class SimplePlayer0 : MonoBehaviour
{
Animator anim;
//Lives
private int lives = 3;
private bool isImmune;
public float immuneCounter;
public float immuneTime;
//PROPERTIES
public int Lives
{
get { return lives; }
set { lives = value; }
}
public bool IsImmune
{
get { return isImmune; }
set { isImmune = value; }
}
void Start ()
{
anim = GetComponent<Animator>();
}
void Update()
{
if (IsImmune)
{
immuneCounter -= Time.deltaTime;
}
if (immuneCounter <= 0)
{
IsImmune = false;
immuneCounter = immuneTime;
anim.SetBool("Immume", false);
}
}
This was the original code where it did work:
using UnityEngine;
using System.Collections;
public class Player0 : MonoBehaviour
{
Animator anim;
//Lives
public int lives = 3;
public bool isImmune;
public float immuneCounter;
public float immuneTime;
public bool isDead;
void Start()
{
anim = GetComponent<Animator>();
}
void Update()
{
if (isImmune)
{
immuneCounter -= Time.deltaTime;
}
if (immuneCounter <= 0)
{
isImmune = false;
immuneCounter = immuneTime;
anim.SetBool("Immume", false);
}
if (isDead == true)
{
Application.LoadLevel(8);
}
void OnCollisionEnter2D(Collision2D other)
{
if (other.gameObject.tag == "spike" && !isDead && lives <= 1 && !isImmune)
{
rigidbody2D.velocity = Vector2.zero;
lives = 0;
rigidbody2D.AddForce(new Vector2(0, 200)); // death animation
isDead = true;
}
else if (other.gameObject.tag == "spike" && lives >= 1 && !isImmune)
{
lives--;
anim.SetBool("Immume", true);
isImmune = true;
}
}
void OnTriggerStay2D(Collider2D other)
{
if (other.tag == "spike" && !isDead && lives <= 1 && !isImmune)
{
rigidbody2D.velocity = Vector2.zero;
lives = 0;
rigidbody2D.AddForce(new Vector2(0, 200));
isDead = true;
}
else if (other.gameObject.tag == "spike" && lives >= 1 && !isImmune)
{
lives--;
anim.SetBool("Immume", true);
isImmune = true;
}
else if (other.gameObject.tag == "Underground")
{
rigidbody2D.AddForce(new Vector2(0, 200));
isDead = true;
}
}
void OnCollisionStay2D(Collision2D other)
{
if (other.gameObject.tag == "spike" && !isDead && lives <= 1 && !isImmune)
{
rigidbody2D.velocity = Vector2.zero;
lives = 0;
rigidbody2D.AddForce(new Vector2(0, 200));
isDead = true;
}
else if (other.gameObject.tag == "spike" && lives > 1 && !isImmune)
{
lives--;
anim.SetBool("Immune", true);
isImmune = true;
}
else if (other.gameObject.tag == "Underground")
{
rigidbody2D.velocity = Vector2.zero;
lives = 0;
isDead = true;
}
}
}
My guess is that your "Player" doesn't lose lives, because the object you're subtracting the lives from isn't your player. In your Spikes class, you're creating an all new Player object and decreasing the lives from that object, not your already available one.
What I would do, is have a GameController script, which instantiates the player (and anything else that may be required). That way, you know that you've only got one player object to work with.
For example:
public static class GameController
{
public static Player myOnlyPlayer; // either drag in the editor, or instantiate
}
Then you can use the following to access the object:
public class Spike
{
void OnCollisionEnter2D(Collision2D other)
{
// Do something with:
GameController.myOnlyPlayer.ReduceLifeCount();
}
}
Hope this helps!
Firstly - instantiating subclasses of MonoBehaviour via new is an error in itself - I am referring to SimplePlayer0 player = new SimplePlayer0(); in Spikes.cs. Don't do that.
Secondly - LokiSinclair's answer would work, but using a global variable for storing player and always applying the damage to it is very limiting. We should just check for what has collided with spikes and then decide what to do with it (mind you, my code isn't a really elegant solution either):
using UnityEngine;
using System.Collections;
public class Spikes : MonoBehaviour
{
private void ResolveDamage(Collision2D other){
if (other.gameObject.tag == "player"){
var player = other.gameObject.getComponent<SimplePlayer0>();
if(!player.IsImmune){
player.Lives--;
}
}
}
void OnCollisionEnter2D(Collision2D other)
{
ResolveDamage(other);
}
void OnTriggerStay2D(Collision2D other)
{
ResolveDamage(other);
}
void OnCollisionStay2D(Collision2D other)
{
ResolveDamage(other);
}
}
And your player logic should be contained in Player class - that's just a good design principle to follow:
using UnityEngine;
using System.Collections;
public class SimplePlayer0 : MonoBehaviour
{
Animator anim;
//Lives
private int lives = 3;
private bool isImmune;
public float immuneCounter;
public float immuneTime;
//PROPERTIES
//putting some logic in getters-setters of your properties
public int Lives
{
get { return lives; }
set {
if(lives != value){
lives = value;
if(IsDead){
Dead();
}else{
IsImmune = true;
}
}
}
}
private void Dead()
{
Application.LoadLevel(8);
}
public bool IsImmune
{
get { return isImmune; }
set {
if(isImmune != value){
isImmune = value;
anim.SetBool("Immume", isImmune);
//ternary operator - a shorthand for if-else statement
immuneCounter = isImmune ? immuneTime : 0;
}
}
}
public bool IsDead{
get{
return Lives <= 0;
}
}
void Start ()
{
anim = GetComponent<Animator>();
}
void Update()
{
if (IsImmune)
{
immuneCounter -= Time.deltaTime;
}
if (immuneCounter <= 0)
{
IsImmune = false;
}
}