Setting a bool active from a different script - c#

I need to active icons in my UI. Since I make use of a pick up script I want to activate the object once I picked it up. I made a bool in my main script but I can't turn the bool on or off in my pick up script.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NadePickUp : MonoBehaviour
{
public GameObject PUEffect;
private void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("Player"))
{
PickUp(other);
// activate = true;
}
}
void PickUp(Collider2D player)
{
Shooting stats = player.GetComponent<Shooting>();
stats.shotType = "grenade";
GameObject effect = Instantiate(PUEffect, transform.position, Quaternion.identity);
PlayerStats activate = player.GetComponent<PlayerStats>();
activate = true;
Destroy(gameObject);
}
}

There are many answers to something like this on Unity Answers, here for example is one that answers your question.
If your PlayerStats is a class, you're treating it as a boolean. You're getting a reference to the script component and then immediately setting that value to true.
Assuming there's a public boolean activate on your PlayerStats class you could do something like this:
PlayerStats playerStats = player.GetComponent<PlayerStats>();
playerStats.activate = true;
This is based on pure assumption of your PlayerStats class.

Related

How can i un do a destroy() function in C#

I need to destroy an object, in my case is "Player2" witch is in the same scene as "Player1" and then after Player1 position.x is past "baraj".position.x reapear. Basically how can i make a temporarly destroy method.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class switchCameras2 : MonoBehaviour
{
public GameObject baraj;
public GameObject CameraOne;
public GameObject CameraTwo;
public GameObject Player1;
public GameObject Player2;
public void Start()
{
CameraOne.SetActive(true);
CameraTwo.SetActive(false);
}
void Update()
{
if (GameObject.Find("Player1").transform.position.x > GameObject.Find("baraj").transform.position.x)
{
CameraTwo.SetActive(true);
CameraOne.SetActive(false);
}
if (GameObject.Find("Player1").transform.position.x < GameObject.Find("baraj").transform.position.x)
{
Destroy(Player2);
}
if (GameObject.Find("Player1").transform.position.x > GameObject.Find("baraj").transform.position.x)
{
Destroy(Player1);
}
}
}
If you want to Destroy it then you should make a new one with Instantiate method. If you don't want to Destroy it, one alternative is to deactivate it with SetActive like this Player1.SetActive(false); and then enable it like this Player1.SetActive(true);
Try creating a new GameObject variable called "U". And then right before destroying or in the start do U = player2.gameObject;
Now let's say you destroyed it and want to spawn. To do that we do
player2 = U.gameObject;
Instantiate(player2);
That will spawn player 2.
But as mentioned in the other answer .SetActive(false); would make things easier. Anyway if you still want to use destroy then that is how to do that. Good luck

Unity: Even when the "player" game object gets destroyed, the text doesn't appear

I've been using Unity to create a simple 2D game but the problem is that even when the game object "player" gets destroyed, the gameobject "isDead" (text) doesn't appear.
This is my script.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class youDied_Text : MonoBehaviour
{
private Transform player;
private Text isDead;
// public static bool isDead;
// Start is called before the first frame update
private void Start() {
isDead = GetComponent<Text>();
}
void checkForDeath()
{
if (player==false)
{
isDead.gameObject.SetActive(true);
}
else
{
isDead.gameObject.SetActive(false);
}
}
// Update is called once per frame
void Update()
{
player = GameObject.FindWithTag("Player").transform;
checkForDeath();
}
}
This script is attached in the text which I need to display in UI element.
As was noted currently you would get a NullReferenceException which is definitely not what you want.
There is absolutely no need / redundancy going through Transform at all actually. Simply store the GameObject reference instead
You are currently setting the object to inactive which has the Text attached ... which is the same object your component is attached to as well!
=> As soon as you end up in the second case once you set it to inactive => from now on Update is never called anymore!
In general as it sounds like this should only happen once anyway I would use a more event driven approach and have a component on your player like e.g.
public class Player : MonoBehaviour
{
public UnityEvent onDied;
private void OnDestroy ()
{
onDied.Invoke();
}
}
And then simply attach a listener/callback to that event once without poll checking states. You can do this either via the Inspector directly (just like in e.g. Button.onClick) or via code like e.g.
public class youDied_Text : MonoBehaviour
{
// Already reference things via the Inspector if possible!
[SerializeField] private GameObject player;
[SerializeField] private Text isDead;
private void Awake()
{
if(!isDead) isDead = GetComponent<Text>();
isDead.gameObject.SetActive(false);
// If you want to rather set it via the Inspector remove all the rest here
//if(!player) player = GameObject.FindWithTag("Player"). GetComponent<Player>();
// or even simpler
if(!player) player = FindObjectOfType<Player>();
player.onDied.AddListener(OnPlayerDied);
}
// If you want to rather set it via the Inspector make this public
private void OnPlayerDied()
{
isDead.gameObject.SetActive(true);
}
}

How can I respawn an object in Unity?

