Game object can't detect others when using collision.gameObject.tag in unity - c#

I have designed a scenario as below:
I created an object spawner to collide with things tagged as "ob", using a boolean to manage the timing to spawn new obstacles. Nonetheless, after some testing, I found that it seemed like nothing had ever collided with one another(Judged by the strings I put in the if condition had never shown in the console.) Can't figure out why! Please HELP!!!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class newObSpawning : MonoBehaviour
{
public GameObject[] oblist;
private bool hasOb=true;
public float adjustSpawnx;
void Update()
{
if (!hasOb)
{
spawnObs();
hasOb = true;
}
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.CompareTag("ob"))
{
hasOb = true;
Debug.Log("hasOb"); //just for testing
}
}
private void OnTriggerExit2D(Collider2D collision)
{
if (collision.gameObject.CompareTag("ob"))
{
hasOb = false;
Debug.Log("hasOb");
}
}
public void spawnObs()
{
int i = Random.Range(0, oblist.Length);
Debug.Log(i);
float y = 7.87f;
GameObject newob = Instantiate(oblist[i], new Vector3(transform.position.x+ adjustSpawnx,y,0), Quaternion.identity);
}
}
obspawner carry a "follow player" script to move at the same pace as the player,and it went just well

Your player doesn't seem to have a Rigidbody2D component. Add Rigidbody2D to your player. A collider can only emit OnTriggerEnter2D or OnTriggerExit2D events if there is a rigidbody on the object too

You have to tag the object "ob" that you want to register the collision with, most probably, I think what you are searching for is the collision of your player with object spawner so tag the player with "ob".

Related

Collision detection for individual objects in a list Unity3D

