How do I enable and disable multiple game objects in Unity? - c#

I Need to Enable and Disable Multiple Gameobjects that contain Same Tag in Unity using C#.Thanks

You can use GameObject.FindGameObjectsWithTag() to return an array of all game objects with a given tag, then use GameObject.SetActive() to enable or disable them. Something like:
string tag = ""; // your tag
GameObject[] taggedObjects = GameObject.FindGameObjectsWithTag(tag);
foreach (GameObject tagged in taggedObjects){
tagged.Setactive(false); // or true
}

Unfortunately GameObject.FindGameObjectsWithTag() does not return inactive gameobjects. So you can leave all objects active before scene start and re close them in awake() or start().
And unity 2020 would have that feature which find inactive gameobjects too.

Above answers mess up with my camera or sort of. So, I Did my own code based on the answers.( Which is Inserted Below) (Posting It for Future Uses) Thanking Everyone who Answered.
using UnityEngine;
using UnityEngine.SceneManagement;
using System.Collections;
public class GameManager : MonoBehaviour
{
public float restarttimer = 3f;
public GameObject Ninja;
public GameObject Covid;
public GameObject[] Buttons;
public GameObject[] Ground;
public GameObject[] HP;
public GameObject[] panelgo;
void Start()
{
//Ninja
Debug.Log("Generating Hero");
Ninja.SetActive(true);
//enemy
Debug.Log("Generating Enemy");
Covid.SetActive(true);
//ground
Debug.Log("Generating Ground");
foreach (GameObject tagged in Ground)
{
tagged.SetActive(true); // or true
}
//HP
foreach (GameObject tagged in HP)
{
tagged.SetActive(true); // or true
}
//Buttons
foreach (GameObject tagged in Buttons)
{
tagged.SetActive(true); // or true
}
//GameOver
foreach (GameObject tagged in panelgo)
{
tagged.SetActive(false); // or true
}
}
public void GameOver()
{
Ninja.SetActive(false);
Covid.SetActive(false);
foreach (GameObject tagged in Ground)
{
tagged.SetActive(false); // or true
}
foreach (GameObject tagged in HP)
{
tagged.SetActive(false); // or true
}
foreach (GameObject tagged in Buttons)
{
tagged.SetActive(false); // or true
}
foreach (GameObject tagged in panelgo)
{
tagged.SetActive(true); // or true
}
}
public void buttonrestart()
{
Invoke("restart", restarttimer);
}
public void restart()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
}
P.S COVID Funny Name for enemy ;)
-------------------THE THREAD IS CLOSED--------------------------

Related

Multiple objects, one animation?

I want to move multiple characters using a single animation. I tried to use loop for this but failed. Can you help? I want to return the characters I added under GameObject.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class ses : MonoBehaviour
{
AudioSource audioSource;
public Animator animator;
public GameObject[] karakul;
void Start()
{
audioSource = GetComponent<AudioSource>();
//animator = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
}
public void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "sayiCollider")
{
audioSource.Play();
foreach (var item in karakul)
{
animator.SetBool("clap", true);
}
}
else
{
animator.SetBool("clap", false);
}
}
}
enter image description here
enter image description here
enter image description here
You are iterating through the GameObjects, and every time set a param on an animator, which is nothing to do with those GameObjects.
Usually, the crowd has solved another way for performance, but to answer your question, you need to add an Animator component to all GameObject you want to animate and call the SetBool on them, something like that:
[SerializeField] private Animator[] _animators;
private void OnTiggerEnter(Collider other)
{
bool isSayi = other.CompareTag("sayiCollider");
if (isSayi) audioSource.Play();
else audioSource.Stop();
for (int i = 0; i < _animators.Length; i++) _animators[i].SetBool("clap", isSayi);
}

Unity Selected Emote Animations