I am working on a 3d basketball game in unity.
It has a score and a timer. After a certain time my scene loads and starts from the beginning. Every time I throw the ball, I have to spawn it.
It has a spawn button and a shoot button. But I don't want to use the spawn button. So I want to spawn the ball automatically.
How should I do it? I am giving my spawn button code and throw button code bellow.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpawnButton: MonoBehaviour
{
public GameObject ball;
public GameObject BallPosition;
public void Spawn()
{
ball.transform.position = BallPosition.transform.position;
var ballPosition = ball.transform.position;
ball.GetComponent<Rigidbody>().useGravity = false;
ball.GetComponent<Rigidbody>().velocity = Vector3.zero;
ball.transform.position = ballPosition;
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ThrowButton: MonoBehaviour
{
static Animator anim;
public GameObject ball;
public float ballThrowingForce = 5f;
internal bool holdingBall;
void Start()
{
anim = GetComponent<Animator>();
ball.GetComponent<Rigidbody>().useGravity = false;
}
public void Throw()
{
anim.SetTrigger("isThrowing");
StartCoroutine(Test());
}
IEnumerator Test()
{
yield return new WaitForSeconds(1.5f);
ball.GetComponent<Rigidbody>().useGravity = true;
//ball.GetComponent<Rigidbody>().AddForce(transform.up * ballThrowingForce);
ball.GetComponent<Rigidbody>().AddForce(0, 380.0f, ballThrowingForce);
}
}
To spawn a ball you should create a prefab and instantiate it. Example:
private class Spawner : MonoBehaviour
{
public GameObject prefab;
public GameObject Spawn() => Instantiate(prefab);
}
So that your throw code should spawn a ball and if you want destroy an older one.
The above answer by Iv Misticos mentioned the use of Instantiate which is a great way to spawn a new ball.
before you spawn a new ball, you need to specify when it must spawn.
Either you can
use a Invoke("SpawnNewBallMethod",3) //after this piece of code is executed, it waits for 3 seconds and executes the method you mention in it which can have the code to instantiate.
Or After the first ball's work is done, you can destroy it(Destroy(ball)) or set active to false - Then check the state (if it exists(null check?) or gameObject.active==true) and accordingly instantiate a new ball (if it is setactive(false) don't forget to destroy it later).
Although gameObject.active is obsolete, it will serve the purpose without complicating things.
In my opinion, Invoke is better than a IEnumerator here as Invoke will not stop the execution flow and continue with the other things while the timer is running.

Unity GameOver Screen

I am just trying to activate game over screen when the Player's activate is 'false'. There is no animation, just the
There are 3 objects that need to be active and i added the script to those 3 objects but the screen does not appear.
How can i fix?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameOverManager : MonoBehaviour
{
public GameObject _player;
void Start()
{
_player = GameObject.FindGameObjectWithTag("Player");
}
void Update()
{
if (_player.activeInHierarchy == false)
{
gameObject.SetActive(true);
}
else
{
gameObject.SetActive(false);
}
}
}
My suspicion is the following. Whenever a Gameobject is not enabled, its code does not run. Test this by adding a Debug.Log("test") message.
If no message appears you can be certain that this check is never evaluated. To work around this simply add a script that is bound to an active gameObject. Creat a new empty gameobject in the scene. And add something like this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameOverManager : MonoBehaviour
{
public GameObject _player;
public GameObject _endscreen;
void Update()
{
if (_player.activeInHierarchy == false)
{
_endscreen.SetActive(true);
}
else
{
_endscreen.SetActive(false);
}
}
}
Assign the Variables in the Inspector by dragging the object to the empty fields. Never use GameObject.Find Methods.
If you need any further help tell me :)
What you're currently doing is to find a single GameObject and checking whether that is active or not.
It would make more sense, and be more optimized, if each player object adds himself to a list of all players when he spawns. You can then loop over that list instead to check all players.
An even better way would be if you only call that "GameOver" check after a player has died. So when you call whichever method kills him.
Based on Franz Answer, I did some modification in the code. You won't need any if else statement if you use a shortcut.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameOverManager : MonoBehaviour
{
public GameObject _player;
public GameObject _endscreen;
void Update()
{
_endscreen.SetActive(!_player.activeInHierarchy);
}
}

Editing variables with GetComponent C#

I am trying to get a conveyor belt to reverse its direction when the player presses a button.
Here's the code for the conveyor belt
using UnityEngine;
using System.Collections;
public class Conveyor : MonoBehaviour {
public float speed = 1.0f;
void OnTriggerStay(Collider col)
{
col.transform.position += transform.forward * speed * Time.deltaTime;
}
}
And the code for the button
public class PushButton : MonoBehaviour
{
public GameObject Button;
private Conveyor conveyor;
void Awake ()
{
conveyor = GetComponent<Conveyor>();
}
void OnTriggerStay(Collider entity)
{
if (entity.tag == "Player")
{
if (Input.GetKeyUp(KeyCode.E))
{
conveyor.speed = conveyor.speed * -1;
}
}
}
}
I'm getting an error saying "Object Reference not set to the instance of an object PushButton.OnTriggerStay (Unity Engine.Collider entity) (at Assests/PushButton.cs21)
I'm still not very familiar with using getComponent so I'm not sure how to fix this. Any help would be appreciated.
GetComponent will need a reference to an initialized object and a component or class that object has assigned. For what you are wanting, you will want to find a game object in the scene. Because you are already specifying that your GameObject has a Conveyor class assigned to it, find your GameObject and then specify the Conveyor component.
void Awake ()
{
conveyor = GameObject.FindWithTag("Conveyor").GetComponent<Conveyor>();
}
This should do the trick pending you have tagged your Conveyor game object with a 'Conveyor' tag.
However, there is an even easier way to quickly "grab" something like this. Be careful though!
void Awake()
{
conveyor = Object.FindObjectOfType<Conveyor>();
// ONLY DO THAT IF THERE IS ONLY >>ONE<< OF THE THING!
}
Here's a little essay on that. http://answers.unity3d.com/answers/46285/view.html
You often do that for example to find "boss" objects .. scene managers and the like.
Don't forget though, you can always just use a public variable, and drag inteh Inspector - that's always a sound idea for beginners working with Unity.

Categories

Resources