I want to have it so that a single game object from a list is destroyed when it hits the ground. So far I am able to spawn random prefabs in set spawn locations in the scene successfully, but I am having trouble implementing the collision detection for when they fall to the ground. I have tried both raycasting and OnCollisionEnter but neither is working, the collision is not being detected. I am missing something but not sure what. Below is my attempt with OnCollisionEnter:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ObjectSpawner : MonoBehaviour
{
public List<GameObject> prefabObjects;
public List<GameObject> locations;
public List<GameObject> spawnedObjects;
void Start()
{
//create empty list of spawned objects
spawnedObjects = new List<GameObject>();
SpawnObject(RandomObjects());
}
// Update is called once per frame
void Update()
{
}
void SpawnObject(GameObject obj)
{
GameObject newObject = Instantiate(obj, transform.position, Quaternion.identity );
spawnedObjects.Add(newObject);
}
GameObject RandomObjects()
{
int rand = Random.Range(0, prefabObjects.Count);
return prefabObjects[rand];
}
void OnCollisionEnter(Collision collision)
{
for (var i = 0; i < spawnedObjects.Count; i++){
GameObject obj = spawnedObjects[i];
if (collision.collider.tag == "Ground"){
Debug.Log("Hit ground");
spawnedObjects.Remove(obj);
Destroy(obj);
}
}
}
Your void OnCollisionEnter(Collision collision) method is in the wrong place, you dont want the ObjectSpawner itself to collide but the instancianted obj's. Place a new script on your prefabs and implement OnCollisionEnter there. For the method to trigger, be sure to set up colliders and rigidbodies correctly. Your prefabs and the ground should have colliders and either one of these a non-kinematic rigidbody too.

Unity (C#) - How do I single out GameObject being detected by Raycast in a destroy / respawn system

I'm trying to make a Destroy gameobject, wait x seconds, respawn gameobject system. I have 2 scripts and I'm destorying then instantiating it again. I want to use multiples of the same prefab called "Breakable" but have only the one I'm aiming at being destroyed. Similar to games like Minecraft, aim and only the aimed at the block is destroyed.
BlockBreakItem script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BlockBreakItem : MonoBehaviour
{
RaycastHit hit;
int layerMask = 1;
public GameObject breakableObject;
public bool isObjectDestoryed = false;
public int score = 0;
// Update is called once per frame
void Update()
{
breakableDetection();
}
void breakableDetection()
{
Ray rayLocation = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(rayLocation, out hit, 1000, layerMask))
{
print("Detected");
if (Input.GetKey(KeyCode.Mouse0))
{
breakableObject = GameObject.Find("Breakable");
Destroy(breakableObject);
isObjectDestoryed = true;
score = score +1 ;
}
}
}
}
RespawnBrokenObject script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RespawnBrokenObject : MonoBehaviour
{
private BlockBreakItem BlockBreakItem;
public GameObject breakablePrefab;
// Start is called before the first frame update
void Start()
{
BlockBreakItem = GameObject.FindObjectOfType<BlockBreakItem>();
}
// Update is called once per frame
void Update()
{
if (BlockBreakItem.isObjectDestoryed == true)
{
Invoke("respawnObject", 5.0f);
BlockBreakItem.isObjectDestoryed = false;
}
}
void respawnObject()
{
GameObject tempObjName = Instantiate(breakablePrefab);
tempObjName.name = breakablePrefab.name;
BlockBreakItem.breakableObject = tempObjName;
}
}
I hope the code isn't too messy! Always worried it won't be understood xD
Fortunately it's easy and basic in Unity!
You don't do this:
breakableObject = GameObject.Find("Breakable");
The good news is the cast will tell you what object you hit! Great, eh?
It's basically:
hit.collider.gameObject
You can use hit.collider.gameObject.name in a Debug.Log for convenience.
It's that easy!
Note you then (if you need it) get your component on that object with something like .GetComponent<YourBreakishBlock>()... easy.
Note that you can CHECK if the object hit, is one of the "YourBreakishBlock" objects, by simply checking if that component is present.
Note simply google something like "unity physics raycast out hit, which object was hit ?" for endless examples,
https://forum.unity.com/threads/getting-object-hit-with-raycast.573982/
https://forum.unity.com/threads/changing-properties-of-object-hit-with-raycast.538819/
etc.
--
Make this simple class:
public class ExamplePutThisOnACube: MonoBehavior
{
public void SAYHELLO() { Debug.Log("hello!"); }
}
Now put that on SOME cubes but NOT on OTHER cubes.
In your ray code:
ExamplePutThisOnACube teste =
hit.collider.gameObject.GetComponent<ExamplePutThisOnACube>();
and then check this out:
if (teste != null) { teste.SAYHELLO(); }
Now run the app and try pointing at the various cubes!

Beginner having Problems with Restarting Scenes when Dying in Unity

so I’m trying to create a respawn system as a beginner, and everything seems to be working the first time but the second time it seems to be unbehaving. If anyone knows how to help me, I would appreciate it
LevelControl:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class LevelControl : MonoBehaviour
{
public int index;
public string levelName;
public GameObject GameOverPanel;
public static LevelControl instance;
private void Awake()
{
if (instance == null)
{
DontDestroyOnLoad(gameObject);
instance = GetComponent<LevelControl>();
}
}
void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("Player"))
{
//Loading level with build index
SceneManager.LoadScene(index);
//Loading level with scene name
SceneManager.LoadScene(levelName);
//Restart level
//SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
}
public void LoadLevel1()
{
SceneManager.LoadScene("Game");
}
public GameObject GetGameOverScreen()
{
return GameOverPanel;
}
}
PlayerMovement:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public CharacterController2D controller;
public float runSpeed = 40f;
float horizontalMove = 0f;
bool jump = false;
bool crouch = false;
// Update is called once per frame
void Update()
{
horizontalMove = Input.GetAxisRaw("Horizontal") * runSpeed;
if (Input.GetButtonDown("Jump"))
{
jump = true;
}
if (Input.GetButtonDown("Crouch"))
{
crouch = true;
}
else if (Input.GetButtonUp("Crouch"))
{
crouch = false;
}
}
void FixedUpdate()
{
// Move our character
controller.Move(horizontalMove * Time.fixedDeltaTime, crouch, jump);
jump = false;
//FindObjectOfType<GameManager>().EndGame();
}
void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == "Enemy")
{
//Destroy(FindObjectOfType<CharacterController2D>().gameObject);
GameObject.Find("Player").SetActive(false);
LevelControl.instance.GetGameOverScreen().SetActive(true);
}
}
}
Error In Unity Video: https://imgur.com/a/Sr0YCWk
If your wondering what I'm trying to do, well, when the 2 colliders of the Player and Enemy collide, I want a restart button to pop up, and the Character to get destroyed, and after that restart the level as is.
You didn't provide much but I try to work with what we have.
In LevelController you have
private void Awake()
{
if (instance == null)
{
DontDestroyOnLoad(gameObject);
instance = GetComponent<LevelControl>();
}
}
First of all just use
instance = this;
;)
Then you are doing
LevelControl.instance.GetGameOverScreenn().SetActive(true);
I don't see your setup but probably GetGameOverScreenn might not exist anymore after the Scene reload while the instance still does due to the DontDestroyOnLoad.
Actually, why even use a Singleton here? If you reload the entire scene anyway you could just setup the references once via the Inspector and wouldn't have to worry about them later after scene changes...
Also
GameObject.Find("Player").SetActive(false);
seems odd .. isn't your PlayerController attached to the Player object anyway? You could just use
gameObject.SetActive(false);
Ok, Normally it would be easier just to do this:
if (collision.gameObject.tag == "Enemy")
{
//Destroy(FindObjectOfType<CharacterController2D>().gameObject);
gameObject.SetActive(false);
LevelControl.instance.GetGameOverScreen().SetActive(true);
But this will NOT work if you want to attach the script to any other gameobjects for any reason. If you are then first make a game object variable containing the player, like this:
public GameObject Player = GameObject.Find("Player");
Then say
Player.SetActive(false);
This creates a player gameobject which you can access by calling the variable.

Unity3D Shooter: Using tags to switch level after killing all enemies

I am new to Unity and was trying, after some suggestions, to use tags to know the number of enemies i have in each level and move to the next scene right after eliminating all enemies. This is the script i use on enemy gameobjects. I've also tagged each of them with the "enemy" tag in unity inspector but it still doesn't work when i run the game. After killing all the enemies, it didn´t change to next scene (Success!). Any ideas on what I'm doing wrong? Any other suggestions?
Thanks a lot for the help.
Enemies Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class BadguyScript : MonoBehaviour
{
public GameObject[] enemies;
public int maxHealth;
public int curHealth;
private Animator myAnimator;
private bool isDead;
[SerializeField]
private float DespawnTime = 2.5f;
[SerializeField]
private string DeathAnimHash = "isDead";
void Start()
{
myAnimator = GetComponent<Animator>();
myAnimator.enabled =true;
myAnimator.SetBool (DeathAnimHash ,isDead);
maxHealth = 1;
curHealth = maxHealth;
}
void Update()
{
if (curHealth < 1)
{
isDead = true;
myAnimator.SetBool (DeathAnimHash ,isDead);
Destroy(gameObject,DespawnTime);
}
enemies = GameObject.FindGameObjectsWithTag("enemy"); // Checks if enemies are available with tag "Enemy".
if (enemies.Length == 0)
{
SceneManager.LoadScene("SucessScene"); // Load the scene with name "SucessScene"
}
}
void OnTriggerEnter2D(Collider2D col)
{
if (isDead)
return;
if (col.tag == "bullet")
{
curHealth -= 1;
Destroy(col.gameObject);
}
}
}
I would create a script holder gameobject for this and put a GameManager script inside it. And inside GameManager.cs which should be a singleton class you can have a property like this:
int _enemyNumber;
public int EnemyNumber{
get{
return _enemyNumber;
}
set{
_enemyNumber = value;
}
}
And when you need to change these values, use some functions you will create inside this game controller such as:
public void DecreaseEnemyCount(){
//do the logic here
}
public void SetEnemyCount(){
//do the logic here
}
Also you can find information about creating a singleton class here
You create a list with all enemies, its a good practice, cause you'll gain performance. But you're verifing if enemies.Lenght == 0, what will never occur, because before you are adding the gameObject in the list enemies = GameObject.FindGameObjectsWithTag("enemy");
In the start method, you can search for all enemies and add then in your array, and in the update or onTriggerEnter you remove it from your array and validate the array lenght. I think it'll be more easy.
Instead of adding the script to a new gameManager script attached to an empty game object cause now once all enemies are killed the script will not be in work but if added to an empty gameobject it will be working always.

Object is not triggering collider

Hi my problem is in Unity, I am a beginner in c#, my gameObject is not triggering the collider that is set on the plane of the game, in order for it to reset it's position.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BasketballSpawnScript : MonoBehaviour
{
public Transform respawnPoint;
void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag("Basketball"))
{
other.gameObject.transform.position = respawnPoint.position;
}
}
}
This script is attached to the plane and the gameobject is tagged with Basketball, when it enters the collider of the floor it should transform it's position to the original position.
I cannot see what is wrong, can I receive some help?
P.S I get this error when other gameobject go through the collider too.
NullReferenceException: Object reference not set to an instance of an object
If using a Transform for spawn point, remember to set the value of it in the inspector menu.
public Transform respawnPoint;
void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Basketball"))
other.transform.position = respawnPoint.position;
}
else
public Vector3 respawnPoint = Vector3.zero;
void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Basketball"))
other.transform.position = respawnPoint;
}
private void OnTriggerEnter(Collider other){
if(other.gameobject.tag=="Basketball"){
other.gameobject.transform.position = respawnPoint;
}
}
I hope it helps you.

Categories