I am using unity 5 c# and I have a gameobject with 2 trigger colliders one of them is in a different location.
I need to be able to use OnTriggerStay2D and OnTriggerEnter2D for them but I need to find what trigger is being entered. Right now if I enter the 1st(polygon) trigger the OnTriggerEnter activates for the 2nd(box).
How can I Tell the two colliders apart???
public void OnTriggerEnter2D(Collider2D other) //2nd collider trigger
{
if (other.tag == "Player") {
Found = true; //if the player is in shooting range
Idle = false;
}
}
public void OnTriggerStay2D(Collider2D other) //1st collider trigger
{
if (Found != true) {
if (other.tag == "Player") {
Shield = true;
Idle = false;
}
}
}
public void OnTriggerExit2D(Collider2D other) //2nd collider trigger
{
if (other.tag == "Player") {
Found = false;
Shield = false;
Shooting = false;
Idle = true;
}
}
I have tried making the 1st trigger public void OnTriggerStay2D(PolygonCollider2D other) but it says "This message parameter has to be of type: Collider2D
The message will be ignored."
What I am trying to do is have a polygon trigger in front of the gameobject and a different box trigger closer to the gameobject so when you go near the gameobject you enter the 1st trigger and it puts its shield up but when you get close to it (within shooting range of it) it will put its shield down and start shooting you.
Well collider2d detects all types of 2d colliders. It doesn't matter if it's polygon or just a box. As the documentation suggestions it doesn't need to be public or private. It only takes a collider2d as it's argument however.
For debugging purposes why not use print?
Print("you've entered the trigger function");
Also I wouldn't use 2 different trigger colliders on the same GameObject. Why not just make 2 separate gameobjects so you can have more thorough detection. Each GameObject with its own trigger collider can have different tags.
If you have to use 2 trigger colliders on one object. Which isn't the best idea. You could use shapeCount to determine which one it's hitting. Although like I said I would warrant against doing 2 trigger colliders on the same object when whatever you're trying to do can be easier on two separate objects.
However links aren't usually prohibited I think. I would watch and study these videos. They're very useful for explaining the engine and they really aren't even that long.
https://unity3d.com/learn/tutorials/modules/beginner/2d
They even have a video explaining 2d colliders.
This is my fix. In one of my games I have a boulder, I have a trigger which will delete a block below it so it falls, I then have another trigger which tells the boulder to start moving left or right I then also have another trigger which will delete the boulder once the boulder comes in contact.
So what you can do is create 2 new game objects, create a new CS file and name them appropriately, then with those two new classes allow them to take in the gameobject you are referring to in your question.
Then when they are triggered you can use code from their class.
So your first class would become something like this
public void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "Player") {
Enemy.Found = true; //if the player is in shooting range
Enemy.Idle = false;
}
}
public void OnTriggerExit2D(Collider2D other)
{
if (other.tag == "Player") {
Enemy.Exit2DTrigger();
}
}
Then the other class would be something like this
public void OnTriggerStay2D(Collider2D other)
{
if (Enemy.Found != true) {
if (other.tag == "Player") {
Enemy.Shield = true;
IEnemy.dle = false;
}
}
}
public void OnTriggerExit2D(Collider2D other)
{
if (other.tag == "Player") {
Enemy.Exit2DTrigger();
}
}
Then in your Enemy class you would have
public void Exit2DTrigger()
{
Found = false;
Shield = false;
Shooting = false;
Idle = true;
}
P.S. also don't you need to use other.gameObject.tag == "Player" ?
Related
here is my code for the trigger
`
private AudioSource finishSound;
private bool levelCompleted = false; //play the audio once
void Start()
{
finishSound = GetComponent<AudioSource>();
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.name == "Player1" && !levelCompleted)
{
CompleteLevel();
levelCompleted = true;
Invoke("CompleteLevel", 1.5f); //delay finish
}
}
private void CompleteLevel()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1);
}
}`
I know this code is only for one Player. How do I do it requiring 2 players at the door to finish the level?
An approach for this would be to cache the players and check against the total count. To see if it's a player, I'd advice to use tags instead of using the name of the object for a lot of reasons. I assume, the tag "Player" is used to identify the player.
List<GameObject> players = new List<GameObject>();
private void OnTriggerEnter2D(Collider2D collision)
{
// Add a new player if they enter the trigger
if (collision.gameObject.CompareTag("Player") && !players.Contains(collision.gameObject))
{
players.Add(collision.gameObject);
}
// Both players are in the trigger
if (players.Count == 2 && !levelCompleted)
{
CompleteLevel();
levelCompleted = true;
Invoke("CompleteLevel", 1.5f); //delay finish
}
}
private void OnTriggerExit2D(Collider2D collision)
{
// Remove a player if they leave the trigger again
if (collision.gameObject.CompareTag("Player") && players.Contains(collision.gameObject))
{
players.Remove(collision.gameObject);
}
}
If you have a varying count of players, you probably don't want to hard code the amount of players in a trigger. You should have a total count somewhere to check against. A game manager of sorts, that tracks the expected amount of players.
One way would be to create flags for each player, not one. When player one enters the trigger, you set playerOneCompleted = true. Then, you check if second player also completed. If that's the case finish the game if not, do nothing.
What you would need to add is the method OnTriggerExit2D to set flags of respective players to false when they exit the area.
Since the code you presented is inside the player, I would advise moving it to the door's trigger, so you can reference both players more easily.
So I am taking a class in basic game development and am currently working on a game with Unity. My game worked perfectly up until now when I updated my unity version. In order for the player to actually take damage I have a method that can only be reached if explicitly called by a script. Somehow the ground, that has no script attached, damages my player.
I have posted the code below.
This one is part of the player script
3 references
public void Hurt(int dmg, string yep)
{
HP -= dmg;
Debug.Log($"took {dmg} damage from{yep}. You now have {HP} HP left");
if (HP <= 0)
{
SceneManagement.Death();
}
}
This one is part of the script attatched to my flame object
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag != "FlameTurret" && collision.gameObject.tag != "flame")
{
player.GetComponent<PlayerController>().Hurt(damage, collision.gameObject.tag);
Destroy(this.gameObject);
}
}
This one is attatched to a projectile fired by the enemy
if (collision.gameObject.CompareTag("Player"))
{
if (!called)
{
collision.gameObject.GetComponent<PlayerController>().Hurt(damage, collision.gameObject.tag);
called = true;
}
}
This one is attatched to an enemy
if (collision.gameObject.CompareTag("Player"))
{
if (!called)
{
collision.gameObject.GetComponent<PlayerController>().Hurt(damage, collision.gameObject.tag);
called = true;
}
Destroy(this.gameObject);
}
Console output
Nothing with the tag "Ground" has a script and nothing else than the methods i've posted are supposed to reference my Hurt() method but the ground still damages my player. Any help would be greatly appreciated!
Your problem seems to be that this function here
private void OnCollisionEnter2D(Collision2D collision)
Will be run whenever any collider (game object with a collider component attached - the game object does not need to have any scripts attached to it) intersects with your player
This code here
if (collision.gameObject.tag != "FlameTurret" && collision.gameObject.tag != "flame")
Will pass so long as the object that collides does not have the tag of "FlameTurret" or "flame", which I assume your ground does not.
It seems to me a little odd that everything in your game will damage your player except for flames... is this an error?
Either way a simple fix would be to tag your ground with something like environment and then add under your OnCollisionEnter2D() have a check along the lines of
if (collision.gameObject.tag == "environment"){
return; // do nothing
}
I need to be able to detect if 2 separate object are touching each other. I have no idea if there is a specific piece of code to do this.
so i made some code that detects if the object the code is attached to is touching something but i don't know how to make it detect if 2 objects with different tags are touching
void OnCollisionEnter(Collision other)
{
if (other.gameObject.tag == "Rocket")
{
istouchingrocket = true;
}
if (other.gameObject.tag == "Ground3")
{
Isend = true; //Ground three is the ending platform. This piece of code is attached to oil which is not touching this. I need to detect if the player is touching "Ground3".
}
}
void OnCollisionExit(Collision other)
{
if (other.gameObject.tag == "Rocket")
{
istouchingrocket = false;
}
}
So the code is attached to the oil and when the player touches "ground3" they gain the ability to destroy the oil. The code needs to detect remotely if 2 separate objects are touching.
It's probably better for the player script to have a field that keeps track of if it has gained the ability to destroy oil:
public bool canDestroyOil;
Be sure to set it to false in Start():
canDestroyOil=false;
Then when player detects if it touches "ground3" then set it to true:
canDestroyOil = true;
And then in the oil script, when it touches player it destroys itself if the player can destroy oil:
if (player.canDestroyOil) {
gameObject.Destroy();
}
Take a look at IsTouching() function.
It does exactly what you're asking.
I have previously asked about this question, and whilst doing some debugging, I have finally found the issue with my code, however I'm not sure how to go about fixing it.
I have created a spawn system that spawns cyclists and instantly begin to cycle them forwards, I have 1 script that makes each cyclist move forwards, and another that makes them stop and continue off when another player or cyclist is in front of it, THIS is the script that has the issue.
To quickly summarise, whenever a cyclist(a) is stopped by a player, and another cyclist(b) get stopped by the cyclist in front, a boolean triggers which turns playerInside and cyclistInside to true. This is fine. However once the player moves out the way, the first cyclist(a) has playerInside set to false, which is correct, but cyclistInside is still set to true. This is because the cyclist behind him is still detecting the one in front. So it doesn't seem like the scripts are working independently for each cyclist.
I've spent some time debugging to really find the issue here, and this is what I've found.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class cyclistStoping : MonoBehaviour
{
public VehicleMove cyclistMovement;
public Animator CycleAnims;
// bools
public bool playerInside;
public bool cyclistInside;
private void Start()
{
playerInside = false;
cyclistInside = false;
}
// implement delay
private void Update()
{
if (playerInside == false && cyclistInside == false)
{
StartCoroutine(timeDelay());
}
}
// player or cyclist (INSIDE)
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Player" ) {
playerInside = true;
cyclistMovement.vehicleMovement = 0.0f;
}
else if (other.gameObject.tag == "Cyclist")
{
cyclistInside = true;
cyclistMovement.vehicleMovement = 0.0f;
}
}
private void OnTriggerExit(Collider other)
{
if (other.gameObject.tag == "Player")
{
playerInside = false;
}
else if (other.gameObject.tag == "Cyclist")
{
cyclistInside = false;
}
}
IEnumerator timeDelay()
{
// wait before moving off
yield return new WaitForSeconds(2);
if (playerInside == false && cyclistInside == false)
{
cyclistMovement.vehicleMovement = 0.1f;
StopAllCoroutines();
}
}
}
At this point, once the player moves away from the cyclist, the first cyclist (and the ones waiting behind) won't move off, because they are waiting for the first cyclist to move, which won't move due to the cyclistInside being set to true even though there's no cyclist infront.
I expect the cyclist to move off once the player is no longer in front of it, and so fourth with the rest of them.
In the game you controll a ball (Sphere) and two types of boxes falling down: deathCube and goldCube. When the Sphere hit the DeathCube, then the Sphere is destroyt, but it not get destroyed and I don't know why. The cubes are prefabs and they have a tag(DeathCube, GoldCube).
void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "DeathCube")
{
Destroy (gameObject);
}
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "GoldCube")
{
gold++;
}
}
If the Sphere hit the goldCube you get points, but this doesn't work too.
Try merging the two OnTriggerEnter's into one.
void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "DeathCube")
{
Destroy (gameObject);
}
if (other.gameObject.tag == "GoldCube")
{
gold++;
}
}
I believe that the second one is overriding the first, never allowing the Destroy() to be called. I would've assumed the compiler would throw an error with this, but you don't seem to have indicated that.
If you don't have a rigidbody attached to at least one of the objects in the collision (ball or cube), then the trigger event won't be initiated.
From the documentation:
Notes: Trigger events are only sent if one of the colliders also has a rigidbody attached
Source: https://docs.unity3d.com/ScriptReference/MonoBehaviour.OnTriggerEnter.html