Hello everyone I am trying to make a simple Emote functionality. I have a bubble(like a chat bubble) and inside of that there is an animation. Like in Legends of Runeterra and Clash Royale type games.
public class EmoteBubble : MonoBehaviour
{
private Animator animator;
private Animator childAnimator;
public List<GameObject> objectList;
// Start is called before the first frame update
void Start()
{
animator = gameObject.GetComponent<Animator>();
foreach (GameObject obj in objectList)
{
obj.SetActive(false);
}
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Space)){
childAnimator = transform.Find(objectList[0].name).GetComponent<Animator>();
objectList[0].SetActive(true);
StartCoroutine(HeroAnimator(2f, objectList[0].name + "Bool"));
}
IEnumerator HeroAnimator(float animationLength, string parameter)
{
animator.SetBool("EmoteBool", true);
childAnimator.SetBool(parameter, true);
yield return new WaitForSeconds(animationLength);
animator.SetBool("EmoteBool", false);
childAnimator.SetBool(parameter, false);
yield return new WaitForSeconds(0.2f);
foreach (GameObject obj in objectList)
{
obj.SetActive(false);
}
}
}
This is the script of the bubble and it has childs in objectList. If I hit space I want a specific animation to kick in like the first one or the second one. I am trying to disable every object in Start function and enable the one that i choose. But when I use prefabs only the real one gets disabled. Should I use prefabs in this emote concept or should I make every object different ?
public class EmoteBubble : MonoBehaviour
{
private Animator animator;
private Animator childAnimator;
public List<GameObject> objectList;
// Start is called before the first frame update
void Start()
{
Debug.Log(objectList[2]);
animator = gameObject.GetComponent<Animator>();
foreach (GameObject obj in objectList)
{
obj.SetActive(false);
}
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Space)){
objectList[0].SetActive(true);
childAnimator = transform.Find(objectList[0].name).GetComponent<Animator>();
StartCoroutine(HeroAnimator(2f, objectList[0].name + "Bool"));
}
if (Input.GetKeyDown(KeyCode.A)) {
objectList[1].SetActive(true);
childAnimator = transform.Find(objectList[1].name).GetComponent<Animator>();
StartCoroutine(HeroAnimator(2f, objectList[1].name + "Bool"));
}
if (Input.GetKeyDown(KeyCode.S)){
objectList[2].SetActive(true);
childAnimator = transform.Find(objectList[2].name).GetComponent<Animator>();
StartCoroutine(HeroAnimator(2f, objectList[2].name + "Bool"));
}
IEnumerator HeroAnimator(float animationLength, string parameter)
{
animator.SetBool("EmoteBool", true);
childAnimator.SetBool(parameter, true);
yield return new WaitForSeconds(animationLength);
animator.SetBool("EmoteBool", false);
childAnimator.SetBool(parameter, false);
yield return new WaitForSeconds(0.2f);
foreach (GameObject obj in objectList)
{
obj.SetActive(false);
}
}
}
}
I think this works, It looks simple and it works but I don't know if it's the best way.

Retrive objects from a list and teleport them to a specific location in Unity

