I want to enable my collider again after disabling it - c#

When my character hits the gameobject collider, an enemy will be spawned and the collider is disabled, cuz I do not want to spawn multiple enemies. When my character dies and I have to start from the beginning, the collider should be enabled again to spawn the enemy again.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TriggerSpawner : MonoBehaviour
{
public EnemySpawn enemyspawn;
void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.CompareTag("Player"))
{
enemyspawn.SpawnEnemy();
gameObject.GetComponent<BoxCollider2D>().enabled = false;
}
}
}
//in other class
private void SetHealth(float health)
{
var actualNextHealth = Mathf.Min(m_maxHealth, health);
m_currentHealth = actualNextHealth;
if (m_healthBar != null && m_maxHealth > 0f)
m_healthBar.SetHealth(actualNextHealth / m_maxHealth);
if (m_currentHealth <= 0f)
{
UpdateHighscore();
Die();
}
}
private void Die()
{
m_character.NotifyDied();
if (m_canRespawn)
{
SetVulnerable();
RemovePoison();
m_hazards.Clear();
gameObject.transform.position = m_spawnPosition;
SetHealth(m_maxHealth);
}
else {
Destroy(gameObject);
}
}

You can create a static variable in the trigger script that you assign the Collider value to it.
When an enemy is spawned it deactivates, as in your code.
public class TriggerSpawner : MonoBehaviour
{
public static Collider2D spawnCollider;
public EnemySpawn enemyspawn;
void Start() => spawnCollider.GetComponent<Collider2D>();
void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.CompareTag("Player"))
{
enemyspawn.SpawnEnemy();
spawnCollider.enabled = false;
}
}
}
When you die, it will reactivate.
private void Die()
{
m_character.NotifyDied();
if (m_canRespawn)
{
TriggerSpawner.spawnCollider.enabled = true;
SetVulnerable();
RemovePoison();
m_hazards.Clear();
gameObject.transform.position = m_spawnPosition;
SetHealth(m_maxHealth);
}
else {
Destroy(gameObject);
}
}

With minimal changes on your code, I'd suggest this:
private void Die()
{
m_character.NotifyDied();
if (m_canRespawn)
{
SetVulnerable();
RemovePoison();
m_hazards.Clear();
gameObject.transform.position = m_spawnPosition;
SetHealth(m_maxHealth);
gameObject.GetComponent<BoxCollider2D>().enabled = true; // add this line
}
else {
Destroy(gameObject);
}
}

Related

A fade animation on another gameObject

is actually a rythm game and when a circle enter into a trigger we can make disapear the circle.
public class CursorPress : MonoBehaviour {
public bool canBePressed;
public KeyCode keyToPress;
void Update()
{
if (Input.GetKeyDown(keyToPress))
{
GameObject target = GameObject.Find("hitcircle_r");
if(target.tag == "Target")
{
if (canBePressed)
{
target.GetComponent<Animation> ().play("hitcircle_fading");
target.SetActive(false);
}
}
}
}
void OnTriggerEnter2D(Collider2D col)
{
if (col.gameObject.tag == "Target")
{
canBePressed = true;
}
}
void OnTriggerExit2D(Collider2D col)
{
if (col.gameObject.tag == "Target")
{
canBePressed = false;
}
}
}
I want that when the player press a key (keyToPress), a custom gameObject (hitcircle_r) gets a fade animation before disapearing, but idk how to do it, i tried a lot of code i found on the web, can someone helps me please ?
There are many ways to achieve what you want.
One would be to call a coroutine that fades deactivates your target after time.
If you are only doing fading style animations you should look into DOTween.
using System.Collections;
using UnityEngine;
public class CursorPress : MonoBehaviour
{
public bool canBePressed;
public KeyCode keyToPress;
void Update()
{
if (Input.GetKeyDown(keyToPress))
{
GameObject target = GameObject.Find("hitcircle_r");
if (target.tag == "Target")
{
if (canBePressed)
{
target.GetComponent<Animation>().Play("hitcircle_fading");
float hideTime = 0.5f; // the length of your animation
StartCoroutine(DeactivateTarget(target, hideTime));
}
}
}
}
void OnTriggerEnter2D(Collider2D col)
{
if (col.gameObject.tag == "Target")
{
canBePressed = true;
}
}
void OnTriggerExit2D(Collider2D col)
{
if (col.gameObject.tag == "Target")
{
canBePressed = false;
}
}
// coroutine to deactivate GameObject
private IEnumerator DeactivateTarget(GameObject targetGo, float hideDelay)
{
yield return new WaitForSeconds(hideDelay);
targetGo.SetActive(false);
}
}

Unity 2D RPG Healing from Potions

