{Unity} effect other objects after collision - c#

I am creating a game with unity and I have a question.
I have 5 game objects + player. And they always rotate when the game has started. I want that if the player collides with the object that is tagged snowflake, the other 4 objects pause the rotation.

Have a static event on your player script, when player collide invoke that event. On other scripts subscribe to that event.
For example in your PlayerScript should be something like
public class PlayerScript : MonoBehaviour {
public static UnityAction OnPlayerCollidedWithSnowFlakes;
private void OnCollisionEnter(Collision other) {
if (other.gameObject.tag.Equals("snowflake")) {
OnPlayerCollidedWithSnowFlakes?.Invoke();
}
}
}
And your RotatingObjectScript should be something like
public class RotatingObjectScript : MonoBehaviour {
private void Awake() {
PlayerScript.OnPlayerCollidedWithSnowFlakes += CollidedWithSnowflakeEventHandler;
}
private void OnDestroy() {
PlayerScript.OnPlayerCollidedWithSnowFlakes -= CollidedWithSnowflakeEventHandler;
}
private void CollidedWithSnowflakeEventHandler() {
.
.
// Stop rotating
.
.
}
}

Related

How can I bring a Player to ignore collision with another GameObject in code?

Im currently trying to code a health system for my game and I want my Player GameObject to ignore collision with the Health Potion GameObject if the Player has max health. My problem is that I cannot simply turn off the collision between the Player Layer and Health Potion Layer because I only want to ignore collision if the Player has Max Health. I tried doing it myself but it didn't work. Here's my code:
public class ExampleCodeUA : MonoBehaviour{
public int PlayerMaxHealth = 100, PlayerCurrentHealth;
public HealthBar healthBar;
private void Start()
{
PlayerCurrentHealth = PlayerMaxHealth;
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("HealthPotion"))
{
if (PlayerCurrentHealth == PlayerMaxHealth)
{
Physics2D.IgnoreLayerCollision(6, 7);
}
else if (PlayerCurrentHealth > 50)
{
GetHealth(PlayerMaxHealth - PlayerCurrentHealth);
}
else if (PlayerCurrentHealth <= 50)
{
GetHealth(50);
}
}
}
void GetHealth(int healing)
{
PlayerCurrentHealth += healing;
healthBar.SetHealth(PlayerCurrentHealth);
}
}
You don't want to modify your physics configuration at runtime. What you could do to avoid the collision... is to make it impossible, by having nothing to collide with. Both of your objects have a collider. What you could do is to disable all existing HealthPotion colliders by modifying their code. An implementation could be the following:
using System.Collections.Generics;
using UnityEngine;
public class HealthPotion : MonoBehaviour
{
private static List<HealthPotion> _existingPotions = new List<HealthPotion>();
public static void EnablePotionsCollider(bool value)
{
foreach (var potion in _existingPotions)
{
potion._collider.enabled = value;
}
}
private Collider _collider;
void Awake()
{
_collider = GetComponent<Collider>();
}
void OnEnable()
{
_existingPotions.Add(this);
}
void OnDisable()
{
_existingPotions.Remove(this);
}
}
Then you just have to call the method when you want to enable/disable by doing
HealthPotion.EnablePotionsCollider(value you want);

is there a way to find if an object in an array has been destroyed? [duplicate]

I'm creating a game and i want to show a panel when the player is dead
I've tried different approaches but none seems to do what I want
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class DeadOrAlive : MonoBehaviour
{
public GameObject Player;
public GameObject deadPanel;
void Update()
{
if (!GameObject.FindWithTag("Player"))
{
deadPanel.SetActive(true);
}
}
}
To check if a object has been destroyed, you should use MonoBehavior's OnDestroy like so:
// Attach this script to the player object
public class DeadOrAlive : MonoBehaviour
{
public GameObject deadPanel;
void OnDestroy()
{
deadPanel.SetActive(true);
}
}
You can also instead of destroying the player object, set it to active/inactive, but to check if the player is dead or alive this way, you will need a separate object which checks the active state:
//Attach this to a object which isn't a child of the player, maybe a dummy object called "PlayerMonitor" which is always active
public class DeadOrAlive : MonoBehaviour
{
public GameObject deadPanel;
void Update()
{
if (!GameObject.FindWithTag("Player"))
{
deadPanel.SetActive(true);
}
}
}
Haven't used unity in a while and forgot how weird it could get.
Thanks to #VincentBree this is how I did it
void Update()
{
if (!Player.activeSelf)
{
deadPanel.SetActive(true);
}
}

Error MissingReferenceException: The object of type 'GameObject' has been destroyed but you are still trying to access it

