(Unity 2D, C#) Issue instantiating Prefabs that shouldn't be instantiated - c#

Background:
I'm trying to set up a system to spawn in a set amount of GameObjects, defined in the Menu Scene loaded before the Main Scene, into my game. I do this by running 3 for loops for the length of however many objects the user inputs in the Menu, with each loop run instantiating a copy of the Prefab.
The Problem:
Whenever the Main Scene (Game Scene) is loaded from the menu, it always spawns at least 1 of each Prefab even if the number is defined as 0 or null. This is an issue, as it always adds a copy of each Prefab on top of the user defined amount.
Partial Menu Image:
Menu segment for inputting values
Images of Issue:
Spawned assets in scene
Assets in navigator
So far I've tried setting up multiple Debug.Log(); -s throughout all the scripts that handle the numbers that are eventually parsed and passed to the spawning script itself (Data Managers, scriptable objs...) , as well as inside the spawning script itself. All the logs return the values as 0 and as such nothing should be spawning.
Code of the Spawner Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PawnSpawner : MonoBehaviour
{
[SerializeField] VarManager VarManager;
[SerializeField] GameObject Pawn;
[SerializeField] GameObject InfPawn;
[SerializeField] GameObject VaxPawn;
private int? totPawns;
private int? defPawns;
private int? infPawns;
private int? vaxPawns;
private void Awake()
{
VarManager = GameObject.Find("GameManager").GetComponent<VarManager>();
totPawns = VarManager.totalPawns;
defPawns = VarManager.uninfectedPawnAmount;
infPawns = VarManager.infectedPawnAmount;
vaxPawns = VarManager.vaccinatedPawnAmount;
}
// Start is called before the first frame update
void Start()
{
if(defPawns != 0 || defPawns != null)
{
for (int i = 0; i <= defPawns; i++)
{
int x = UnityEngine.Random.Range(-300, 301);
int y = UnityEngine.Random.Range(-300, 301);
GameObject D_Pawn = Instantiate(Pawn, new Vector3(x, y, 0), Quaternion.identity);
}
}
if(infPawns != 0 || infPawns != null)
{
for (int i = 0; i <= infPawns; i++)
{
int x = UnityEngine.Random.Range(-300, 301);
int y = UnityEngine.Random.Range(-300, 301);
GameObject I_Pawn = Instantiate(InfPawn, new Vector3(x, y, 0), Quaternion.identity);
}
}
if (vaxPawns != 0 || vaxPawns != null)
{
for (int i = 0; i <= vaxPawns; i++)
{
int x = UnityEngine.Random.Range(-300, 301);
int y = UnityEngine.Random.Range(-300, 301);
GameObject V_Pawn = Instantiate(VaxPawn, new Vector3(x, y, 0), Quaternion.identity);
}
}
}
// Update is called once per frame
void Update()
{
Destroy(this);
}
private void OnDestroy()
{
Debug.Log("---PAWN SPAWNER HAS FULLY EXECUTED SPAWNING SEQUENCE---");
Debug.Log("TOTAL PAWNS SPAWNED:" + totPawns);
Debug.Log("Default Pawns:" + defPawns);
Debug.Log("Infected Pawns:" + infPawns);
Debug.Log("Vaccinated Pawns:" + vaxPawns);
Debug.Log("---REMOVING SELF---");
}
}

Related

Variable is giving different values in different areas of the script (and when accessed in other scripts) and not updating the value

I am making a tower defense game and everytime I summon an enemy, i add 1 to the enemyCount variable. and everytime the enemy reaches the endpoint, I subtract 1 to the same variable. Default value is zero.
For some reason the variable gives different values in different parts of the script. I have 2 other scripts that has access to enemyCount. One is the PlayerUI script which just displays it, and the other is the enemyMovement script which is suppose to subtract 1 to it everytime the enemy object is destroyed.
The value of enemyCount in PlayerUI is 0, and it updates when the subtraction happens so it becomes -1.
Now when i run the game again, it retains the value of -1, and when subtracted to -2, its -2 that is displayed on the next run.
The value of enemyCount when I log it in the update function inside the script is that it updates to +1 when the enemy is summoned but doesnt update when the enemy is destroyed.
Can anyone point out what i did wrong?
WaveSpawner script:
public Transform enemyPrefab;
private Transform[] spawners;
private bool summonWave = false;
private float countDown = 2;
private int enemyPerWave = 1;
private int waveCtr = 0;
private int enemyCount;
void Awake() {
spawners = new Transform[transform.childCount];
for (var i = 0; i < spawners.Length; i++) {
spawners[i] = transform.GetChild(i);
}
}
void Start() {
enemyCount = 0;
}
void Update() {
if(countDown <= 0) {
summonWave = true;
countDown = 999;
}
if (summonWave) {
StartCoroutine(waveSpawner());
}else {
countDown -= Time.deltaTime;
}
Debug.Log(enemyCount); //GIVES THE RIGHT VALUE BUT DOESNT SUBTRACT 1 WHEN ENEMY IS DESTROYED
}
public int getEnemyCount() { //Accessed by the PlayerUI script. just to display it onscreen.
Debug.Log(enemyCount); // GIVES A VALUE OF N-1
return enemyCount;
}
public void reduceEnemyCount() { //Accessed by the EnemyMovement script.
enemyCount--; //IF THE ENEMY REACHES THE END, THIS FUNCTION IS CALLED AND THEN THE ENEMY OBJECT IS DESTROYED
}
IEnumerator waveSpawner() {
waveCtr++;
summonWave = false;
for (int i = 0; i < enemyPerWave; i++) {
summonEnemies();
yield return new WaitForSeconds(0.3f);
}
}
void summonEnemies() {
enemyCount += 1; //ADDS 1 TO THE VARIABLE EVERY TIME I SPAWN AN ENEMY UNIT. IN THIS CASE JUST 1
Instantiate(enemyPrefab, spawners[0].position, spawners[0].rotation);
//Instantiate(enemyPrefab, spawners[1].position, spawners[1].rotation);
//Instantiate(enemyPrefab, spawners[2].position, spawners[2].rotation);
//Instantiate(enemyPrefab, spawners[3].position, spawners[3].rotation);
}
}
EnemyMovement script:
public WaveSpawner spawner;
private float speed = 35f;
private int numberOfCycles = 2;
private Transform target;
private Transform startingPoint;
private int cycleCtr = 0;
private bool isDestroyed;
void Start() {
target = getClosestWaypoint(Waypoints.points);
startingPoint = target;
isDestroyed = false;
}
void Update() {
Vector3 dir = target.position - transform.position;
transform.Translate(dir.normalized * speed * Time.deltaTime, Space.World);
if (Vector3.Distance(transform.position, target.position) <= 0.2f && !isDestroyed) {
if (cycleCtr == numberOfCycles) {
spawner.reduceEnemyCount(); //subtracts the enemyCount in WaveSpawner
isDestroyed = true;
Destroy(gameObject); //destroying the enemy unit
} else {
if (target.name == startingPoint.name) {
cycleCtr++;
}
target = getToNextWaypoint(target);
}
}
}
PlayerUI script:
public Text enemyCount_UI;
[SerializeField]
private WaveSpawner spawner;
private int enemyCount_var;
void Start() {
enemyCount_UI.text = "Enemy count: 0";
enemyCount_var = 0;
}
void Update() {
enemyCount_var = spawner.getEnemyCount();
enemyCount_UI.text = "Enemy count: " + enemyCount_var.ToString();
}
I believe it is because you have assigned WaveSpawner prefab to EnemyMovement prefab and PlayerUI object. And you also probably have instance of WaveSpawner added somewhere in the scene.
Let's call WaveSpawner (from prefab) a PrefabSpawner and WaveSpawner (from scene) a SceneSpawner. When game is started, SceneSpawner is created. It has its own value of enemy count. When you spawn a prefab of EnemyMovement it is referencing PrefabSpawner, not SceneSpawner. What happens, is that SceneSpawner always incremets its own enemyCount, while EnemyMovement decreases count on PrefabSpawner. Because PlayerUI is also accessing PrefabSpawner it sees its value instead of SceneSpawner.
Try changing the spawning to this:
void summonEnemies() {
enemyCount += 1; //ADDS 1 TO THE VARIABLE EVERY TIME I SPAWN AN ENEMY UNIT. IN THIS CASE JUST 1
var enemyInstnace = Instantiate(enemyPrefab, spawners[0].position, spawners[0].rotation);
enemyInstance.spawner = this;
}
Rather than having WaveSpawner script on both PlayerUI and EnemyMovement, you'll want to make sure they are accessing the same instance of the script.
If you haven't already, create an empty game object to be your "wave spawner" in the scene and drop the WaveSpawner script on that.
Then update PlayerUI and EnemyMovement to get a reference to that game object, and then its WaveSpawner script
public Text enemyCount_UI;
[SerializeField]
private GameObject waveSpawnerGameObject;
private WaveSpawner spawner;
private int enemyCount_var;
void Start() {
enemyCount_UI.text = "Enemy count: 0";
enemyCount_var = 0;
}
void Awake()
{
// Get the reference here
spawner = waveSpawnerGameObject.GetComponent<WaveSpawner>();
}
void Update() {
enemyCount_var = spawner.getEnemyCount();
enemyCount_UI.text = "Enemy count: " + enemyCount_var.ToString();
}
And do the same for your enemy movement and enemy prefabs

