Cannot implicitly convert type 'int' to 'string'.

I’m new to programming and struggling to figure out how to get it when the enemy counter is 0 (i.e. all enemies are dead) the counter will stop.

I’m having an issue that when the ragdoll character falls, it hits itself and the number keeps going down into the negatives.

How can I get to counter to stop at 0 instead of going into negatives?

using System;
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class enemiesCounter : MonoBehaviour
{
    public Text enemyCounter;
    int EnemiesToKill;
    private void Awake()
    {
        GameEvents.OnEnemyDead.AddListener(RecountEnemies);
    }
    private void RecountEnemies()
    {
        EnemiesToKill--;
        UpdateUI();
        if (EnemiesToKill <= 0)
        {
            ActivatewinScene();
        }
    }
    private void ActivatewinScene()
    {
        SceneManager.LoadScene("winscene", LoadSceneMode.Single);
    }
    // Start is called before the first frame update
    void Start()
    {
        Enemy[] enemies = GameObject.FindObjectsOfType<Enemy>();
        EnemiesToKill = enemies.Length;
        UpdateUI();
    }
    // Update is called once per frame
    void Update()
    {
        if (enemyCounter.text = 0)
        {
            Destroy(enemyCounter);
        }
    }
    void UpdateUI()
    {
        enemyCounter.text = EnemiesToKill.ToString();
        enemyCounter.text = EnemiesToKill.ToString();
    }
}

Welcome to programming! An important lesson that is good to learn early is that text/strings are not a good way to store data. UI in particular should just be used to present data to the user (or receive input from them).

Looking at your code, you’re already counting down EnemiesToKill. Why not compare against that value instead of trying to use your Text’s component text?

Or you can introduce a separate integer value which counts the enemies killed (rather than counting down EnemiesToKill. When an enemy is killed, add to the count, then update the text, and anything else as necessary.

1 Like

Video showcase: counter bit hard to see top right ish UdJTVXVVJt2ai8RNQf

Thank you so much for the quick response!
I did this to try and fix but it still went into negatives as show in video I recently uploaded:

if (EnemiesToKill <= 0)
{
    EnemiesToKill = 0;
}

The video wasn’t necessary. Explaining your problem was enough.

And look at your code. Look and think about where you’re updating the the text UI. In RecountEnemies() you reduce EnemiesToKill and then update your UI. So if it goes to -1, you probably want to correct that there instead, before updating your UI.

1 Like

That worked! thank you. it was more a matter of order, although not the score goes straight to 0 when I shoot.

I think it’s due to the fact that the score doesn’t just go down by one.

1 Like

Note, just in case you missed it, besides the fact that you can not compare a string to an integer and you should actually use your integer variable, you actually did not compare them here:

    void Update()
    {
        if (enemyCounter.text = 0)

A single equals sign is an assignment, not a comparison. So you try to set the text property to the integer 0.
So two mistakes at once :slight_smile:

3 Likes

I wonder how OP managed to do this without a compiler warning. I remember having a talk with a C++ colleague 20 years ago when he showed me yoda conditions (and I was amazed at how anti-ergonomic that language felt to me, but kept my mouth shut), but this is practically a non-existent problem in C#. In fact, it never happened to me in my life. Across all c-likes, C and C++ are seemingly the only languages that would silently obey an if assignment inside the condition clause.

1 Like

Actually you can do that in C#, but C# is much stricter when it comes to the condition of an if statement. It only accepts an actual boolean value. So there’s no implicit int to bool conversion. In C / C++ it’s kinda the opposite, there’s actually no bool type. Everything not 0 is true.

In C# you can still do assignments in if statements, but the comparision operators have a higher precedence than assignment and therefore you need brackets for things like this:

        string a = "foo";
        string b = "bar";
        string c = "";
        if ((c="foobar") == (a+=b))
        {

The result here is that “c” is assigned to “foobar”, “a” ends up as “foobar” as well and the comparison is true.

ps:
Stupid example

Consider a type like this:

    public class MyType
    {
        public int num;
        public static MyType operator +(MyType a, int b)
        {
            a.num += b;
            return a;
        }
        public static implicit operator bool(MyType a)
        {
            return a.num != 0;
        }
        public static implicit operator MyType(int a)
        {
            return new MyType { num = a };
        }
    }

With this type we can do this:

MyType a = 5;
if (a=8)
{

This would evaluate to “true” because the “8” is implicitly converted into a MyType and the result of the assignment is that new MyType instance which is implicitly converted to bool, thanks to the conversion operators. With the addition operator we can also do

if (a + 5)

or

if (a += 5)
2 Likes

Indeed, it’s perfectly doable, and — from a technical standpoint — there is nothing wrong about it, assignments are interpreted both as statements and expressions.

So in your examples, this is a bit involved and the normal behavior is overridden, and that’s likely not to happen by accident or at least it requires someone to push against the grain without any proper discipline.

But the compiler will always dispense a warning (CS0665) specifically for the most obvious use case (vanilla if(var=literal)), which usually only happens as a typo. I haven’t tried to test this thoroughly, but perhaps one could suppress this warning with just parentheses, I don’t really know how deeply the analyzer runs.

Edit:
In .net 8 parentheses won’t fool it, but this works without a warning

var x = true;
if((x = false) == false) Console.WriteLine("test");

So it doesn’t run that deep, treats anything more complicated as a blackbox expression.

2 Likes

Right. This makes C# a much more user friendly language since you really have to try hard to shoot yourself in the foot but it’s still possible. That’s why the general advice on implicit conversion operators is: Only implement them when it’s obvious that this conversion makes sense and use them sparingly. If you have an idea for an implicit conversion, show a usecase to 10 people and if one can’t follow it, you probably shouldn’t implement it. At least make it explicit in such a case so you’re required to do

a = (MyType)5;

It still might not be clear what it actually does, but you at least know there’s something going on. Of course for custom number types it would make sense to have some implicit conversion.

2 Likes