I am trying to make a scoring system for a game that I am making; it's a remake of Flappy Bird.
The issue I am having is, I have set up a sprite with a rigidbody2d and a box collider as the score; I am trying to make it so that when the character passes through that sprite; it will add one to the score however when the character attempts to go through it, it just get's pushed back to the other side of the screen.
This is because of the box collider of course but I am not sure of any other way of doing this without this method. Here is the code which detects if the character hits the pipe or the score line:
void OnCollisionEnter2D (Collision2D hit) {
if(hit.transform.gameObject.name == "Pipe(Clone)") {
die();
Debug.Log("hit");
}
if (hit.transform.gameObject.name == "Score(Clone)") {
Debug.Log("Score");
}
}
Everything logs perfectly fine however the problem is that the bird just faceplants into the score line which isn't what is supposed to happen, please try to help or advise what I should do with this.
P.S. I am a novice programmer; I sort of know what I am doing however not really good at debugging things and fixing them, Thank you.
You should check the "Is Trigger" on your Bird object collider in editor. And use:
void OnTriggerEnter2D(Collider2D col) {
if (col.transform.name == "Score")
Score++;
}
In the bird object script.
Related
i have a trouble with a collision, i know this is not the way to do "bullets" , but for now im very new and I'm exploring and trying some stuff. I have in my little "bullet" a script with the "onCollisionEnter" function, but when i shoot to make the cube dissapear I have to take 2 shots(two fasts) instead one to that occur, and i do not understand why.
my code says:
void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.name == "Cube")
{
Destroy(collision.gameObject);
}
Debug.Log(this.gameObject.name);
}
VIDEO
THANKS!
Here two things you need to check for the collision to work properly in Unity3D.
1. The two objects that are being collided in your case the bullet and the cube that the bullet is gonna collide with should have a collider (box or capsule) anything. And make sure isTrigger is off.
2. This is very important. Either one of the gameObject i.e., your bullet or the cube should have rigidbody component for collision to actually take place. If you dont have a rigidbody in the one of the components your collision wont work. So, I would suggest you to add rigidbody component to your bullet and that should do the magic for you.
Let me know if these worked or if you have any other problem.
And to which gameObject have you attached the following script to?
So I'm attempting to create a 2D game in Unity where the gameObjects would be destroyed upon hitting the walls. So i decided to use the isTrigger function and add the script to each of the walls. However, I do not know why the gameObjects don't get destroyed. I have tried to set Collision type as both discrete and continuous for the walls and gameobjects and I've also added static rigidbodys to the walls to see if that would help and even tried changing the size of the collisionbodys of the walls.
Here is the code for the wallscript
public class wallScript : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
public void OnTrigger2D(Collider2D other)
{
if (other.tag == "player01")
{
Destroy(other.gameObject);
}
}}
p.s. Even if I remove the conditional statement Destroy() still does not work
You should use void OnCollisionEnter2D(Collision2D other) {...} instead of void OnTrigger2D(Collider2D other).
And uncheck Is Trigger checkbox on your object's Collider.
To Fix The Problem You Are Facing, First Select The Wall Sprite In The Scene, Scroll Down To The Collider And Make Sure Is Trigger Is Checked.
Other Than That Just Check If The Tag You Typed Into The Code Matches The Player You Are Trying To Destroy. Remember, It's Case Sensitive!
After That The Code Should Run Just Fine.
I have an animated sprite which has 8 frames of animation. Each frame has a PolygonCollider2D attached as an element of an array thus providing it with accurate collision detection no matter which frame is playing.
When I had only one collider on the sprite and it passed through the "score" object the player's score increased by 1 point.
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.tag == "Point")
{
score++;
scoreText.text = score.ToString();
return;
}
}
Polygon Collider 2D array in Unity inspector
Each collider in the array becomes active in turn...
public void SetColliderForSprite(int spriteNum)
{
colliders[batColliderIndex].enabled = false;
batColliderIndex = spriteNum;
colliders[batColliderIndex].enabled = true;
}
Now that each frame of the animation has its own collider I find that the score is increasing at an alarming rate as each frame plays multiple times whilst inside the "score" game object, triggering the point scoring logic multiple times, before the player leaves said object.
I'm wondering what the ideal programmatic solution is in order to ensure that on entering the "point" collider object the player only gets a score increment once before exiting the area?
Thanks in advance for any suggestions (and my apologies if this has been answered elsewhere).
EDIT: I was thinking about my post below and I think there is a simpler solution. You should be able to animate your collider shape rather than having 1 collider per animation frame. For example, see this question on How to update 2d colliders with sprite animation.
(And as a side note, you can also have multiple polygon colliders on each part of the sprite, and animate the colliders to move accordingly. For example, see this post on Animating Polygon Collider 2D. This alternative approach might make the suggestion I make in my post below simpler.)
One suggestion I have is to only increment the score when the first "Point" trigger is detected and then not incrementing the score again until the object has fully left. This can be implemented by keeping track of how many colliders (or which specific colliders) have entered and exited the object. Something like the following:
private const string PointTag = "Point";
private int _triggerCount;
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.tag == PointTag)
{
bool firstCollision = (_triggerCount == 0);
if (firstCollision)
{
score++;
scoreText.text = score.ToString();
}
_triggerCount++;
}
}
private void OnTriggerExit2D(Collider2D collision)
{
if (collision.gameObject.tag == PointTag)
{
_triggerCount--;
}
}
However, once a collision is in progress, you will likely have to change the behaviour so that all colliders stay active until the object has fully left the collision area. This is because if you disable the collider, the OnTriggerExit2D event will not fire.
This solution may not be acceptable depending on how accurately you need to detect that the VampireBat has left the collision area.
If it doesn't need to be very accurate, you can simplify the solution by adding a 9th collider with a unique tag that covers the entire area of the sprite's animation. By using this 9th collider to determine when the player has left the collision area, you would not need to worry about affecting the code related to showing the appropriate collider per animation frame. (But note that the code example here would have to be modified so that the OnTriggerExit2D uses this 9th collider object.)
If it needs to be more accurate, I think there is likely a solution similar to what I suggested based on which colliders are currently active, the details of your collider shapes & animation frames, and OnTrigerEnter2D, OnTriggerStay, and OnTriggerExit2D. But note that you may also need to be careful that a collision is not re-triggered immediately. (For example, the object may have fully left the collision area, but the next animation frame might trigger a collision again immediately.)
Thanks for the response. Your edit got me to thinking about child objects. I added a child collider (with an index value of 9) then checked for a collision with that.
child object in inspector
Referenced the child collider in the collider array.
Collider array in inspector
After that it was just a matter of referencing it in the player controller script.
// Update is called once per frame
void Update () {
//Player input
if (Input.GetMouseButtonDown(0))
{
bat.velocity = new Vector2(0, 4);
//ADD BAT FLAP SOUND LATER!!!
}
scoreText.text = score.ToString();
Debug.Log("SCORE: " + score);
}
//Point increment function
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.tag == "Point" && batColliderIndex == 9)
{
score++;
return;
}
}
I now have pixel perfect collision detection against obstacles and a score which increments correctly.
Thanks again.
What I'm trying to do is when it hits a triggered collider I want it to minus an int, but what unity does is minus it with 3 instead, and I have it attached to the player itself
lifecontroller lves;
public GameObject gm;
CoinScript coins;
// Use this for initialization
void Start () {
gm = GameObject.FindGameObjectWithTag("GM");
coins = gm.GetComponent<CoinScript>();
lves = gm.GetComponent<lifecontroller>();
}
void OnTriggerEnter2D(Collider2D other)
{
if(other.tag == "Evil")
{
lves.lives -= 1;
Debug.Log("U hit it");
}
}
// Update is called once per frame
void Update () {
if(lves.lives == 0)
{
Debug.Log("u died");
}
}
Judging from the screenshot, your script is attached to the Player GameObject multiple times. Select your Player GameObject, and remove the duplicate Script.
Make sure there is only one script attached to it. It is probably attached there 3 times.
This problem can also happen if you are instantiating multiple Player GameObjects during run-time as this will duplicate your script too.
EDIT:
With the updated Image in your comment, the problem is that you have 3 Colliders on your Player. It is true that only one of them is made IsTrigger but this is a problem if the GameObject with the Evil tag is marked as IsTrigger too.
You have 2 options to fix this:
1.Select the GameObjects with the Evil tag and make sure that no Collider attached to it is marked as IsTrigger. Unceheck all IsTrigger properties on the Collider of all Evil tagged GameObjects only. This should fix your problem.
2.Only have one Collider on Player GameObject. Remove the other 2. This again should fix your problem.
The trigger is definitly happening 3 times, your screenshot shows that (there is a 3 on the right since duplicate logs get collapsed).
This might occur because of the collider shape I think (circle). Try using a bool that us set on trigger enter and clear on trigger exit (or even Update should be ok for clearing).
This is what I suggested to debug your problem:
void OnTriggerEnter2D(Collider2D other)
{
if(other.tag == "Evil")
{
lves.lives -= 1;
Debug.Log("U hit it", other.gameObject);
}
}
And by looking at your screenshot you are getting 3 log messages.
Always use don't collapse in console window to see whats happening
I trouble trying to get this to work. here is the problem.
When I spawn I bomb with a collider, it presses my character out of the way, forcing him either in the wall or to a side.
Now my character instantiates a Bomb gameobject with a bomb script.
What I want and my thought process:
I was thinking it might be possible having a triggercollider on the instantiated bomb, and no collider, but when my character "leaves" the bomb radius it spawn a regular collider.
Then He can't get stuck, and when he has exited he can't just past through it again.
But I don't know how to write this, any suggestions?
Or any better ideas? Thanks for all help :)
ps: ( I use c#)
You almost get a solution.
1. in bomb collider check trigger;
2. in bomb script at start get reference to collider
3. in OnTriggerExit set isTrigger to false
public class bomb : MonoBehaviour {
BoxCollider collider;
void Start () {
collider = gameObject.GetComponent<BoxCollider> ();
}
void OnTriggerExit(Collider other)
{
collider.isTrigger = false;
}
}
P.S. don't mix 3d and 2d colliders. Code sample for 3d, in 2d it slightly different.