and thank you for looking at this in advance.
I have yet another problem that i need to solve and it goes like this:
I have a list of objects that i select with a raycast, and i would like to teleport them to a specific location in the scene. Like for example i have selected a cube and a sphere and they are added to my list called playersTagged.
How can i get the objects in my list to that specific location when OnCollisionEnter with my player that has the tag "Tagger"?
My code looks like this:
PlayerTagged Class
using System.Collections.Generic;
using UnityEngine;
public class PlayerTagged : MonoBehaviour
{
public float damage = 10f;
public float range = 100f;
public Camera fpsCam;
public List<GameObject> playersTagged;
private void Update()
{
if (Input.GetButtonDown("Fire1"))
{
Shoot();
}
}
void Shoot()
{
RaycastHit hit;
if (Physics.Raycast(fpsCam.transform.position, fpsCam.transform.forward, out hit, range))
{
Debug.Log(hit.transform.name);
Target target = hit.transform.GetComponent<Target>();
if (target != null && target.isHit == false)
{
target.takeDamage(damage);
if(hit.collider.tag == "Taggable")
playersTagged.Add(hit.collider.gameObject);
target.isHit = true;
}
}
}
}
Teleport class:
using UnityEngine;
public class Teleport : MonoBehaviour
{
public Transform teleportTarget;
public PlayerTagged player;
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Tagger")
{
Debug.Log("You hit the can");
}
}
}
You need to have the PlayerTagged reference in your Teleport component. If both objects will always exist in your scene, only create a public field in your Teleport and drag and drop your PlayerTagged ref, otherwise you will need to fill this ref by code using some "find" approach, for example, GameObject.FindObjectWithTag().
You can also make an event that trigger when the object that entered the OnTriggerEnter is valid (I mean, when your tag condition pass) and then make sure that PlayerTagged is being registered as listener to this event.
First one is easier to setup, but if you plan to make unique things with this OnTriggerEnter as playing sounds, changing data or something like that, the second one is a better approach.
EDIT: I'll try to insert some code, let me know if you still having problems on getting the idea
"If both objects will always exist in your scene..."
using UnityEngine;
public class Teleport : MonoBehaviour
{
public Transform teleportTarget;
public PlayerTagged player; // I didn't saw that you already have an ref here, my bad, so you only need to access the fields
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Tagger")
{
Debug.Log("You hit the can");
var list = player.playersTagged; // this is how you will access your list
// Do some stuff with your list
}
}
}
Ignore the rest, it will only complicate things
EDIT 2: Making the teleport happen in player, and teleport every object
using System.Collections.Generic;
using UnityEngine;
public class PlayerTagged : MonoBehaviour
{
public float damage = 10f;
public float range = 100f;
public Camera fpsCam;
public List<GameObject> playersTagged;
private void Update()
{
if (Input.GetButtonDown("Fire1"))
{
Shoot();
}
}
// Option 1:
private void OnTriggerEnter(Collider col)
{
if (col.gameObject.tag == "Teleport Tag")
{
var teleport = col.gameObject.GetComponent<Teleport>();
TeleportObjectsTo(teleport.teleportTarget.position);
}
}
void Shoot()
{
RaycastHit hit;
if (Physics.Raycast(fpsCam.transform.position, fpsCam.transform.forward, out hit, range))
{
Debug.Log(hit.transform.name);
Target target = hit.transform.GetComponent<Target>();
if (target != null && target.isHit == false)
{
target.takeDamage(damage);
if(hit.collider.tag == "Taggable")
playersTagged.Add(hit.collider.gameObject);
target.isHit = true;
}
}
}
public void TeleportObjectsTo(Vector3 targetPosition)
{
foreach(taggedObjects in playersTagged)
{
taggedObjects.transform.position = targetPosition;
}
}
}
You can also make the teleport happen on teleport script:
using UnityEngine;
public class Teleport : MonoBehaviour
{
public Transform teleportTarget;
public PlayerTagged player; // I didn't saw that you already have an ref here, my bad, so you only need to access the fields
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Tagger")
{
Debug.Log("You hit the can");
// Option 2:
player.TeleportObjectsTo(teleportTarget);
// Option 3: Or you can iterate here instead of make use of the API
foreach(var taggedObjects in player.playersTagged)
{
taggedObjects.transform.position = targetPosition;
}
}
}
}
Chose one option, and delete/comment others
--N

Unity particle system play after collision

