0

I'm having difficulty with OnCollisionEnter while making a dodgeball game, so is there any way I can make the player lose lives/points when it's hit with a ball with a specific color?

What I've tried:

The script on the player:

    void Start () {
    livesText = GameObject.FindWithTag("lives").GetComponent<Text>();
    lives = 4;

}

// Update is called once per frame
void Update () {

    livesText.text = "Lives: " + lives;
}

void OnCollisionEnter(Collision bol)
{
     if (bol.gameObject.name == "blueBall")
    {

      lives = lives - 1;

      Debug.Log("Collided");

      }


}

enter image description here

enter image description here

Player prefab: The highlighted portion is the actual physical body of the player:

enter image description here

BREAKDOWN of the player prefab:

PLAYER1:

enter image description here

FPSController:

enter image description here

FirstPersonCharacter:

enter image description here

CAPSULE:

enter image description here

halfer
  • 19,824
  • 17
  • 99
  • 186
  • provide what you've tried. – Ousmane D. Mar 22 '17 at 23:30
  • 2
    You can access the "GameObject whose collider we are colliding with" through the [collision](https://docs.unity3d.com/ScriptReference/Collision.html) parameter of the [method](https://docs.unity3d.com/ScriptReference/MonoBehaviour.OnCollisionEnter.html) and that will get you towards your goal. Keep in mind that you probably shouldn't probably tie your game logic to the actual _color_ of the ball (because of low maintainability of such solution) - use tags instead, for example. – apk Mar 22 '17 at 23:34
  • @OusmaneMahyDiaw I've edited my question and provided what I tried. – Juan Francisco Patino Mar 22 '17 at 23:36
  • @apk I just tried using 'if(col.gameObject.tag == "player")' on the ball and I am still getting no collision detection. I edited and put what I previously tried before in my question. – Juan Francisco Patino Mar 22 '17 at 23:42

1 Answers1

2

You can do this in two ways depending on if the color is generated during game-play or color that already exist is used.

Method 1:

Create a tag for each color then make sure that each object has it's tag assigned in the Editor. Use CompareTag to compare which color it collided with.

Here is a quick tutorial on how to create tags.

void OnCollisionEnter(Collision bol)
{
    if (bol.gameObject.CompareTag("blueBall"))
    {
        lives = lives - 1;
        Debug.Log("Collided red");
    }
    else if (bol.gameObject.CompareTag("greenBall"))
    {
        lives = lives - 2;
        Debug.Log("Collided green");
    }

    else if (bol.gameObject.CompareTag("blackBall"))
    {
        lives = lives - 3;
        Debug.Log("Collided black");
    }
}

Method 2:

Now, if you are doing something advanced that you have to generate color in run-time, you have to check the threshold of the color. There is a question about this here and I ported the code for Unity.

public double ColourDistance(Color32 c1, Color32 c2)
{
    double rmean = (c1.r + c2.r) / 2;
    int r = c1.r - c2.r;
    int g = c1.g - c2.g;
    int b = c1.b - c2.b;
    double weightR = 2 + rmean / 256;
    double weightG = 4.0;
    double weightB = 2 + (255 - rmean) / 256;
    return System.Math.Sqrt(weightR * r * r + weightG * g * g + weightB * b * b);
}

Then do something like this in the collision callback function:

void OnCollisionEnter(Collision bol)
{
    MeshRenderer ballMesh = bol.gameObject.GetComponent<MeshRenderer>();

    if (ColourDistance((Color32)ballMesh.sharedMaterial.color, (Color32)Color.red) < 300)
    {
        lives = lives - 1;
        Debug.Log("Collided red");
    }
    else if (ColourDistance((Color32)ballMesh.sharedMaterial.color, (Color32)Color.green) < 300)
    {
        lives = lives - 2;
        Debug.Log("Collided green");
    }

    else if (ColourDistance((Color32)ballMesh.sharedMaterial.color, (Color32)Color.black) < 300)
    {
        lives = lives - 3;
        Debug.Log("Collided black");
    }
}

EDIT:

The OnCollisionEnter function is not being called because you are using the First Person Controller.

In this case, you must use the OnControllerColliderHit function.

void OnControllerColliderHit(ControllerColliderHit bol)
{

}

everything in the function remains the-same.

Community
  • 1
  • 1
Programmer
  • 121,791
  • 22
  • 236
  • 328
  • I just tried the '(bol.gameObject.CompareTag("blueBall")' method of doing this and I am still getting no collision detection. I'll try checking the threshold of the color now. – Juan Francisco Patino Mar 22 '17 at 23:50
  • Hi, please watch the video I linked for how to create tags. You did not do that right. After creating the tags, you have to **select each object** with different color and **change their tags**. Make sure to change their tags from the Editor. Watch that video completely. Also, make sure that the tag name matches with the tags in the code. This should work out of the box. Also, I have added complete information on how to use the threshold if you want to go that route. Check it out. – Programmer Mar 23 '17 at 00:00
  • Hi @Programmer, I understand that this should work, and I did change the tag of the (blue)ball (I only have one ball at the moment) in the editor... but I attached a screenshot of the player prefab and I think there is definitely a problem with how I structured the player, because not a single collision detection method is working with it. I will provide more details by editing the question after I post this comment. – Juan Francisco Patino Mar 23 '17 at 00:06
  • The screenshot of your ball shows that you did **not** change the tag. Please change the tag then update the screenshot. – Programmer Mar 23 '17 at 00:10
  • I'm Sorry, I forgot to mention that in the start function of the ball, I set 'gameObject.tag = "active"', so that it starts off as active then turns to 'Untagged' when it touches the ground. So during runtime the ball's tag does change and the script still doesn't work. I also just inserted a breakdown of the Player Prefab in my question if that helps. Sorry if this is really complicated and thank you for your time so far. – Juan Francisco Patino Mar 23 '17 at 00:14
  • "So during runtime the ball's tag does change and the script still doesn't work" Changes to what tag name? – Programmer Mar 23 '17 at 00:16
  • Basically, it starts off with the tag 'active' and if it touches the ground it turns to 'untagged'. Currently I am keeping the ball in the air when I'm testing the collision so that I can keep the tag as 'active'. – Juan Francisco Patino Mar 23 '17 at 00:18
  • No. After it lands, Change it to one of the tags in my code....`blueBall`, `greenBall` or `blackBall`. This is an answer that should work on first try. I really don't know what you are doing. `gameObject.tag = "blueBall"`. – Programmer Mar 23 '17 at 00:21
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/138775/discussion-between-juan-francisco-patino-and-programmer). – Juan Francisco Patino Mar 23 '17 at 00:22
  • I can't chat at this time. I will be back after. – Programmer Mar 23 '17 at 00:24