I'm currently developing developing a 2d top-down RPG game in Unity.
I am trying to implement a healing system where you heal some points when you buy a coffee. This is my healthManager:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HealthManager : MonoBehaviour
{
public int maxHealth = 10;
public int currentHealth;
public HealthBarScript healthBar;
void Start()
{
currentHealth = maxHealth;
healthBar.SetMaxHealth(maxHealth);
}
void Update()
{
if(Input.GetKeyDown(KeyCode.Space))
{
TakeDamage(1);
}
}
public void TakeDamage(int damage)
{
currentHealth -= damage;
healthBar.SetHealth(currentHealth);
if(currentHealth <= 0)
{
currentHealth = 0;
}
}
public void heal(int heal)
{
currentHealth += heal;
healthBar.SetHealth(currentHealth);
if(currentHealth >= maxHealth)
{
currentHealth = maxHealth;
}
}
}
And this is the script to buy coffee from a game object (sth. like a healing fountain):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class KaffeeautomatDialog : MonoBehaviour
{
public GameObject dialogBox;
public Text dialogText;
public string dialog;
public bool playerInRange;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if(Input.GetKeyDown(KeyCode.E) && playerInRange)
{
if(dialogBox.activeInHierarchy)
{
dialogBox.SetActive(false);
}
else
{
dialogBox.SetActive(true);
dialogText.text = dialog;
}
}
}
public void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("Player"))
{
Debug.Log("Player entered");
playerInRange = true;
var healthManager = other.GetComponent<HealthManager>();
if(Input.GetKeyDown(KeyCode.J) && playerInRange)
{
if(healthManager != null)
{
healthManager.heal(5);
Debug.Log("You healed 5 Points!");
}
}
}
}
public void OnTriggerExit2D(Collider2D other)
{
if (other.CompareTag("Player"))
{
Debug.Log("Player left");
playerInRange = false;
dialogBox.SetActive(false);
}
}
}
The Dialog Box shows up just fine and the Text is displayed. When i am staning in front of the healing fountain, i can activate and deactivate the dialog box by pressing "e".
But when i press "j", i don't heal and the console.log won't appear in Unity.
Did i mess up the Component import?
Checking for an Input it should always happen inside the Update() method and not inside the OnTriggerEnter2D() because the OnTriggerEnter2D() method it will only executed everytime something gets inside the trigger which might happen only onces. On the other hand Update() it will be executed every single frame and check for an Input.
What you can do is the following, inside your OnTriggerEnter2D() method you need to have a global boolean variable that indicates that the player has entered the trigger and inside your Update() method when you check for the Input key "J" you need to check if the above boolean flag is true, if it is true then continue with the heal process. Also you need to make the flag false when the player exit the trigger.
From what I see you already have such flag playerInRange, you can write the following code:
public HealthManager healthManager;
void Update()
{
if(playerInRange)
{
if(Input.GetKeyDown(KeyCode.E))
{
if(dialogBox.activeInHierarchy)
{
dialogBox.SetActive(false);
}
else
{
dialogBox.SetActive(true);
dialogText.text = dialog;
}
}
if(Input.GetKeyDown(KeyCode.E))
{
if(healthManager != null)
{
healthManager.heal(5);
Debug.Log("You healed 5 Points!");
}
}
}
}
public void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("Player"))
{
Debug.Log("Player entered");
playerInRange = true;
healthManager = other.GetComponent<HealthManager>();
}
}
Remove the Input check from your OnTriggerEnter2D() method.

The scene change script for my unity project is not working, I cant understand why

Here is the code for the same.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class changescene : MonoBehaviour
{
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Player"))
{
if(Input.GetKeyDown(KeyCode.Space))
{
SceneManager.LoadScene(1);
}
}
}
}
Running this with a 3D cube tagged player is not changing scenes and neither showing any errors.
Input.GetKeyDown is only true once per key press and only during a single frame where the key went down.
It is extremely unlikely that you press the key down exactly in the FixedUpdate physics all when the trigger enters your collider!
You want to split your physics / collision detection from user input and rather do e.g.
public class changescene : MonoBehaviour
{
private bool isEntered;
private void OnTriggerExit(Collider other)
{
if (!other.CompareTag("Player")) return;
isEntered = false;
}
private void OnTriggerEnter(Collider other)
{
if (!other.CompareTag("Player")) return;
isEntered = true;
}
private void Update()
{
if(isEntered && Input.GetKeyDown(KeyCode.Space))
{
SceneManager.LoadScene(1);
}
}
}
Or if you want to make it a bit more efficient without an Update method that runs most of time unnecessary you can use a Coroutine like e.g.
public class changescene : MonoBehaviour
{
private void OnTriggerExit(Collider other)
{
if (!other.CompareTag("Player")) return;
StartCoroutine(CheckSpaceRoutine());
}
private void OnTriggerEnter(Collider other)
{
if (!other.CompareTag("Player")) return;
StopAllCoroutines();
}
private IEnumerator CheckSpaceRoutine()
{
while(true)
{
if(Input.GetKeyDown(KeyCode.Space))
{
SceneManager.LoadScene(1);
yield break;
}
yield return null;
}
}
}

Character does not "see" the player (3D Game)