I made a Project in Unity, a game to be clear. So the player has a Sci-fi car and he tries to avoid obstacles-rocks.
When the car hits a rock, the Game Manager load the "credits" screen to choose between quit or restart.
My problem is that I want to make the rock explode when the car goes on it and then the Game Manager will load the "credits" screen.
Some of my code:
For player collision:
public class PlayerCollision : MonoBehaviour {
public PlayerMovement movement;
public static bool y = true;
public void OnCollisionEnter (Collision collisionInfo)
{
// We check if the object we collided with has a tag called "Obstacle".
if (collisionInfo.collider.tag == "Obstacle")
{
movement.enabled = false; // Disable the players movement.
y = false;
FindObjectOfType<GameManager>().EndGame();
}
}
}
Game Manager:
public class GameManager : MonoBehaviour {
bool gameHasEnded = false;
public float restartDelay = 1f;
public GameObject completeLevelUI;
public void CompleteLevel ()
{
completeLevelUI.SetActive(true);
}
public void EndGame ()
{
if (gameHasEnded == false)
{
gameHasEnded = true;
Debug.Log("GAME OVER");
Invoke("Restart", restartDelay);
}
}
void Restart ()
{
SceneManager.LoadScene("Credits");
//SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
}
The endTrigger:
public class EndTrigger : MonoBehaviour {
public GameManager gameManager;
void OnTriggerEnter ()
{
gameManager.CompleteLevel();
}
}
LevelComplete:
public class LevelComplete : MonoBehaviour {
public void LoadNextLevel ()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1);
}
}
Menu:
public class Menu : MonoBehaviour {
public void StartGame ()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1);
}
}
I have written other scripts. If you want anything let me know. Thanks guys.
Add a particle system to your rocks. Uncheck "looping" and "play on awake". Then you can play by adding the line below.
public void OnCollisionEnter (Collision collisionInfo)
{
// We check if the object we collided with has a tag called "Obstacle".
if (collisionInfo.collider.tag == "Obstacle")
{
movement.enabled = false; // Disable the players movement.
y = false;
collisionInfo.gameObject.GetComponent<ParticleSystem>().Play(); // play the explosion
FindObjectOfType<GameManager>().EndGame();
}
}
I would change your approach. As I understand you already have an endTrigger [With a Collider Trigger] that ends the game if the player goes inside. So uncheck the trigger in the player collider and instead add that trigger to the rocks collider, so when the player crashes it will:
Activate the Particle System
Makes the rock invisible
End the Game
You can add this script to your rock and see how it works
public class RockTrigger : MonoBehaviour {
public GameManager gameManager;
ParticleSystem myParticleSystem;
void Awake()
{
myParticleSystem = GetComponent<ParticleSystem>();
}
void OnTriggerEnter(Collider other)
{
myParticleSystem.Play();
GetComponent<MeshRenderer>.enabled = false;
gameManager.GetComponent<GameManager>().EndGame();
}
}
Note about the OnTriggerEnter: In case you only have the player moving in the scene this is fine like this (I use the same pattern you used in EndGame),
but in case there were other GameObject with a RigidBody moving in the
scene you should check if other is indeed the player. Usually tagging the player and the checking if(other.tag == "Player")

Making a sliding door that is unlocked with a key in unity

I've been trying to make a sliding door for my unity level and I've managed to set up the animations but the scripting that's supposed to link up the functions with the objects isn't working.
Here's the script for the key card:
using UnityEngine;
using System.Collections;
public class Key_Pickup_1 : MonoBehaviour {
public GameObject player;
private Player_inventory playerinventory;
void Awake ()
{
playerinventory = player.GetComponent<Player_inventory>();
}
// Update is called once per frame
void onTriggerEnter()
{
if (gameObject == player)
{
playerinventory.hasKey_1 = true;
Destroy(gameObject);
}
}
}
Here's the script for the Door animation:
using UnityEngine;
using System.Collections;
public class Door_Animation_1 : MonoBehaviour {
public string Open;
private Animator anim_1;
public GameObject player;
private Player_inventory playerInventory;
void Start()
{
anim_1 = GetComponent<Animator>();
player = GameObject.FindGameObjectWithTag("Player");
playerInventory = player.GetComponent<Player_inventory>();
}
void OntriggerEnter (Collider other)
{
if(other.gameObject == player)
{
if (playerInventory.hasKey_1)
{
anim_1.SetTrigger(Open);
}
}
}
Any Ideas?
You don't have the proper capitalization for the OnTriggerEnter methods in your code. You have two different spellings and they are both wrong. It must be exactly OnTriggerEnter (or OnTriggerEnter2D for objects with a Collider2D instead of a Collider).

Categories

Resources