How do I properly make an IgnoreCollision command? - c#

I have the code to where is resets when my main object hits another object. However it hits every single object and resets the scene. I'm attempting to make my main abject ignore a certain object. Here is what I have so far.
void OnCollisionEnter(Collision collision)
{
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
if (collision.gameObject.tag == "BlueLaunchpad")
{
Physics.IgnoreCollision(BlueLaunchpad.collider);
}
}
}

i think you should try something like thins:
void OnCollisionEnter(Collider collider )
{
if (collider.gameObject.tag == "BlueLaunchpad")
{
Physics.IgnoreCollision(collider);
}
else
{
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
}
this way it shouldn't load the scene when it hits the BlueLaunchpad

Related

If enemy alive shoot if not then stop but it is not what it is doing

So what I'm doing is doing a pvz game but the objects is constantly firing so I implemented collision when the enemy is collided it will fire and stop when it is not so here is the code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class attackRange : MonoBehaviour
{
public towerAttacker towerAttacker;
void OnTriggerEnter2D(Collider2D collision)
{
if (collision.tag == "enemyCollider")
{
towerAttacker.shootStart();
// It will detect once but once too many enemies are present it only counts as 1
}
}
void OnTriggerStay2D(Collider2D collision)
{
if (collision.tag == "enemyCollider")
{
towerAttacker.shootStart();
// It detects constantly but makes the object go into rapid fire mode
}
}
void OnTriggerExit2D(Collider2D collision)
{
if (collision.tag == "enemyCollider")
{
towerAttacker.StopAllCoroutines();
// Stop when there is no collision detected
}
}
}
It works perfectly on one object but screws on many objects
I'm think I know what's going on here. you might want to keep a list of existing enemies inside your range.
The issue I'm seeing is running "StopAllCoroutines()" when a collision ends might be messing up your logic, because it stops listening for all the other collisions.
That OnTriggerExit2D should get executed when 1 collision ends, so you are stopping everything when the first enemy dissapears.
So what I believe you want to try is something like this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class attackRange : MonoBehaviour
{
public towerAttacker towerAttacker;
private List<string> activeEnemies = new List<string>();
void OnTriggerEnter2D(Collider2D collision)
{
if (collision.tag == "enemyCollider")
{
// You might want to make sure there is no existing element with this name
activeEnemies.Add(collision.gameObject.name);
towerAttacker.shootStart();
// It will detect once but once too many enemies are present it only counts as 1
}
}
void OnTriggerStay2D(Collider2D collision)
{
if (collision.tag == "enemyCollider")
{
towerAttacker.shootStart();
// It detects constantly but makes the object go into rapid fire mode
}
}
void OnTriggerExit2D(Collider2D collision)
{
if (collision.tag == "enemyCollider")
{
// Again, you might want to have some validation to make sure that string exists.
activeEnemies.Remove(collision.gameObject.name);
if(activeEnemies.Count() == 0) {
// Stop when there is no collision detected
towerAttacker.StopAllCoroutines();
towerAttacker.shootStop();
}
// UPDATED to comment this line
//towerAttacker.StopAllCoroutines();
}
}
}
UPDATE
To make sure your attacker does not fire twice, you should update the towerAttacker class and the shootStart method.
And you'll need a new shootStop method, to reset that flag.
public class towerAttacker
{
public bool isAttacking = false;
void shootStart ()
{
if (!isAttacking)
{
// Do whatever your doing now
...
this.isAtacking = true;
}
}
void shootStop() {
this.isAttacking = false;
}
}

Function OnCollisionEnter is not working properly

I've written code for destroying the player if it collides with an obstacle. But I get the error
The local function 'OnCollisionEnter' is declared but never used
My Code:
void Update()
{
void OnCollisionEnter(Collision col)
{
if (col.gameObject.tag = "Player")
{
Destroy(col.gameObject);
}
}
}
Your code should look like this:
void Update()
{
}
void OnCollisionEnter(Collision col)
{
if (col.gameObject.tag = "Player")
{
Destroy(col.gameObject);
}
}
You can theoretically define a function in your Update Method, they are called Local Functions.
But you can't do that with Unitys prepgroammed Functions eg. Start(), Update(), OnTriggerEnter(), OnCollisioEnter().
What you need to do instead, is take out your OnCollisionEnter() Function from the locally defined Update scope and instead place it into the MonoBehaviour Scope.
Example:
private void Update() {
}
private void OnCollisionEnter(Collision col) {
// Use CompareTag to get Error Message,
// when the Tag doesn't exist in the Scene
if (col.gameObject.CompareTag("Player")) {
Destroy(col.gameObject);
}
}
Unrelated:
I would also generally advise you to use CompareTag() instead of gameObjec.tag == "". Because CompareTag will throw an Error if there is no such Tag in your Scene and is therefore pretty usefull when you made a typo with the name of the Tag.

How to check if i`m touching something in Unity

I've got OnCollisionEnter2D function, but it say's only once, when i`m landing on ground, i want function that will return object name(or smthng like this) if i'm touching it, so if i'll stay on it it will say me about it not only once but every frame.
It's as simple as using the correct method OnCollisionStay2D which is called every frame while you are colliding with another object
Sent each frame where a collider on another object is touching this object's collider (2D physics only).
To be fair: Their example in that link is bullshit since it is for OnTriggerStay2D ^^
It could look like
private void OnCollisionStay2D(Collision2D collision)
{
Debug.Log($"I am touching {collision.gameObject.name}", this);
}
If instead you want to keep track of every touching object I would rather use something like
private HashSet<GameObject> _currentlyTouching = new HashSet<GameObject>();
private void OnCollisionEnter2D(Collision2D collision)
{
if(!_currentlyTouching.Contains(collision.gameObject))
{
_currentlyTouching.Add(collision.gameObject);
}
}
private void OnCollisionExit2D(Collision2D collision)
{
if(_currentlyTouching.Contains(collision.gameObject))
{
_currentlyTouching.Remove(collision.gameObject);
}
}
private void Update()
{
var logString = new StringBuilder("I am touching ");
foreach(var touchingObject in _currentlyTouching)
{
logString.Append(touchingObject.name).Append(" ");
}
Debug.Log(logString.ToString(), this);
}

OnCollisionExit is not being called

Why is OnCollisionExit not being called? I am using both OnCollisionEnter and OnCollisionExit but unfortunately only OnCollisionEnter is being called.
public bool HandleCollided = false;
public void OnCollisionEnter(Collision col)
{
if(col.gameObject.name == "RightHandAnchor")
{
HandleCollided = true;
}
}
public void OnCollisionExit(Collision col)
{
if(col.gameObject.name == "RightHandAnchor")
{
HandleCollided = false;
}
}
It's impossible to tell why your code isn't working based the given snippet - this code depends on the configuration of each of the GameObjects' inspector windows in the editor.
Both the GameObject that this script is attached to and the colliding GameObject must have one Collider component attached to each of them (for example, a BoxCollider component or a SphereCollider component). Both Colliders must have their isTrigger checkboxes disabled. The GameObject that this script is attached to must also have a Rigidbody component attached.
In order to debug this situation, add Debug.Log() statements in your functions. This is generally good practice, and it might be that the function is being called but the conditional statement is not true.
Here are some additional ideas on what might be going wrong:
You may be changing the name of the colliding GameObject somewhere else in your code.
You may be destroying the GameObject.
It might be that neither function was being called and HandleCollided was being changed elsewhere in your code.
It might be that the parameter, col, is not what you expect.
public void OnCollisionEnter(Collision col)
{
Debug.Log("Collision Enter!");
Debug.Log(col.gameObject.name);
}
public void OnCollisionExit(Collision col)
{
Debug.Log("Collision Exit!");
Debug.Log(col.gameObject.name);
}
So you said "There are two objects that collides with each other. One has sphere collider attached to it and another has box collider. One of the objects have rigidbody attached as well." On which one is the code? and yes this matters! only 1 of the objects will keep track of the exit meaning that if it's the non-kinematic it will not work.
Unfortunately using OnCollisionExit did not work so instead I used OnTriggerEnter and OnTriggerExit. I activated "isTrigger" for both objects.
public void OnTriggerEnter(Collider col)
{
Debug.Log("entered");
if (col.gameObject.name == "RightHandAnchor")
{
HandleCollided = true;
}
}
public void OnTriggerExit(Collider other)
{
Debug.Log("exit");
if (other.gameObject.name == "RightHandAnchor")
{
print("No longer in contact with " + other.transform.name);
HandleCollided = false;
}
}
You need a non-kinematic rigidbody attached to your object to get the event for OnCollisionExit
Try to use OnCollisionEnter() and OnTriggerExit() !!
Example:
void OnCollisionEnter(Collision collision)
{
if((collision.gameObject.GetComponent<AttributeManager>().attributes & doorType) != 0)
{
this.GetComponent<BoxCollider>().isTrigger = true;
}
}
private void OnTriggerExit(Collider other)
{
this.GetComponent<BoxCollider>().isTrigger = false;
}

Repeat function (unity3d/c#)

First of all, here's the code:
using UnityEngine;
using System.Collections;
namespace UltimateSurvival
{
public class Radiation : MonoBehaviour
{
public GameObject radiationEffect;
public EntityVitals Vitals { get { return m_Vitals; } }
private EntityVitals m_Vitals;
// Use this for initialization
void Start() {
InvokeRepeating ("OnTriggerEnter", 1.5f, 3.5f);
}
// Update is called once per frame
void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Player")
{
radiationEffect.SetActive(true);
//yield return new WaitForSeconds(5);
var entity = other.GetComponent<EntityEventHandler>();
if(entity)
{
var healthEventData = new HealthEventData(-Random.Range(7.0f, 23.0f));
entity.ChangeHealth.Try(healthEventData);
}
//yield return new WaitForSeconds(5);
}
}
void OnTriggerExit(Collider other)
{
if (other.gameObject.tag == "Player")
{
radiationEffect.SetActive(false);
}
}
}
}
What I'm trying to do is that I want this script to execute OnTriggerEnter every 3.5 seconds. As you can see, I'm using InvokeRepeating but it seems like it doesnt work. I've also tried changing void OnTriggerEnter on IENumerator OntriggerEnter and then yield return new WaitForSeconds(5); - It didn't work either. I'm really confused D: Please help!
It seems you're trying to solve the problem of draining HP from the player if player is inside the area of radiation. This is a solution that will use most of your current code, but is not neccesarily the best code. I'd also like to inform you of OnTriggerStay, which
is called once per frame for every Collider other that is touching the trigger.
and can also be used to solve this problem. I'm going to use your already declared OnTriggerEnter and OnTriggerExit to damage every player inside area every 3.5 seconds.
public GameObject radiationEffect;
public EntityVitals Vitals { get { return m_Vitals; } }
private EntityVitals m_Vitals;
// Declare a list that will contain the players.
List<GameObject> playersInArea = new List<GameObject>();
// Use this for initialization
void Start() {
InvokeRepeating ("DamagePlayers", 1.5f, 3.5f);
}
void DamagePlayers() {
foreach (var player in playersInArea) {
var entity = player.GetComponent<EntityEventHandler>();
if(entity)
{
var healthEventData = new HealthEventData(-Random.Range(7.0f, 23.0f));
entity.ChangeHealth.Try(healthEventData);
}
}
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Player")
{
playersInArea.Add(other.gameObject);
radiationEffect.SetActive(true);
}
}
void OnTriggerExit(Collider other)
{
if (other.gameObject.tag == "Player")
{
playersInArea.Remove(other.gameObject);
if (playersInArea.Count == 0) {
radiationEffect.SetActive(false);
}
}
}
Something like that should work. If you only have 1 player it should work all the same, but this supports multiple players. Let me know if you have any further issues.
You have problems calling your method using InvokeRepeating because of two reasons:
InvokeRepeating can not be used with method that have parameters: you probably have the Trying to Invoke method: [...] couldn't be called. message in your console.
OnTriggerEnter is a method that is automatically called by Unity when the gameobject's collider is set as Trigger and another collider enters it: as #Hellium said, calling such methods manually is a bad idea (same as calling Start or Update manually: this can happen but really doesn't make sense in most of the scenarios).
Hope this helps,

Categories