Setting the spawn position for a 3D object

I am making an endless runner style game in unity where the floor tiles spawn randomly and endlessly in front of the player as they run and delete themselves after a certain distance behind the player this is all working fine and as intended however the individual tiles spawn about half way inside each other and as much as I try to debug my code I can't seem to effect them. Ideally, I want the code to do exactly what it's doing, but the tiles spawn end to end rather than inside each other.
Any help would be greatly appreciated.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Tile_Manager : MonoBehaviour
{
public GameObject[] tilePrefabs;
private Transform playerTransform;
private float spawnZ = 5.0f;
private float tileLength = 5.0f;
private float safeZone = 7.0f;
private int amtTilesOnScreen = 10;
private int lastPrefabIndex = 0;
private List<GameObject> activeTiles;
// Use this for initialization
void Start () {
activeTiles = new List<GameObject>();
playerTransform = GameObject.FindGameObjectWithTag ("Player").transform;
for (int i = 0; i < amtTilesOnScreen; i++)
{
if (i < 2)
SpawnTile(0);
else
SpawnTile();
}
}
// Update is called once per frame
void Update () {
if (playerTransform.position.z - safeZone > (spawnZ - amtTilesOnScreen * tileLength))
{
SpawnTile();
DeleteTile();
}
}
private void SpawnTile(int prefabIndex = -1)
{
GameObject go;
if (prefabIndex == -1)
go = Instantiate(tilePrefabs[RandomPrefabIndex()]) as GameObject;
else
go = Instantiate(tilePrefabs[prefabIndex]) as GameObject;
go.transform.SetParent(transform);
go.transform.position = Vector3.forward * spawnZ;
spawnZ += tileLength;
activeTiles.Add (go);
}
private void DeleteTile()
{
Destroy(activeTiles [0]);
activeTiles.RemoveAt (0);
}
private int RandomPrefabIndex()
{
if (tilePrefabs.Length <= 1)
return 0;
int randomIndex = lastPrefabIndex;
while (randomIndex == lastPrefabIndex)
{
randomIndex = Random.Range(0, tilePrefabs.Length);
}
lastPrefabIndex = randomIndex;
return randomIndex;
}
}
stacked tiles
You need to take the length of a tile into account. Try changing this
go.transform.position = Vector3.forward * spawnZ;
to this
go.transform.position = Vector3.forward * (spawnZ + tileLength / 2);
to add half the tile length to the spawn position.
Wouldn't you want
go.transform.Translate(Vector3.forward * spawnZ);
not position?
As you're spawning things relative to the world coordinate system.
https://docs.unity3d.com/ScriptReference/Transform.Translate.html

