Why does getting an int from an event function require ":"?

I’ve been brushing up on my programming skills and thought I’d get a proper bullet script working but I’m quite baffled as to how some aspects of the code work and I wonder if it’s because things have been changed in the recent updates because the examples I have been reading don’t work like this. Either that or I’ve messed up somewhere with my syntax as usual and just haven’t written it up in a way the engine likes.

So the concept is very simple, here’s the EnemyHealth script.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EnemyHealth : MonoBehaviour {

    public int currentHealth = 100;
  
    // Update is called once per frame
    void Update () {

        if ( currentHealth == 0 )

        {
            Destroy (gameObject);
        }
      
    }

    public void TakeDamage ( int damageAmount )

    {
        currentHealth -= damageAmount;
    }


}

My plasma shot script then takes away some health from the enemy, the plasma itself being a custom particle shader I made attached to an empty.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlasmaShotTakeHealth : MonoBehaviour {
  

    void Start ()

    {

      
    }


    void OnCollisionEnter ( Collision col )

    {
        if ( col.gameObject.tag == "Enemy" )

        {
            col.gameObject.GetComponent<EnemyHealth>().TakeDamage(damageAmount : 10);
        }
    }





}

It took some working out, but for whatever reason I have to have an integer next to my damage amount integer, here in the line of code as you can see.

col.gameObject.GetComponent<EnemyHealth>().TakeDamage(damageAmount : 10);

However why is this the case? Shouldn’t the integer already be declared and taking the number that is shown in the variable belonging to the EnemyHealth script? All the examples I’ve seen show TakeDamage (damageAmount) without any numbers being needed but for some reason Unity insists I have to have a number after “:” to make it all work.

The colon is used for named parameters from C# 4.0 onwards, which basically allows you to re-order the actual arguments.
You should be able to pass a literal to it, or any other type-compatible variable (i.e. of type that can be casted (explicitly/implicitly) to integer) that is accessible in your scope.

If there are examples that do exactly what you’ve described, there should be an actual variable with the name ‘damageAmount’ which is accessible in your current scope.

It appears you don’t have that variable anywhere, that’s why the parser/compiler complains.

So what would be the correct syntax then?

col.gameObject.GetComponent<EnemyHealth>().TakeDamage(damageAmount);

Gives the error:

And that’s what all the other examples I looked up use.

They’re just being cute, abusing optional language rules. They are doing 10 damage. They real call is TakeDamage(10). The damageAmount-colon in front is extra (notice how it’s not a variable in that script.)

C# has an optional feature where you can add the parameter name in front (look at the TakeDamage function, the variable name.) It’s called a “named parameter” or a “named argument” if you want to look it up. It’s main use is to warn people to skip your code examples (I mean it: there are things wrong with that example they could have fixed. Instead they “fixed” a perfectly good TakeDamage(10).)

1 Like

I was editing my answer while you typed that., check the previous post. :slight_smile:

The error is still popping up despite me declaring.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EnemyHealth : MonoBehaviour {

    public int currentHealth = 100;
    public int damageAmount = 10;
  
    // Update is called once per frame
    void Update () {

        if ( currentHealth == 0 )

        {
            Destroy (gameObject);
        }
      
    }

    public void TakeDamage ( int damageAmount )

    {
        currentHealth -= damageAmount;
    }


}

This is annoying, I’m glad I asked about this though.

The scope that you’re calling from needs to know about the variable ‘damageAmount’ or any other variable that you’d like to pass to TakeDamage.

Thanks for your help guys, fixed it in the end :slight_smile:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlasmaShotTakeHealth : MonoBehaviour {
  

    void Start ()

    {
      
    }


    void OnCollisionEnter ( Collision col )

    {
        if ( col.gameObject.tag == "Enemy" )

        {
            col.gameObject.GetComponent<EnemyHealth>().TakeDamage();
        }
    }





}

Just needed to make sure the TakeDamage function had brackets and a semicolon at the end like if I were to declare it on the actual script, was just rather baffled as to why it was behaving in the other way too when I wrote the script out.

Well, you removed the paramter… Now it’s a different method hat handles the damage amount internally and does not longer accept a damage value from the caller.
But that’s fine if the EnemyHealth component is meant to control the damage value.

1 Like

Yes, the first ‘fix’ you made put the variable in the script you’d call into.
Originally, the solution would have been to make the variable by that name in the script from which you were calling :slight_smile:

I agree it’s okay like this, but I’d say it makes a little more sense to have the variable in the plasma giving the dmg, that way you can choose to alter that value (rather than the recipient having a fixed dmg amount taken).