I want to call another script method (stars) when object is destroyed, Below is my code so far I had done, I am getting error (Null reference) at line "tim.stars", Any suggestions what I had done wrong? Here is my code.
using UnityEngine;
using System.Collections;
public class clear : MonoBehaviour {
// Use this for initialization
void Start () {
GetComponent<ParticleSystem> ().emissionRate = 0;
}
// Update is called once per frame
void Update () {
if (Input.GetMouseButtonDown (1)) {
GetComponent<ParticleSystem> ().Emit (10);
}
}
void OnParticleCollision(GameObject obj)
{
if (obj.gameObject.tag == "fire1") {
Destroy (obj, 5.0f);
TimingForIndust2 tim = GetComponent<TimingForIndust2> ();
tim.stars ();
}
StartCoroutine (TestCoroutine());
}
IEnumerator TestCoroutine(){
yield return new WaitForSeconds(8);
Application.LoadLevel (25);
}
}
here is my 2nd script TimingForIndust2
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using MadLevelManager;
public class TimingForIndust2 : MonoBehaviour {
public Transform TimingBar;
public Transform TextIndicator;
public Transform TextRemaining;
[SerializeField] private float currentAmount;
[SerializeField] private float speed;
// method to reduce the time continously
void Update () {
if (currentAmount > 0) {
currentAmount -= speed*Time.deltaTime;
TextIndicator.GetComponent<Text>().text=((int)currentAmount).ToString()+"s";
TextRemaining.gameObject.SetActive(true);
} else {
TextRemaining.gameObject.SetActive(false);
TextIndicator.GetComponent<Text>().text="TimeUP";
Application.LoadLevel (62);
}
TimingBar.GetComponent<Image> ().fillAmount = currentAmount / 60;
}
public void stars()
{
if (currentAmount > 45.0f) {
MadLevelProfile.SetLevelBoolean (MadLevel.currentLevelName, "star_1", true);
MadLevelProfile.SetLevelBoolean (MadLevel.currentLevelName, "star_2", true);
MadLevelProfile.SetCompleted (MadLevel.currentLevelName, true);
} else if (currentAmount > 20.0f && currentAmount < 29.0f) {
MadLevelProfile.SetLevelBoolean (MadLevel.currentLevelName, "star_1", true);
MadLevelProfile.SetLevelBoolean (MadLevel.currentLevelName, "star_2", true);
MadLevelProfile.SetCompleted (MadLevel.currentLevelName, true);
} else if (currentAmount > 2.0f && currentAmount < 19.0f) {
MadLevelProfile.SetLevelBoolean (MadLevel.currentLevelName, "star_1", true);
}
}
}
By reading your comment, you have to Find the Timer with GameObject.Find then get the component from it. You can't be doing this each time there is a collision. You have to cache it in the Start() function once then re-use it.
I also cached ParticleSystem in the new code. Also, instead of comparing tag directly with obj.gameObject.tag == "fire1", use the CompareTag function to compare tags.
This should fix your problem. Now, it's your job to cache the Text component that is attached to the TextIndicator script which you are calling in the updat function from the TimingForIndust2 script.
using UnityEngine;
using System.Collections;
public class clear : MonoBehaviour {
TimingForIndust2 timingForIndust2;
ParticleSystem particles;
// Use this for initialization
void Start () {
particles = GetComponent<ParticleSystem> ();
particles.emissionRate = 0;
GameObject tempObj = GameObject.Find("Timer");
timingForIndust2 = tempObj.GetComponent<TimingForIndust2>();
}
// Update is called once per frame
void Update () {
if (Input.GetMouseButtonDown (1)) {
particles.Emit (10);
}
}
void OnParticleCollision(GameObject obj)
{
if (obj.CompareTag("fire1")) {
Destroy (obj, 5.0f);
timingForIndust2.stars ();
}
StartCoroutine (TestCoroutine());
}
IEnumerator TestCoroutine(){
yield return new WaitForSeconds(8);
Application.LoadLevel (25);
}
}
Related
Assets\GameControl2D.cs(25,10): error CS0106: The modifier 'public' is not valid for this item
This error is happening why? Please anyone let me help it to figure out.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameControl2D : MonoBehaviour
{
public static GameControl2D instance;
public GameObject gameOverText;
public bool gameOver = false;
void Awake ()
{
if (instance == null)
{
instance = this;
}
else if (instance != this)
{
Destroy (gameObject);
}
}
void Update ()
{
public void BirdDied()
{
GameOverText.SetActive (true);
gameOver = true;
}
}
}
You have a nested/local method BirdDied, that can't have access modifiers. It's accessible only from the method body of Update anyway. So this compiles:
void Update ()
{
void BirdDied()
{
GameOverText.SetActive (true);
gameOver = true;
}
}
But since you don't use it in your code, i doubt that it's what you want.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Bird2D : MonoBehaviour
{
public float upForce = 200f;
private bool isDead = false;
private Rigidbody2D rb2d;
private Animator anim;
// Start is called before the first frame update
void Start()
{
rb2d = GetComponent<Rigidbody2D>();
anim = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
if (isDead == false)
{
if (Input.GetMouseButtonDown(0))
{
rb2d.velocity = Vector2.zero;
rb2d.AddForce(new Vector2(0, upForce));
anim.SetTrigger("Flap");
}
}
}
void OnCollisionEnter2D()
{
isDead = true;
anim.SetTrigger("Die");
GameControl2D.Instance.BirdDied();
}
}
This is the Bird2D.cs file i already remove public from birdDied method but the error is same
I just started using Unity, to make a small game called flappy duck.
I wanne have an online leaderboard so everyone can beat each others highscore.
I stumbled on this error Assets\scripts\PlayerController.cs(65,9): error CS0103: The name 'playfabManager' does not exist in the current context
I cand cant find anything wrong. BTW i am using a tutorial
from CoCo Code https://www.youtube.com/watch?v=e2RXDso6fWU&t=266s he uses playfab i am trying to
get this working in my own game.
THIS IS THE SCRIPT THAT MAKES THE TEXT DISPLAY THE HIGHSCORE
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class HighSScore : MonoBehaviour
{
public Text HighScore;
// Start is called before the first frame update
void Start()
{
HighScore.text = PlayerPrefs.GetInt("highscore").ToString();
}
}
THIS IS THE PLAYFAB MANAGER
using System.Collections.Generic;
using UnityEngine;
using PlayFab;
using PlayFab.ClientModels;
public class PlayFabManager : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
Login();
}
void Login()
{
var request = new LoginWithCustomIDRequest
{
CustomId = SystemInfo.deviceUniqueIdentifier,
CreateAccount = true
};
PlayFabClientAPI.LoginWithCustomID(request, OnSuccess, OnError);
}
void OnSuccess(LoginResult result)
{
Debug.Log("Successful login/account create!");
}
void OnError(PlayFabError error)
{
Debug.Log("Error while logging in/creating account!");
Debug.Log(error.GenerateErrorReport());
}
public void SendLeaderboard(int score)
{
var request = new UpdatePlayerStatisticsRequest
{
Statistics = new List<StatisticUpdate>
{
new StatisticUpdate
{
StatisticName = "score",
Value = score
}
}
};
PlayFabClientAPI.UpdatePlayerStatistics(request, OnLeaderboardUpdate, OnError);
}
void OnLeaderboardUpdate(UpdatePlayerStatisticsResult result)
{
Debug.Log("succsessfull send leaderboard");
}
}`
LAST IS THIS THE PLAYERCONTROLLER
were the error is based on line 65
I am trying to send the highscore to the leaderboard in playfab.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class PlayerController : MonoBehaviour
{
[SerializeField] TextMeshProUGUI scoreText;
Rigidbody2D bird;
int score = 0;
bool dead = false;
int highscore = 0;
// Start is called before the first frame update
void Start()
{
bird = transform.GetComponent<Rigidbody2D>();
}
// Update is called once per frame
public void update ()
{
if (Input.GetKeyDown("space") && !dead)
{
bird.velocity = new Vector2(0, 6f);
}
if (Input.GetKeyDown("r"))
{
SceneManager.LoadSceneAsync(SceneManager.GetActiveScene().buildIndex);
}
if (score > highscore)
{
highscore = score;
SendLeaderboard();
PlayerPrefs.SetInt("highscore", score);
}
}
void OnCollisionEnter2D()
{
dead = true;
score = 0;
scoreText.text = "0";
}
void OnTriggerExit2D(Collider2D col)
{
if (col.gameObject.tag == "PointTrigger")
{
score++;
scoreText.text = score.ToString();
}
}
void OnTriggerExit(Collider col)
{
if (col.gameObject.tag == "PointTrigger")
{
score++;
scoreText.text = score.ToString();
}
}
public void SendLeaderboard()
{
playfabManager.SendLeaderboard(highscore);
}
}
I hope someone can help me.
Most probably in PlayerController you wanted to have a
[SerializeField] private PlayFabManager playfabManager;
and either reference it via the Inspector or at runtime via e.g.
private void Awake ()
{
// Try and get the component if it is attached to the same object as this
if(! playfabManager) playfabManager = GetComponent<PlayFabManager>();
// Or try and find it anywhere in the scene
if(! playfabManager) playfabManager = FindObjectOfType<PlayFabManager>();
// Or simply create and attach it to the same object as this one
if(! playfabManager) playfabManager = gameObject.AddComponent<PlayFabManager>();
}
Or - and in my eyes this would be the more correct solution - the PlayerFabManager should not be a MonoBehaviour at all but rather simply do
public class PlayFabManager
{
public void Login()
{
...
}
...
}
And in PlayerController you'd rather do
private readonly PlayFabManager playfabManager = new PlayFabManager();
private void Start ()
{
playfabManager.Login();
}
I am a newbie to Unity and I am trying to build a little shooter 2d game in C#. I am now stuck and confess that I am a little lost not knowing what the best approach is, but the problem is that my hero shoots at the enemies and they die but how do I get to the next level after the enemies are all dead? If I make a dead counter, what script do I put in? In the enemy script? Or do I make a new script but associate it with what? I also need the game to end if the hero fires his six bullets (already have a counter that makes the hero not shoot anymore after six shoots) and there are still enemies left ...
Does anyone give me some tips? Thanks!
Enemy script:
using System.Collections.Generic;
using UnityEngine;
public class BadguyScript : MonoBehaviour
{
public int maxHealth;
public int curHealth;
private Animator myAnimator;
private bool isDead;
[SerializeField]
private float DespawnTime = 2.5f;
[SerializeField]
private string DeathAnimHash = "isDead";
void Start()
{
myAnimator = GetComponent<Animator>();
myAnimator.enabled =true;
myAnimator.SetBool (DeathAnimHash ,isDead);
maxHealth = 1;
curHealth = maxHealth;
}
void Update()
{
if (curHealth < 1)
{
isDead = true;
myAnimator.SetBool (DeathAnimHash ,isDead);
Destroy(gameObject,DespawnTime);
}
}
void OnTriggerEnter2D(Collider2D col)
{
if (isDead)
return;
if (col.tag == "bullet")
{
curHealth -= 1;
Destroy(col.gameObject);
}
}
}
Count Bullets Script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class GameFlow : MonoBehaviour
{
public static float remainingShots = 6;
public Transform shot1;
public Transform shot2;
public Transform shot3;
public Transform shot4;
public Transform shot5;
public Transform shot6;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (remainingShots > 0)
{
shot1.GetComponent<Image> ().enabled = true;
}
else
{
shot1.GetComponent<Image> ().enabled = false;
}
if (remainingShots > 1)
{
shot2.GetComponent<Image> ().enabled = true;
}
else
{
shot2.GetComponent<Image> ().enabled = false;
}
if (remainingShots > 2)
{
shot3.GetComponent<Image> ().enabled = true;
}
else
{
shot3.GetComponent<Image> ().enabled = false;
}
if (remainingShots > 3)
{
shot4.GetComponent<Image> ().enabled = true;
}
else
{
shot4.GetComponent<Image> ().enabled = false;
}
if (remainingShots > 4)
{
shot5.GetComponent<Image> ().enabled = true;
}
else
{
shot5.GetComponent<Image> ().enabled = false;
}
if (remainingShots > 5)
{
shot6.GetComponent<Image> ().enabled = true;
}
else
{
shot6.GetComponent<Image> ().enabled = false;
}
if(Input.GetButtonDown("Fire1"))
{
remainingShots -= 1;
}
}
}
To switch to another scene after your conditions do the following:
1. Add the OtherScenes to your game by doing this:
File -> Build Settings -> Add Open Scenes
2. Do something like this in your code:
Enemy Script.cs
using UnityEngine.SceneManagement; // Contains scene management functions
public GameObject[] enemies;
void Update()
{
enemies = GameObject.FindGameObjectsWithTag("Enemy"); // Checks if enemies are available with tag "Enemy". Note that you should set this to your enemies in the inspector.
if (enemies.length == 0)
{
SceneManager.LoadScene("OtherSceneName"); // Load the scene with name "OtherSceneName"
}
}
Bullet Script.cs
using UnityEngine.SceneManagement;
void Update()
{
if (remainingShots == -1)
{
SceneManager.LoadScene("OtherSceneName");
}
}
use an empty gameobject and attach this line of code in update method .
if (enemies.length == 0)
{
SceneManager.LoadScene("OtherSceneName"); // Load the scene with name "OtherSceneName"
}
As you were using the enemy script and when all the enemies dies then there is no gameobject which hold the script.
So I put the object in the scene and then I made it "invisible" (deactivate if you will) from the inspector (the checkmark box next to the object's name) and after waiting 8 seconds it doesn't become visible. I am using Unity 2d and C#.
I have the game start paused for three seconds then plays after that which works. The first script is that one. The item is supposed to reappear after 8 seconds so after the game resumes, which doesn't work.
//delay before level starts script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class countDown : MonoBehaviour
{
public GameObject CountDown;
private void Start()
{
StartCoroutine("StartDelay");
}
void Update()
{
}
IEnumerator StartDelay()
{
Time.timeScale = 0;
float pauseTime = Time.realtimeSinceStartup + 3f;
while (Time.realtimeSinceStartup < pauseTime)
yield return 0;
CountDown.gameObject.SetActive(false);
Time.timeScale = 1;
}
{
//script for the flower to appear
IEnumerator Start()
{
print(Time.time);
yield return new WaitForSeconds(8);
print(Time.time);
flowerInScene.gameObject.SetActive(true);
}
[SerializeField] Transform flowerInScene;
}
I still don't really get your two methods called Start
You can simply call a StartCoroutine at the end of another Coroutine so you can chain them together (though there are surely better ways to do what you want in general):
using System.Collections;
using UnityEngine;
public class CountDown : MonoBehaviour
{
public GameObject CountDownObject;
public GameObject flowerObject;
private void Start()
{
StartCoroutine(Delay());
}
private IEnumerator Delay()
{
yield return new WaitForSeconds(3);
HideCountdown();
StartCoroutine(FlowerDelay());
}
private void HideCountdown()
{
CountDownObject.SetActive(false);
}
private IEnumerator FlowerDelay()
{
yield return new WaitForSeconds(8);
ShowFlower();
}
private void ShowFlower()
{
flowerObject.SetActive(true);
}
}
I personaly don't like Coroutines .. they are not so easy to debug sometimes. I would prefer doing something like this with simple timers (though in the first moment it does look worse). Advantage is I can now directly watch the timer count down in the inspector:
using UnityEngine;
public class SimpleCountDown : MonoBehaviour
{
[Header("The Objects")]
public GameObject CountDownObject;
public GameObject FlowerObject;
[Header("Settings")]
// Here you can adjust the delay times
public float StartOffset = 3;
public float FlowerOffset = 8;
[Header("Debug")]
public float startTimer;
public float flowerTimer;
public bool isStartDelay;
public bool isFlowerDelay;
private void Start()
{
startTimer = StartOffset;
flowerTimer = FlowerOffset;
isStartDelay = true;
}
private void Update()
{
if (!isStartDelay && !isFlowerDelay) return;
if (isStartDelay)
{
startTimer -= Time.deltaTime;
if (startTimer <= 0)
{
HideCountdown();
isStartDelay = false;
isFlowerDelay = true;
}
}
if (isFlowerDelay)
{
flowerTimer -= Time.deltaTime;
if (flowerTimer <= 0)
{
ShowFlower();
isFlowerDelay = false;
this.enabled = false;
}
}
}
private void HideCountdown()
{
CountDownObject.SetActive(false);
}
private void ShowFlower()
{
FlowerObject.SetActive(true);
}
}
im having a problem from my enemyDamage script in unity5 when i play it and stick to the enemy i died instantly even the enemy damage is 10 and my health was 100
well this is my first time to make this things on unity hope you helps me :(
heres my code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class enemydmg : MonoBehaviour {
public float damage;
public float damagerate;
public float pushbackforce;
float nextdamage;
bool playerInRange = false;
GameObject theplayer;
playerHealth theplayerhealth;
// Use this for initialization
void Start () {
nextdamage = Time.time;
theplayer = GameObject.FindGameObjectWithTag ("Player");
theplayerhealth = theplayer.GetComponent<playerHealth> ();
}
// Update is called once per frame
void Update () {
if (playerInRange)
Attack ();
}
void OnTriggerEnter (Collider other)
{
if (other.tag == "Player")
{
playerInRange = true;
}
}
void OnTriggerExit (Collider other)
{
if (other.tag == "Player")
{
playerInRange = false;
}
}
void Attack()
{
if (nextdamage <= Time.time)
{
theplayerhealth.addDamage(damage);
nextdamage = Time.time + damagerate;
pushback (theplayer.transform);
}
}
void pushback(Transform pushObject)
{
Vector3 pushDirection = new Vector3 (0, (pushObject.position.y - transform.position.y), 0).normalized;
pushDirection *= pushbackforce;
Rigidbody pushedRB = pushObject.GetComponent<Rigidbody> ();
pushedRB.velocity = Vector3.zero;
pushedRB.AddForce (pushDirection, ForceMode.Impulse);
}
}
and this was my playerhealth
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class playerHealth : MonoBehaviour {
public float fullhealth;
float currentHealth;
// Use this for initialization
void Start () {
currentHealth = fullhealth;
}
// Update is called once per frame
void Update () {
}
public void addDamage(float damage)
{
currentHealth -= damage;
if (currentHealth <= 0) {
makeDead ();
}
}
public void makeDead()
{
Destroy (gameObject);
}
}
theplayerhealth = theplayer.GetComponent<playerHealth> ();
I think this line of code fails you because the player is a GameObject. theplayerhealth is or should already be initialized in your other script. I think you could approach polymorphism in a better way.
public class enemydmg : playerHealth{
}
This will allow you to directly inherit everything you need from the playerHealth script without having to grab extra components. You can also use this technique for may other scripts in the future.
Another approach that you could use is calling your class directly:
playerHealth.addDamage(damage);
From now on when you name your scripts use capitalization. PlayerHealth, EnemyDamage, etc... That's just a pro-tip to make your code look a bit cleaner when you're doing things like this. (Optional)