I have been making a 2D game in Unity. I'm trying to make a game over screen appear every time a ball touches the player. I also added advertisements to release it. I added Restart and Continue buttons. When you press continue, an ad shows and the game continues. When Restart is pressed, it resets the game and your score. Whenever I restart the game and then press continue, the ad is played, but the game does not continue.
Here is the collision script:
using UnityEngine;
public class hitDetect : MonoBehaviour
{
public GameObject menuContainer;
private void OnTriggerEnter2D(Collider2D other)
{
Debug.Log("HIT");
menuContainer.SetActive(true);
Time.timeScale = 0;
}
}
This is the script that restarts the game:
using UnityEngine;
using UnityEngine.SceneManagement;
public class RestartGame : MonoBehaviour
{
public void Restart()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
Time.timeScale = 1;
}
}
Here is the advertisement and continue script:
using UnityEngine;
using UnityEngine.Advertisements;
public class continueGame : MonoBehaviour, IUnityAdsListener
{
string placement = "rewardedVideo";
public GameObject menuContain;
private void Start()
{
Advertisement.AddListener(this);
Advertisement.Initialize("4006857", true);
}
public void Continue(string p)
{
Advertisement.Show(p);
}
public void OnUnityAdsReady(string placementId)
{
}
public void OnUnityAdsDidError(string message)
{
}
public void OnUnityAdsDidStart(string placementId)
{
}
public void OnUnityAdsDidFinish(string placementId, ShowResult showResult)
{
if(showResult == ShowResult.Finished)
{
menuContain.SetActive(false);
Time.timeScale = 1;
}
}
}
Once you call
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex)
a "new" scene is loaded and therefore anything currently existing is destroyed.
In continueGame you do
private void Start()
{
Advertisement.AddListener(this);
Advertisement.Initialize("4006857", true);
}
But you never remove that listener!
Thus the next time the Advertisement fires its event it is still trying to execute them of the now already destroyed continueGame instance.
Therefore you always should remove any listeners as soon as you don't need them anymore:
private void OnDestroy ()
{
Advertisement.RemoveListener(this);
}

GameObject won't change after updating it with a Method (object reference not set)

Unity newb here :)
I have a button which calls this function which basicly sets a prefab to instantiate.
public void setTurret()
{
towerNode.setTurretType(turret)
Debug.Log("selected shop turret:" + turret.name);
}
My Tower_Node class handles the actual instantiate
public class Tower_Node : MonoBehaviour
{
private GameObject turret;
public void setTurretType(TowerType _turret)
{
turret= _turret.prefab;
}
private void OnMouseDown()
{
Instantiate(turret,GetBuildPosition(),Quaternion.identity);
}
...}
EDIT: What I also tried
public class Tower_Node : MonoBehaviour
{
private TowerType turret;
public void setTurretType(TowerType _turret)
{
turret = _turret;
}
private void OnMouseDown()
{
Instantiate(turret.prefab,GetBuildPosition(),Quaternion.identity);
}
...}
EDIT:
This is how the references in the inspector look. The shop script is the script with the setTurret() method
--
Setting the turret with the setTurretType method works. If i check it with Debug.Log() i get the right TowerType but outside of the function the gameobject is still =null and when i try to instantiate it gives me an NullReferenceException (because Gameobject is null obviously)
What am i missing here?
Thank you for your answers.
switch OnMouseDown() for
if (Input.GetMouseButtonDown(0))
in your update loop
just make sure that turret.prefab is a prefab
Instantiate(turret.prefab, GetBuildPosition(),Quaternion.identity);
I would say that if your TowerType class has a GameObject var named prefab, you should either assign the prefab to the prefab, or assign the turret to the _turret and the access the prefab.
Either this:
public void setTurretType(TowerType _turret) {
turret = _turret;
hoverTurret = _turret.hoverPrefab;
}
private void OnMouseDown()
{
Instantiate(turret.prefab, GetBuildPosition(),Quaternion.identity);
}
or
public void setTurretType(TowerType _turret) {
turret.prefab = _turret.prefab;
hoverTurret = _turret.hoverPrefab;
}
private void OnMouseDown()
{
Instantiate(turret.prefab, GetBuildPosition(),Quaternion.identity);
}
should work.
Edit:
You could set the turret while instiantiating:
public void setTurretType(TowerType _turret) {
turret.prefab = _turret.prefab;
hoverTurret = _turret.hoverPrefab;
}
private void OnMouseDown()
{
turret = Instantiate(turret.prefab, GetBuildPosition(),Quaternion.identity);
}

Is there a way to check if a GameObject has been destroyed?

I'm creating a game and i want to show a panel when the player is dead
I've tried different approaches but none seems to do what I want
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class DeadOrAlive : MonoBehaviour
{
public GameObject Player;
public GameObject deadPanel;
void Update()
{
if (!GameObject.FindWithTag("Player"))
{
deadPanel.SetActive(true);
}
}
}
To check if a object has been destroyed, you should use MonoBehavior's OnDestroy like so:
// Attach this script to the player object
public class DeadOrAlive : MonoBehaviour
{
public GameObject deadPanel;
void OnDestroy()
{
deadPanel.SetActive(true);
}
}
You can also instead of destroying the player object, set it to active/inactive, but to check if the player is dead or alive this way, you will need a separate object which checks the active state:
//Attach this to a object which isn't a child of the player, maybe a dummy object called "PlayerMonitor" which is always active
public class DeadOrAlive : MonoBehaviour
{
public GameObject deadPanel;
void Update()
{
if (!GameObject.FindWithTag("Player"))
{
deadPanel.SetActive(true);
}
}
}
Haven't used unity in a while and forgot how weird it could get.
Thanks to #VincentBree this is how I did it
void Update()
{
if (!Player.activeSelf)
{
deadPanel.SetActive(true);
}
}

Categories