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();
}
}
Related
Optimization script doesn`t work. I made a script to optimize my game in unity, when the player is standing, everything is fine, But once it starts to go... Framerate Per Second starts to decrease to zero, tell me what should I do? After all, the player does not perform heavy operations, how can this load something? (I tried OnBecameVisible and OnBecameInvisible they don't work)
~Scripts~
using UnityEngine;
[RequireComponent(typeof(ObjectParameters))]
public class ObjectManager : MonoCache
{
public SpriteRenderer[] spriteRenderers;
[Space]
public ObjectParameters objectParameters;
[Space]
[SerializeField] bool freezeRotation;
bool isBuilded;
[Space]
public bool usingDragging = true;
[Space]
[SerializeField] bool usingRigidBody;
Rigidbody2D rb2D;
float gS;
[Space]
[SerializeField] bool usingSheetDrop;
SheetDrop sheetDrop;
void Start()
{
rb2D = GetComponent<Rigidbody2D>();
objectParameters = GetComponent<ObjectParameters>();
sheetDrop = GetComponent<SheetDrop>();
if (usingRigidBody == true)
{
rb2D.constraints = RigidbodyConstraints2D.FreezeAll;
gS = rb2D.gravityScale;
}
if (usingSheetDrop == true)
{
sheetDrop.enabled = false;
}
objectParameters.enabled = false;
for (int i = 0; i < spriteRenderers.Length; i++)
{
spriteRenderers[i].enabled = false;
}
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.tag == "PlayerDrawing")
{
if (usingRigidBody == true)
{
if (rb2D == null)
{
rb2D = GetComponent<Rigidbody2D>();
}
if (freezeRotation == false)
{
rb2D.constraints = RigidbodyConstraints2D.None;
}
}
if (usingSheetDrop == true)
{
sheetDrop.enabled = true;
}
objectParameters.enabled = true;
for (int i = 0; i < spriteRenderers.Length; i++)
{
spriteRenderers[i].enabled = true;
}
}
}
private void OnTriggerExit2D(Collider2D collision)
{
if (collision.tag == "PlayerDrawing")
{
if (usingRigidBody == true)
{
if (rb2D == null)
{
rb2D = GetComponent<Rigidbody2D>();
}
if (rb2D.constraints != RigidbodyConstraints2D.FreezeAll || rb2D.bodyType != RigidbodyType2D.Kinematic)
{
rb2D.constraints = RigidbodyConstraints2D.FreezeAll;
}
}
}
if (usingSheetDrop == true)
{
sheetDrop.enabled = false;
}
objectParameters.enabled = false;
for (int i = 0; i < spriteRenderers.Length; i++)
{
spriteRenderers[i].enabled = false;
}
}
}
and ObjectParameters
using UnityEngine;
public class ObjectParameters : MonoCache
{
public Dragging dragging;
public Rigidbody2D rb;
public Vector3 position;
public Quaternion rotation;
ObjectManager objectManager;
Transform transform_;
void Start()
{
objectManager = GetComponent<ObjectManager>();
transform_ = transform;
rb = GetComponent<Rigidbody2D>();
}
public override void OnTick()
{
position = transform_.position;
rotation = transform_.rotation;
}
}
I wanted the script to work like this: When an object touches the Player Drawing, it turns on physic and SpriteRenderer, otherwise everything would happen in reverse. BUT IT DOESN'T WORK.
help please
Make sure you don't have any exceptions spamming into the console when you walk.
Also make sure to use the Profiler to see what method-calls are using the most of your framerate, you might have to turn on the deep profiler to see the exact methods.
In my game in unity C#, I have two classes one is a PlayerHealth and the other is EnemyHealth they have the same functions but these two fields are inverted currentHapinessPower and currentSadnesPower.
I don't know if i should use the polymorphism principle or inheritance or interfaces.
These are the classes:
public class PlayerHealth : MonoBehaviour
{
#region Public Instances
public GameObject Player;
public GameObject Pl_DeathParticle;
public TextMeshProUGUI NumOfHappyPower;
public TextMeshProUGUI NumOfSadPower;
#endregion
#region HapAndSad System Variables
public int playerHappinessPower;
[HideInInspector] public int currentHappinessPower; <--
[HideInInspector] public int currentSadnesPower; <--These two
#endregion
#region HapAndSad States
private bool isSad = false;
#endregion
void Start()
{
currentHappinessPower = playerHappinessPower; // in the enemy class is currentSadnessPower
NumOfSadPower.enabled = false; // here in the enemy class is true
}
void Update()
{
HapAndSadPowerSystem();
StartCoroutine(CheckThePlayerSadState());
}
void HapAndSadPowerSystem()
{
if (currentHappinessPower > 0) //enemy class: currentSadnessPower
{
NumOfHappyPower.text = currentHappinessPower.ToString(); //also here is changed
}
else if (currentHappinessPower == 0) // here also is currentSadnessPower
{
NumOfHappyPower.enabled = false;
NumOfSadPower.enabled = true;
}
else if (currentHappinessPower < 0 && currentSadnesPower == 0) //and here
{
isSad = true; // enemy class is false
currentSadnesPower = currentHappinessPower * -1; //Make the rest of the soubstraction positive / also here its inverted
NumOfHappyPower.enabled = false; //true in the enemy class
NumOfSadPower.enabled = true; // false
NumOfSadPower.text = currentSadnesPower.ToString();
}
else if (currentSadnesPower > 0)
{
NumOfSadPower.text = currentSadnesPower.ToString();
}
}
IEnumerator CheckThePlayerSadState()
{
if (isSad == true) //here is false
{
yield return new WaitForSeconds(2f);
GameObject PlayerDeath_particle_prefab = Instantiate(Pl_DeathParticle, Player.transform.position, Quaternion.identity);
Destroy(PlayerDeath_particle_prefab.gameObject, 1f);
Destroy(Player.gameObject);
}
}
}
And here is the enemy class:
public class EnemyHealth : MonoBehaviour
#region Public Instances
public GameObject Enemy;
public GameObject En_DeathParticle;
public TextMeshProUGUI NumOfHappyPower;
public TextMeshProUGUI NumOfSadPower;
#endregion
#region HapAndSad System Variables
public int enemySadnesPower;
[HideInInspector] public int currentHappinessPower;
[HideInInspector] public int currentSadnesPower;
#endregion
#region HapAndSad States
private bool isSad = true;
#endregion
void Start()
{
currentSadnesPower = enemySadnesPower;
NumOfHappyPower.enabled = false;
}
void Update()
{
HapAndSadPowerSystem();
StartCoroutine(CheckThePlayerSadState());
}
void HapAndSadPowerSystem()
{
if (currentSadnesPower > 0)
{
NumOfSadPower.text = currentSadnesPower.ToString();
}
else if (currentSadnesPower == 0)
{
NumOfHappyPower.enabled = true;
NumOfSadPower.enabled = false;
}
else if (currentSadnesPower < 0 && currentHappinessPower == 0)
{
isSad = false;
currentHappinessPower = currentSadnesPower * -1;
NumOfHappyPower.enabled = true;
NumOfSadPower.enabled = false;
NumOfHappyPower.text = currentHappinessPower.ToString();
}
else if (currentHappinessPower > 0)
{
NumOfHappyPower.text = currentHappinessPower.ToString();
}
}
IEnumerator CheckThePlayerSadState()
{
if (isSad == false)
{
yield return new WaitForSeconds(2f);
GameObject PlayerDeath_particle_prefab = Instantiate(En_DeathParticle, Enemy.transform.position, Quaternion.identity);
Destroy(PlayerDeath_particle_prefab.gameObject, 1f);
Destroy(Enemy.gameObject);
}
}
}
These scripts are almost identical. I would use the same script as the player and the enemy. And add a boolean to distinguish between the player and the enemy.
Edit:
If you want to use inheritance or polymorphism desperately, I would recommend you to make an Entity class and make Player and Enemy derive from it.
My Game is working perfectly in Unity but when I export apk tp Android Mobile 2nd Scene doesn't load properly and does not work.
Please look at the image. It is the second Scene and not loaded properly and the Run button is not working which is working perfectly in unity play mode.
enter image description here
CODES ARE BELOW
SCENE 1 CODE#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
#if UNITY_ANALYTICS
using UnityEngine.Analytics;
#endif
#if UNITY_PURCHASING
using UnityEngine.Purchasing;
#endif
public class StartButton : MonoBehaviour
{
public void StartGame()
{
if (PlayerData.instance.ftueLevel == 0)
{
PlayerData.instance.ftueLevel = 1;
PlayerData.instance.Save();
#if UNITY_ANALYTICS
AnalyticsEvent.FirstInteraction("start_button_pressed");
#endif
}
#if UNITY_PURCHASING
var module = StandardPurchasingModule.Instance();
#endif
SceneManager.LoadScene("main");
}
}
SCENE 2 CODE#
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
#if UNITY_ANALYTICS
using UnityEngine.Analytics;
#endif
/// <summary>
/// State pushed on the GameManager during the Loadout, when player select player, theme and accessories
/// Take care of init the UI, load all the data used for it etc.
/// </summary>
public class LoadoutState : AState
{
public Canvas inventoryCanvas;
[Header("Char UI")]
public Text charNameDisplay;
public RectTransform charSelect;
public Transform charPosition;
[Header("Theme UI")]
public Text themeNameDisplay;
public RectTransform themeSelect;
public Image themeIcon;
[Header("PowerUp UI")]
public RectTransform powerupSelect;
public Image powerupIcon;
public Text powerupCount;
public Sprite noItemIcon;
[Header("Accessory UI")]
public RectTransform accessoriesSelector;
public Text accesoryNameDisplay;
public Image accessoryIconDisplay;
[Header("Other Data")]
public Leaderboard leaderboard;
public MissionUI missionPopup;
public Button runButton;
public GameObject tutorialBlocker;
public GameObject tutorialPrompt;
public MeshFilter skyMeshFilter;
public MeshFilter UIGroundFilter;
public AudioClip menuTheme;
[Header("Prefabs")]
public ConsumableIcon consumableIcon;
Consumable.ConsumableType m_PowerupToUse = Consumable.ConsumableType.NONE;
protected GameObject m_Character;
protected List<int> m_OwnedAccesories = new List<int>();
protected int m_UsedAccessory = -1;
protected int m_UsedPowerupIndex;
protected bool m_IsLoadingCharacter;
protected Modifier m_CurrentModifier = new Modifier();
protected const float k_CharacterRotationSpeed = 45f;
protected const string k_ShopSceneName = "shop";
protected const float k_OwnedAccessoriesCharacterOffset = -0.1f;
protected int k_UILayer;
protected readonly Quaternion k_FlippedYAxisRotation = Quaternion.Euler (0f, 180f, 0f);
public override void Enter(AState from)
{
tutorialBlocker.SetActive(!PlayerData.instance.tutorialDone);
tutorialPrompt.SetActive(false);
inventoryCanvas.gameObject.SetActive(true);
missionPopup.gameObject.SetActive(false);
charNameDisplay.text = "";
themeNameDisplay.text = "";
k_UILayer = LayerMask.NameToLayer("UI");
skyMeshFilter.gameObject.SetActive(true);
UIGroundFilter.gameObject.SetActive(true);
// Reseting the global blinking value. Can happen if the game unexpectedly exited while still blinking
Shader.SetGlobalFloat("_BlinkingValue", 0.0f);
if (MusicPlayer.instance.GetStem(0) != menuTheme)
{
MusicPlayer.instance.SetStem(0, menuTheme);
StartCoroutine(MusicPlayer.instance.RestartAllStems());
}
runButton.interactable = false;
runButton.GetComponentInChildren<Text>().text = "Loading...";
if(m_PowerupToUse != Consumable.ConsumableType.NONE)
{
//if we come back from a run and we don't have any more of the powerup we wanted to use, we reset the powerup to use to NONE
if (!PlayerData.instance.consumables.ContainsKey(m_PowerupToUse) || PlayerData.instance.consumables[m_PowerupToUse] == 0)
m_PowerupToUse = Consumable.ConsumableType.NONE;
}
Refresh();
}
public override void Exit(AState to)
{
missionPopup.gameObject.SetActive(false);
inventoryCanvas.gameObject.SetActive(false);
if (m_Character != null) Addressables.ReleaseInstance(m_Character);
GameState gs = to as GameState;
skyMeshFilter.gameObject.SetActive(false);
UIGroundFilter.gameObject.SetActive(false);
if (gs != null)
{
gs.currentModifier = m_CurrentModifier;
// We reset the modifier to a default one, for next run (if a new modifier is applied, it will replace this default one before the run starts)
m_CurrentModifier = new Modifier();
if (m_PowerupToUse != Consumable.ConsumableType.NONE)
{
PlayerData.instance.Consume(m_PowerupToUse);
Consumable inv = Instantiate(ConsumableDatabase.GetConsumbale(m_PowerupToUse));
inv.gameObject.SetActive(false);
gs.trackManager.characterController.inventory = inv;
}
}
}
public void Refresh()
{
PopulatePowerup();
StartCoroutine(PopulateCharacters());
StartCoroutine(PopulateTheme());
}
public override string GetName()
{
return "Loadout";
}
public override void Tick()
{
if (!runButton.interactable)
{
bool interactable = ThemeDatabase.loaded && CharacterDatabase.loaded;
if(interactable)
{
runButton.interactable = true;
runButton.GetComponentInChildren<Text>().text = "Run!";
//we can always enabled, as the parent will be disabled if tutorial is already done
tutorialPrompt.SetActive(true);
}
}
if(m_Character != null)
{
m_Character.transform.Rotate(0, k_CharacterRotationSpeed * Time.deltaTime, 0, Space.Self);
}
charSelect.gameObject.SetActive(PlayerData.instance.characters.Count > 1);
themeSelect.gameObject.SetActive(PlayerData.instance.themes.Count > 1);
}
public void GoToStore()
{
UnityEngine.SceneManagement.SceneManager.LoadScene(k_ShopSceneName, UnityEngine.SceneManagement.LoadSceneMode.Additive);
}
public void ChangeCharacter(int dir)
{
PlayerData.instance.usedCharacter += dir;
if (PlayerData.instance.usedCharacter >= PlayerData.instance.characters.Count)
PlayerData.instance.usedCharacter = 0;
else if(PlayerData.instance.usedCharacter < 0)
PlayerData.instance.usedCharacter = PlayerData.instance.characters.Count-1;
StartCoroutine(PopulateCharacters());
}
public void ChangeAccessory(int dir)
{
m_UsedAccessory += dir;
if (m_UsedAccessory >= m_OwnedAccesories.Count)
m_UsedAccessory = -1;
else if (m_UsedAccessory < -1)
m_UsedAccessory = m_OwnedAccesories.Count-1;
if (m_UsedAccessory != -1)
PlayerData.instance.usedAccessory = m_OwnedAccesories[m_UsedAccessory];
else
PlayerData.instance.usedAccessory = -1;
SetupAccessory();
}
public void ChangeTheme(int dir)
{
PlayerData.instance.usedTheme += dir;
if (PlayerData.instance.usedTheme >= PlayerData.instance.themes.Count)
PlayerData.instance.usedTheme = 0;
else if (PlayerData.instance.usedTheme < 0)
PlayerData.instance.usedTheme = PlayerData.instance.themes.Count - 1;
StartCoroutine(PopulateTheme());
}
public IEnumerator PopulateTheme()
{
ThemeData t = null;
while (t == null)
{
t = ThemeDatabase.GetThemeData(PlayerData.instance.themes[PlayerData.instance.usedTheme]);
yield return null;
}
themeNameDisplay.text = t.themeName;
themeIcon.sprite = t.themeIcon;
skyMeshFilter.sharedMesh = t.skyMesh;
UIGroundFilter.sharedMesh = t.UIGroundMesh;
}
public IEnumerator PopulateCharacters()
{
accessoriesSelector.gameObject.SetActive(false);
PlayerData.instance.usedAccessory = -1;
m_UsedAccessory = -1;
if (!m_IsLoadingCharacter)
{
m_IsLoadingCharacter = true;
GameObject newChar = null;
while (newChar == null)
{
Character c = CharacterDatabase.GetCharacter(PlayerData.instance.characters[PlayerData.instance.usedCharacter]);
if (c != null)
{
m_OwnedAccesories.Clear();
for (int i = 0; i < c.accessories.Length; ++i)
{
// Check which accessories we own.
string compoundName = c.characterName + ":" + c.accessories[i].accessoryName;
if (PlayerData.instance.characterAccessories.Contains(compoundName))
{
m_OwnedAccesories.Add(i);
}
}
Vector3 pos = charPosition.transform.position;
if (m_OwnedAccesories.Count > 0)
{
pos.x = k_OwnedAccessoriesCharacterOffset;
}
else
{
pos.x = 0.0f;
}
charPosition.transform.position = pos;
accessoriesSelector.gameObject.SetActive(m_OwnedAccesories.Count > 0);
AsyncOperationHandle op = Addressables.InstantiateAsync(c.characterName);
yield return op;
if (op.Result == null || !(op.Result is GameObject))
{
Debug.LogWarning(string.Format("Unable to load character {0}.", c.characterName));
yield break;
}
newChar = op.Result as GameObject;
Helpers.SetRendererLayerRecursive(newChar, k_UILayer);
newChar.transform.SetParent(charPosition, false);
newChar.transform.rotation = k_FlippedYAxisRotation;
if (m_Character != null)
Addressables.ReleaseInstance(m_Character);
m_Character = newChar;
charNameDisplay.text = c.characterName;
m_Character.transform.localPosition = Vector3.right * 1000;
//animator will take a frame to initialize, during which the character will be in a T-pose.
//So we move the character off screen, wait that initialised frame, then move the character back in place.
//That avoid an ugly "T-pose" flash time
yield return new WaitForEndOfFrame();
m_Character.transform.localPosition = Vector3.zero;
SetupAccessory();
}
else
yield return new WaitForSeconds(1.0f);
}
m_IsLoadingCharacter = false;
}
}
void SetupAccessory()
{
Character c = m_Character.GetComponent<Character>();
c.SetupAccesory(PlayerData.instance.usedAccessory);
if (PlayerData.instance.usedAccessory == -1)
{
accesoryNameDisplay.text = "None";
accessoryIconDisplay.enabled = false;
}
else
{
accessoryIconDisplay.enabled = true;
accesoryNameDisplay.text = c.accessories[PlayerData.instance.usedAccessory].accessoryName;
accessoryIconDisplay.sprite = c.accessories[PlayerData.instance.usedAccessory].accessoryIcon;
}
}
void PopulatePowerup()
{
powerupIcon.gameObject.SetActive(true);
if (PlayerData.instance.consumables.Count > 0)
{
Consumable c = ConsumableDatabase.GetConsumbale(m_PowerupToUse);
powerupSelect.gameObject.SetActive(true);
if (c != null)
{
powerupIcon.sprite = c.icon;
powerupCount.text = PlayerData.instance.consumables[m_PowerupToUse].ToString();
}
else
{
powerupIcon.sprite = noItemIcon;
powerupCount.text = "";
}
}
else
{
powerupSelect.gameObject.SetActive(false);
}
}
public void ChangeConsumable(int dir)
{
bool found = false;
do
{
m_UsedPowerupIndex += dir;
if(m_UsedPowerupIndex >= (int)Consumable.ConsumableType.MAX_COUNT)
{
m_UsedPowerupIndex = 0;
}
else if(m_UsedPowerupIndex < 0)
{
m_UsedPowerupIndex = (int)Consumable.ConsumableType.MAX_COUNT - 1;
}
int count = 0;
if(PlayerData.instance.consumables.TryGetValue((Consumable.ConsumableType)m_UsedPowerupIndex, out count) && count > 0)
{
found = true;
}
} while (m_UsedPowerupIndex != 0 && !found);
m_PowerupToUse = (Consumable.ConsumableType)m_UsedPowerupIndex;
PopulatePowerup();
}
public void UnequipPowerup()
{
m_PowerupToUse = Consumable.ConsumableType.NONE;
}
public void SetModifier(Modifier modifier)
{
m_CurrentModifier = modifier;
}
public void StartGame()
{
if (PlayerData.instance.tutorialDone)
{
if (PlayerData.instance.ftueLevel == 1)
{
PlayerData.instance.ftueLevel = 2;
PlayerData.instance.Save();
}
}
manager.SwitchState("Game");
}
public void Openleaderboard()
{
leaderboard.displayPlayer = false;
leaderboard.forcePlayerDisplay = false;
leaderboard.Open();
}
}
When you are building an APK file it can be splited to APK + OBB.
So, it is possible that you are trying to load a scene that is absent in your APK. You need to force the creation of the APK without the OBB. To do it you need to check Player Settings in Android, go to Publishing Settings and uncheck Split Application Binary.
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
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;
}
}