Disable rigidbody on a specific gameobject using C# and Unity

I'm having trouble in my pinch code because it also grabs my player. Here is my code:
using UnityEngine;
using System.Collections;
using Leap;
using Leap.Unity;
/**
* Detects pinches and grabs the closest rigidbody if it's within a given range.
*
* Attach this script to the physics hand object assinged to the HandController in a scene.
*/
public class MagneticPinch : MonoBehaviour {
public const float TRIGGER_DISTANCE_RATIO = 0.7f;
/** The stiffness of the spring force used to move the object toward the hand. */
public float forceSpringConstant = 100.0f;
/** The maximum range at which an object can be picked up.*/
public float magnetDistance = 0.5f;
protected bool pinching_;
protected Collider grabbed_;
public GameObject TrashAudio;
public GameObject myPlayer;
void Start() {
pinching_ = false;
grabbed_ = null;
}
/** Finds an object to grab and grabs it. */
void OnPinch(Vector3 pinch_position) {
pinching_ = true;
// Check if we pinched a movable object and grab the closest one that's not part of the hand.
Collider[] close_things = Physics.OverlapSphere(pinch_position, magnetDistance);
Vector3 distance = new Vector3(magnetDistance, 0.0f, 0.0f);
for (int j = 0; j < close_things.Length; ++j) {
Vector3 new_distance = pinch_position - close_things[j].transform.position;
if (close_things[j].GetComponent<Rigidbody>() != null && new_distance.magnitude < distance.magnitude &&
!close_things[j].transform.IsChildOf(transform)) {
grabbed_ = close_things[j];
distance = new_distance;
}
}
}
/** Clears the pinch state. */
void OnRelease() {
grabbed_ = null;
pinching_ = false;
TrashAudio.gameObject.SetActive (false);
//ActivateRigidbody ();
}
/**
* Checks whether the hand is pinching and updates the position of the pinched object.
*/
void Update() {
bool trigger_pinch = false;
HandModel hand_model = GetComponent<HandModel>();
Hand leap_hand = hand_model.GetLeapHand();
if (leap_hand == null)
return;
// Scale trigger distance by thumb proximal bone length.
Vector leap_thumb_tip = leap_hand.Fingers[0].TipPosition;
float proximal_length = leap_hand.Fingers[0].Bone(Bone.BoneType.TYPE_PROXIMAL).Length;
float trigger_distance = proximal_length * TRIGGER_DISTANCE_RATIO;
// Check thumb tip distance to joints on all other fingers.
// If it's close enough, start pinching.
for (int i = 1; i < HandModel.NUM_FINGERS && !trigger_pinch; ++i) {
Finger finger = leap_hand.Fingers[i];
for (int j = 0; j < FingerModel.NUM_BONES && !trigger_pinch; ++j) {
Vector leap_joint_position = finger.Bone((Bone.BoneType)j).NextJoint;
if (leap_joint_position.DistanceTo(leap_thumb_tip) < trigger_distance)
trigger_pinch = true;
}
}
Vector3 pinch_position = hand_model.fingers[0].GetTipPosition();
// Only change state if it's different.
if (trigger_pinch && !pinching_)
OnPinch(pinch_position);
else if (!trigger_pinch && pinching_)
OnRelease();
//this line of code is a self scripting for disabling the rigidbody from the player component
// Accelerate what we are grabbing toward the pinch.
if (grabbed_ != null) {
Vector3 distance = pinch_position - grabbed_.transform.position;
//DeactivateRigidbody (); //this is not to grab the rigidbody of the player
grabbed_.GetComponent<Rigidbody> ().AddForce (forceSpringConstant * distance);
TrashAudio.gameObject.SetActive (true);
//DeactivateRigidbody ();
}
}
}
Every object must have a rigidbody that is set to USE GRAVITY so my player as well so that it will not go through my terrain . My script is grabs the nearest object that has a rigidbody. The problem is when I grab some object its always grab itself I mean my player. I'm using a leap motion to grab.
So how can I obtain that if my script detects that it is grabbing my player it will stop grabbing but instead grab the object?
Really easy.
You can tag your player like player like in image:
then add to your code something like this into the method OnPinch
// Check if we pinched a movable object and grab the closest one that's not part of the hand.
Collider[] close_things = Physics.OverlapSphere(pinch_position, magnetDistance);
Vector3 distance = new Vector3(magnetDistance, 0.0f, 0.0f);
for (int j = 0; j < close_things.Length; ++j) {
if(close_things[j].gameobject.Tag.ToUppercase() == "PLAYER")
continue; //here you jump to a the next object
PS: Or you can simply use a different layer that ignore the player
By using
//attach this script to pinching
void DeactivateRigid(){
myPlayer.Getcomponent<Rigidbody>().isKenimatic == false;
myPlayer.Getcomponent<Rigidbody().detectCollision = true;
}
//attach this script to release
void ActivateRigid(){
...
}
My Unity is a bit rusted but you can attach a tag to GameObject, https://docs.unity3d.com/ScriptReference/GameObject-tag.html
Be sure to tag the player as a player, afterwards you could use a check whether the nearest gameobjects tag isn't "player".

objects using their own unique waypoints array

update...
First Class
using UnityEngine;
using System.Collections;
[System.Serializable]
public class Wave
{
public GameObject enemyPrefab;
public float spawnInterval = 2;
public int maxEnemies = 20;
}
public class SpawnEnemy : MonoBehaviour
{
public GameObject[] waypoints;
public GameObject testEnemyPrefab;
public Wave[] waves;
public int timeBetweenWaves = 5;
private GameManagerBehavior gameManager;
private float lastSpawnTime;
private int enemiesSpawned = 0;
// Use this for initialization
void Start()
{
lastSpawnTime = Time.time;
gameManager =
GameObject.Find("GameManager").GetComponent<GameManagerBehavior>();
}
// Update is called once per frame
void Update()
{
// 1 Get the index of the current wave, and check if it’s the last one.
int currentWave = gameManager.Wave;
if (currentWave < waves.Length)
{
// 2 If so, calculate how much time passed since the last enemy spawn and whether it’s time to spawn an enemy. Here you consider two cases.
// If it’s the first enemy in the wave, you check whether timeInterval is bigger than timeBetweenWaves.
// Otherwise, you check whether timeInterval is bigger than this wave’s spawnInterval. In either case, you make sure you haven’t spawned all the enemies for this wave.
float timeInterval = Time.time - lastSpawnTime;
float spawnInterval = waves[currentWave].spawnInterval;
if (((enemiesSpawned == 0 && timeInterval > timeBetweenWaves) ||
timeInterval > spawnInterval) &&
enemiesSpawned < waves[currentWave].maxEnemies)
{
// 3 If necessary, spawn an enemy by instantiating a copy of enemyPrefab. You also increase the enemiesSpawned count.
lastSpawnTime = Time.time;
GameObject newEnemy = (GameObject)
Instantiate(waves[currentWave].enemyPrefab);
newEnemy.GetComponent<MoveEnemy>().waypoints = waypoints;
newEnemy.GetComponent<MoveEnemy>().JiggleWaypoints();
enemiesSpawned++;
}
// 4 You check the number of enemies on screen. If there are none and it was the last enemy in the wave you spawn the next wave.
// You also give the player 10 percent of all gold left at the end of the wave.
if (enemiesSpawned == waves[currentWave].maxEnemies &&
GameObject.FindGameObjectWithTag("Enemy") == null)
{
gameManager.Wave++;
gameManager.Gold = Mathf.RoundToInt(gameManager.Gold * 1.1f);
enemiesSpawned = 0;
lastSpawnTime = Time.time;
}
// 5 Upon beating the last wave this runs the game won animation.
}
else {
gameManager.gameOver = true;
GameObject gameOverText = GameObject.FindGameObjectWithTag("GameWon");
gameOverText.GetComponent<Animator>().SetBool("gameOver", true);
}
}
}
Second Class
using UnityEngine;
using System.Collections;
public class MoveEnemy : MonoBehaviour
{
[System.NonSerialized]
public GameObject[] waypoints;
private int currentWaypoint = 0;
private float lastWaypointSwitchTime;
public float speed = 1.0f;
// Use this for initialization
void Start()
{
lastWaypointSwitchTime = Time.time;
}
// Update is called once per frame
void Update()
{
// 1
Vector3 startPosition = waypoints[currentWaypoint].transform.position;
Vector3 endPosition = waypoints[currentWaypoint + 1].transform.position;
// 2
float pathLength = Vector3.Distance(startPosition, endPosition);
float totalTimeForPath = pathLength / speed;
float currentTimeOnPath = Time.time - lastWaypointSwitchTime;
gameObject.transform.position = Vector3.Lerp(startPosition, endPosition, currentTimeOnPath / totalTimeForPath);
// 3
if (gameObject.transform.position.Equals(endPosition))
{
if (currentWaypoint < waypoints.Length - 2)
{
// 3.a
currentWaypoint++;
lastWaypointSwitchTime = Time.time;
RotateIntoMoveDirection();
}
else {
// 3.b
Destroy(gameObject);
AudioSource audioSource = gameObject.GetComponent<AudioSource>();
AudioSource.PlayClipAtPoint(audioSource.clip, transform.position);
//<< deduct health
GameManagerBehavior gameManager =
GameObject.Find("GameManager").GetComponent<GameManagerBehavior>();
gameManager.Health -= 1;
//>>
}
}
}
public void JiggleWaypoints()
{
for (int i = 1; i < waypoints.Length; i++)
{
waypoints[i].transform.position = new Vector3(waypoints[i].transform.position.x + Random.Range(-3, 3), waypoints[i].transform.position.y + Random.Range(-3, 3), 0);
}
}
private void RotateIntoMoveDirection()
{
//1 It calculates the bug’s current movement direction by subtracting the current waypoint’s position from that of the next waypoint.
Vector3 newStartPosition = waypoints[currentWaypoint].transform.position;
Vector3 newEndPosition = waypoints[currentWaypoint + 1].transform.position;
Vector3 newDirection = (newEndPosition - newStartPosition);
//2 It uses Mathf.Atan2 to determine the angle toward which newDirection points, in radians, assuming zero points to the right.
// Multiplying the result by 180 / Mathf.PI converts the angle to degrees.
float x = newDirection.x;
float y = newDirection.y;
float rotationAngle = Mathf.Atan2(y, x) * 180 / Mathf.PI;
//3 Finally, it retrieves the child named Sprite and rotates it rotationAngle degrees along the z-axis.
// Note that you rotate the child instead of the parent so the health bar — you’ll add it soon — remains horizontal.
GameObject sprite = (GameObject)
gameObject.transform.FindChild("Sprite").gameObject;
sprite.transform.rotation =
Quaternion.AngleAxis(rotationAngle, Vector3.forward);
}
public float distanceToGoal()
{
float distance = 0;
distance += Vector3.Distance(
gameObject.transform.position,
waypoints[currentWaypoint + 1].transform.position);
for (int i = currentWaypoint + 1; i < waypoints.Length - 1; i++)
{
Vector3 startPosition = waypoints[i].transform.position;
Vector3 endPosition = waypoints[i + 1].transform.position;
distance += Vector3.Distance(startPosition, endPosition);
}
return distance;
}
}
Code is working 100% without errors, BUT....
After each spawn all objects get the same waypoint array. This can be seen on the screen as all objects jump to new waypoint in line together each time new object is spawned. I want the object which is already spawn to live life with it's own array of only once created waypoints.
You need to create a new array of waypoints each time you create one from the prefabricated object. You don't show your Instantiate method but I'm guessing that it has a line like this:
this.waypoints = prefab.waypoints;
This will mean that all object you create will share the same list of waypoints (as you've discovered).
What you need is something like this - assuming that the waypoints have X, Y, and Z properties):
this.waypoints = new GameObject[5];
for (int i = 0; i++ ; i < 5)
{
this.waypoints[i].X = prefab.waypoints[i].X;
this.waypoints[i].Y = prefab.waypoints[i].Y;
this.waypoints[i].Z = prefab.waypoints[i].Z;
}
(If you want your points to be a variable length you might want to consider using a list).
This means that each object has a list of unique points even if they start with the same values you can change each independently.
Based on ChrisFs' and Joe Blows' answers, do something like this in your MoveEnemy script:
private Vector3[] myWay;
public void JiggleWaypoints(GameObject[] waypoints)
{
myWay = new Vector3[waypoints.Length];
for(int i = 1; i < waypoints.Length; i++)
{
myWay[i] = new Vector3(waypoints[i].transform.position.x + Random.Range(-3, 4), waypoints[i].transform.position.y + Random.Range(-3, 4), 0);
}
}
myWay replaces the GameObject[].
In your SpawnEnemy script you do this:
GameObject e = (GameObject)Instantiate(enemyPrefab);
e.GetComponent<MoveEnemy>().JiggleWaypoints(waypoints);

Intergrating life of player in each level in unity

In my game there are various levels
I have made those level in separate scenes
Every Scene has a player at the starting point and when it crosses the exit point the next level (next scene) is loaded but the health and life are reset as starting point in the game and not remain what the player currently has when he exited the level
Exit level Script:-
using UnityEngine;
using System.Collections;
public class ExitLevel : MonoBehaviour {
public string scene;
private Player player;
// Use this for initialization
void Start () {
player = GameObject.Find ("Player").GetComponent<Player> ();
}
// Update is called once per frame
void Update () {
}
void OnTriggerEnter2D(Collider2D target){
if (target.gameObject.tag == "Player") {
if (player.ArtifactCount == 1) {
player.ArtifactCount = 0;
Destroy (target.gameObject);
Application.LoadLevel (scene);
}
}
}
}
LifeMeter Script:-
using UnityEngine;
using System.Collections;
public class LifeMeter : MonoBehaviour {
public float Life = 100;
public float maxLife = 100;
public float LifeBurnRate = 1f;
public Texture2D bgTexture;
public Texture2D LifeBarTexture;
public Texture2D HeartTexture;
public int iconWidth = 32;
public Vector2 LifeOffset = new Vector2(255, 10);
public int HeartCount = 3;
public Vector2 HeartOffset = new Vector2(455, 6.5f);
public int HeartDistance = 0;
public int HeartDistanceAddup = 40;
public int HeartDisplayWidth = 40;
public int HeartDisplayHeight = 40;
private Player player;
private ExitLevel exitLevel;
// Use this for initialization
void Start () {
player = GameObject.FindObjectOfType<Player> ();
}
public void OnGUI(){
var percent = Mathf.Clamp01 (Life / maxLife);
if (!player)
percent = 0;
if(Life == 0 && HeartCount !=0 ){
HeartCount = HeartCount - 1;
Life = 100;
}
HeartDistance = 0;
DrawMeter (LifeOffset.x, LifeOffset.y, LifeBarTexture, bgTexture, percent);
for (int i = 0; HeartCount > i; i++) {
HeartDistance = HeartDistance + HeartDistanceAddup;
GUI.DrawTexture (new Rect (HeartOffset.x + HeartDistance, HeartOffset.y, HeartDisplayWidth, HeartDisplayHeight), HeartTexture);
}
}
void DrawMeter(float x, float y, Texture2D texture, Texture2D background, float percent){
var bgW = background.width;
var bgH = background.height;
GUI.DrawTexture (new Rect (x, y, bgW, bgH), background);
var nW = ((bgW - iconWidth) * percent) + iconWidth;
GUI.BeginGroup (new Rect (x, y, nW, bgH));
GUI.DrawTexture (new Rect (0, 0, bgW, bgH), texture);
GUI.EndGroup ();
}
// Update is called once per frame
void Update () {
}
public void life(){
Life = Life - LifeBurnRate;
if (HeartCount == 0) {
{ Explode script = player.GetComponent<Explode> ();
script.OnExplode ();
}
}
}
}
you can use PlayerPrefs (Stores and accesses player preferences between game sessions)for save current status of Player.
Reffer this link http://docs.unity3d.com/ScriptReference/PlayerPrefs.html
There are two ways to proceed in the above case:
You can add DontDestroyOnload(this); to your player object. This
will not destroy that game object when the new level loads. And On
Every start of level you can spawn him your level start point. This
way your player's stats will remain consistent throughout the game.
You can use a static class to get the players health and other
required stats. Save the players health in the static class while
exiting the level and apply the values to the next levels player
object when the next level loads.

Categories