I am following this unity 3D course. I followed every single step of the part called "Enemies Part 1: Static Observers", and after re-checking the code and doing researches for a day, I still did not find the problem. The scope of this part of the tutorial is to make that when the "Gargoyle" sees the player, when passing in front of him, should restart the game.
These are the two scripts that should make this work, but don't.
Observer (Gargoyle):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Observer : MonoBehaviour
{
public Transform player;
public GameEnding gameEnding;
bool m_IsPlayerInRange;
void OnTriggerEvent(Collider other)
{
if (other.transform == player)
{
m_IsPlayerInRange = true;
}
}
void OnTriggerExit(Collider other)
{
if (other.transform == player)
{
m_IsPlayerInRange = false;
}
}
void Update()
{
if (m_IsPlayerInRange)
{
Vector3 direction = player.position - transform.position + Vector3.up;
Ray ray = new Ray(transform.position, direction);
RaycastHit raycastHit;
if (Physics.Raycast(ray, out raycastHit))
{
if (raycastHit.collider.transform == player)
{
gameEnding.CaughtPlayer();
}
}
}
}
}
And this is the GameEnding script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class GameEnding : MonoBehaviour
{
public float fadeDuration = 1f;
public float displayImageDuration = 1f;
public GameObject player;
public CanvasGroup exitBackgroundImageCanvasGroup;
public CanvasGroup caughtBackgroundImageCanvasGroup;
bool m_IsPlayerAtExit;
bool m_IsPlayerCaught;
float m_Timer;
void OnTriggerEnter(Collider other)
{
if (other.gameObject == player)
{
m_IsPlayerAtExit = true;
}
}
public void CaughtPlayer()
{
m_IsPlayerCaught = true;
}
void Update()
{
if (m_IsPlayerAtExit)
{
EndLevel(exitBackgroundImageCanvasGroup, false);
}
else if (m_IsPlayerCaught)
{
EndLevel(caughtBackgroundImageCanvasGroup, true);
}
}
void EndLevel(CanvasGroup imageCanvasGroup, bool doRestart)
{
m_Timer += Time.deltaTime;
imageCanvasGroup.alpha = m_Timer / fadeDuration;
if (m_Timer > fadeDuration + displayImageDuration)
{
if (doRestart)
{
SceneManager.LoadScene(0);
}
else
{
Application.Quit();
}
}
}
}
Back to the unity editor, I set the variables (player, gameending, exitimagebackground and caught imagebackground.
Does anybody know what the problem is and could help me out?
Thank you!
Edit:
these are the components of the Player Character:
and these of the Gargoyle:
Which has these as children:
which have these other components:
On your Observer class,
void OnTriggerEvent(Collider other)
{
if (other.transform == player)
{
m_IsPlayerInRange = true;
}
}
The function name is OnTriggerEvent(Collider), it should be OnTrigger**Enter**(Collider) instead.
Otherwise, it should work as intended.

Object is being spammed when it comes to my timeBetweenShot variable, can anyone take a look?

I Have created a 2d stealth game where the enemy fires on the player, only problem is that although the bullets are created and deleted fine on another script, the script itself spams the program with bullets every frame, creating the unwanted result
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HurtPlayer : MonoBehaviour
{
public float timeToShoot;
private float timeToShootCounter;
private bool shot;
private Vector3 moveDirection;
public float timeBetweenShot;
public float timeBetweenShotCounter;
public Transform firePoint;
public GameObject Bullet;
// Use this for initialization
void Start()
{
shot = false;
timeToShootCounter = timeToShoot;
}
// Update is called once per frame
void Update()
{
while (shot == true)
{
StartCoroutine(Delay());
Destroy(GameObject.Find("Bullet"));
timeBetweenShot -= Time.deltaTime;
timeToShoot -= Time.deltaTime;
}
}
IEnumerator Delay()
{
yield return new WaitForSeconds(0.5f);
}
void OnTriggerStay2D(Collider2D other)
{
if (other.gameObject.tag == "player")
{
if (shot == false)
{
if (timeToShoot >= 0f)
{
shot = true;
if (shot == true)
{
shot = false;
Instantiate(Bullet, firePoint.position, firePoint.rotation);
Delay();
if (timeBetweenShot <= 0f)
{
shot = false;
timeToShoot = timeToShootCounter;
timeBetweenShot = timeBetweenShotCounter;
}
}
}
}
}
}
}
What I want is the time betweenshot to work and for the enemy to only shoot once every one or half a second, thanks.
Is this what you are looking for?
IEnumerator ContinuousShoot()
{
// Continuously spawn bullets until this coroutine is stopped
// when the player exits the trigger.
while (true)
{
yield return new WaitForSeconds(1f); // Pause for 1 second.
Instantiate(Bullet, firePoint.position, firePoint.rotation);
}
}
void OnTriggerEnter2D(Collider2D other)
{
// Player enters trigger
if (other.gameObject.CompareTag("player"))
{
StartCoroutine(ContinuousShoot());
}
}
void OnTriggerExit2D(Collider2D other)
{
// Player exits trigger
if (other.gameObject.CompareTag("player"))
{
StopCoroutine(ContinuousShoot());
}
}

Categories