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);
}
}
Related
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.
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);
}
}
I have tried everything with this. The coroutine will do nothing after yield return. My timestep is 0.005, because I'm executing this in VR (and require this setup). I have no idea if it has anything to do with it, I have read conflicting info. Please help, totally stumped. If there is another route I should go down, happy to dry a different method.
Ideally: tap on object, voiceover comes on and panel appears, panel disappears after 5sec, voiceover obj gets destroyed.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ActiveTouch : MonoBehaviour
{
bool redCell;
bool whiteCell;
bool plateletCell;
bool plasmodiumCell;
public GameObject plasmodiumGroup;
public GameObject rPanel;
public GameObject wPanel;
public GameObject pPanel;
public GameObject pfPanel;
public GameObject mPanel;
public GameObject welldonePanel;
public GameObject dragdropPanel;
public GameObject infoPanel;
public AudioSource myAudioSource;
public AudioSource rAudioSource;
public GameObject rAudio;
public AudioSource wAudioSource;
public GameObject wAudio;
public AudioSource pAudioSource;
public GameObject pAudio;
public AudioSource pfAudioSource;
public GameObject pfAudio;
public GameObject groupParent;
Animator groupAnimator;
private void Start()
{
redCell = false;
whiteCell = false;
plateletCell = false;
plasmodiumCell = false;
plasmodiumGroup.SetActive(false);
rPanel.SetActive(false);
wPanel.SetActive(false);
pPanel.SetActive(false);
pfPanel.SetActive(false);
welldonePanel.SetActive(false);
dragdropPanel.SetActive(false);
mPanel.SetActive(true);
rAudio.SetActive(true);
wAudio.SetActive(true);
pAudio.SetActive(true);
pfAudio.SetActive(true);
}
void OnTriggerEnter(Collider col)
{
if (col.gameObject.CompareTag("WhiteBloodCell"))
{
//Debug.Log("White Cell triggered!");
whiteCell = true;
mPanel.SetActive(false);
wPanel.SetActive(true);
myAudioSource.Play();
wAudio.SetActive(true);
wAudioSource.Play();
if (wAudioSource.isPlaying)
{
rAudio.SetActive(false);
pAudio.SetActive(false);
pfAudio.SetActive(false);
}
//StartCoroutine(wPanelCoroutine(wPanel));
StartCoroutine(PanelCoroutine(wPanel));
}
else if (col.gameObject.CompareTag("RedBloodCell"))
{
redCell = true;
mPanel.SetActive(false);
rPanel.SetActive(true);
//Debug.Log("Red Cell triggered!");
myAudioSource.Play();
rAudio.SetActive(true);
rAudioSource.Play();
if (rAudioSource.isPlaying)
{
wAudio.SetActive(false);
pAudio.SetActive(false);
pfAudio.SetActive(false);
}
//StartCoroutine(rPanelCoroutine(rPanel));
StartCoroutine(PanelCoroutine(rPanel));
}
else if (col.gameObject.CompareTag("PlateletCell"))
{
//Debug.Log("Platelet Cell triggered!");
plateletCell = true;
mPanel.SetActive(false);
pPanel.SetActive(true);
myAudioSource.Play();
pAudio.SetActive(true);
pAudioSource.Play();
if (pAudioSource.isPlaying)
{
wAudio.SetActive(false);
rAudio.SetActive(false);
pfAudio.SetActive(false);
}
//StartCoroutine(pPanelCoroutine(pPanel));
StartCoroutine(PanelCoroutine(pPanel));
}
else if (col.gameObject.CompareTag("PlasmodiumF"))
{
plasmodiumCell = true;
mPanel.SetActive(false);
pfPanel.SetActive(true);
myAudioSource.Play();
pfAudio.SetActive(true);
pfAudioSource.Play();
if (pfAudioSource.isPlaying)
{
wAudio.SetActive(false);
pAudio.SetActive(false);
rAudio.SetActive(false);
}
//StartCoroutine(pfPanelCoroutine(pfPanel));
StartCoroutine(PanelCoroutine(pfPanel));
}
else
{
}
}
IEnumerator PanelCoroutine(GameObject myPanel)
{
myPanel.SetActive(true);
yield return new WaitForSeconds(35);
myPanel.SetActive(false);
infoPanel.SetActive(true);
if (redCell == true)
{
if(GameObject.FindWithTag("RedAudio"))
Destroy (GameObject.FindWithTag("RedAudio"));
}
else if (whiteCell == true)
{
if(GameObject.FindWithTag("WhiteAudio"))
Destroy (GameObject.FindWithTag("WhiteAudio"));
}
else if (plateletCell == true)
{
if(GameObject.FindWithTag("PLAudio"))
Destroy (GameObject.FindWithTag("PLAudio"));
}
else if (plasmodiumCell == true)
{
if(GameObject.FindWithTag("PFAudio"))
Destroy (GameObject.FindWithTag("PFAudio"));
}
}
void Update()
{
if (redCell == true && whiteCell == true && plateletCell == true)
{
Debug.Log("yay");
rPanel.SetActive(false);
pPanel.SetActive(false);
wPanel.SetActive(false);
welldonePanel.SetActive(true);
//StartCoroutine(DoneCoroutine(welldonePanel));
plasmodiumGroup.SetActive(true);
redCell = false;
whiteCell = false;
plateletCell = false;
}
if (plasmodiumCell == true)
{
welldonePanel.SetActive(false);
pfPanel.SetActive(false);
dragdropPanel.SetActive(true);
}
}
this is a pretty long code for a simple function but i can't seem to know how i can shorten it. any advice?
this is a simple script that i created for a beginner project and i placed the script inside the player object with both rigidbody2d and boxcollider2d and yeah it works and all, it toggles both the button gameobjects which is what i was going for in a sense but i wanted it to use only one button. if you can help with this as well i would appreciate it.
//different button objects
public GameObject smithbutton;
public GameObject innbutton;
private void OnTriggerEnter2D(Collider2D col)
{
//debugs which collider player is in
if (col.gameObject.name == "Blacksmith")
{
Debug.Log("This is the Blacksmith");
}
if (col.gameObject.name == "Inn")
{
Debug.Log("This is the Inn");
}
}
private void OnTriggerStay2D(Collider2D col)
{
//once playerobject stays, button will toggle till player leaves
if (col.gameObject.name == "Blacksmith")
{
Debug.Log("still on the Blacksmith's door");
smithbutton.SetActive(true);
}
if (col.gameObject.name == "Inn")
{
Debug.Log("still on the Inn's door");
innbutton.SetActive(true);
}
}
private void OnTriggerExit2D(Collider2D col)
{
//once playerobject exits, button will toggle and disappear
if (col.gameObject.name == "Blacksmith")
{
smithbutton.SetActive(false);
}
if (col.gameObject.name == "Inn")
{
innbutton.SetActive(false);
}
}
There is no much you could do, as the function is quite simple. You could make it better, and still reduce some of the lines. Using tag instead of name will be future proof if you create more Inns or more blacksmiths. Using the collider call a method will let you extend the functionality with ease. I will usually add each of this checks to the Inn and Blacksmiths myself, and they will be looking for the player.
//different button objects
[SerializeField] private GameObject smithbutton;
[SerializeField] private GameObject innbutton;
private void OnTriggerEnter2D(Collider2D col)
{
//debugs which collider player is in
if (col.gameObject.tag == "Blacksmith")
{
ButtonActivationToggle(smithbutton, col);
}
if (col.gameObject.tag == "Inn")
{
ButtonActivationToggle(innbutton, col);
}
}
private void OnTriggerExit2D(Collider2D col)
{
//once playerobject exits, button will toggle and disappear
if (col.gameObject.tag == "Blacksmith")
{
ButtonActivationToggle(smithbutton, col);
}
if (col.gameObject.tag == "Inn")
{
ButtonActivationToggle(innbutton, col);
}
}
public void ButtonActivationToggle(GameObject button, Collider2D collider)
{
bool tmp = false;
tmp = button.activeInHierarchy ? false : true;
button.SetActive(tmp);
if (button.activeInHierarchy)
{
Debug.Log("This is the " + gameObject.collider.tag)
}
}
you dont need the OnTriggerStay, you can do that in OnTriggerEnter and get rid of the Stay function.
public Button mybtn;
bool isBlacksmith; // keep track of where you are (you can later make it an enum if there are more than 2 places and check that)
void Start()
{
//when the button is clicked buttonFunction will be called
mybtn.onClick.AddListener(buttonFunction);
}
private void OnTriggerEnter2D(Collider2D col)
{
if (col.gameObject.name == "Blacksmith")
{
Debug.Log("Entered Blacksmith's door");
mybtn.gameObject.SetActive(true);
isBlacksmith = true;
}
if (col.gameObject.name == "Inn")
{
Debug.Log("Entered Inn's door");
mybtn.gameObject.SetActive(true);
isBlacksmith = false;
}
}
private void OnTriggerExit2D(Collider2D col)
{
//once playerobject exits, button will toggle and disappear
if (col.gameObject.name == "Blacksmith" || col.gameObject.name == "Inn")
{
smithbutton.SetActive(false);
}
}
public void buttonFunction()
{
if (isBlacksmith)
Debug.Log("In Blacksmith");
else
Debug.Log("In Inn");
}
How can I enable/disable mesh renderer of multiple gameobjects when the player enters in a collider? This is my code but it doesn't works.
using UnityEngine;
using System.Collections;
public class SueloManager : MonoBehaviour {
private GameObject suelo;
void Start ()
{
suelo = GameObject.FindGameObjectsWithTag ("SueloWireframe");
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Player") {
suelo.GetComponent<Renderer> ().enabled = false;
Debug.Log ("Oculta suelo");
}
}
void OnTriggerExit(Collider other)
{
if (other.gameObject.tag == "Player") {
suelo.GetComponent<Renderer> ().enabled = true;
Debug.Log ("Aparece suelo");
}
}
}
FindGameObjectWithTag returns a single GameObject and FindGameObjectsWithTag returns array of GameObject. Just like Kroltan mentioned, you have to change suelo to an array then use loop to enable and disable all of them. Having the loop in a simple re-usable function should simplify this. Look at the EnableRenderer function in the solution below.
private Renderer[] sueloRenderers;
void Start()
{
GameObject[] suelo = GameObject.FindGameObjectsWithTag("SueloWireframe");
sueloRenderers = new Renderer[suelo.Length];
for (int i = 0; i < sueloRenderers.Length; i++)
{
sueloRenderers[i] = suelo[i].GetComponent<Renderer>();
}
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Player")
{
EnableRenderer(sueloRenderers, false);
Debug.Log("Oculta suelo");
}
}
void OnTriggerExit(Collider other)
{
if (other.gameObject.tag == "Player")
{
EnableRenderer(sueloRenderers, true);
Debug.Log("Aparece suelo");
}
}
void EnableRenderer(Renderer[] rd, bool enable)
{
for (int i = 0; i < rd.Length; i++)
{
rd[i].enabled = enable;
}
}