0

Here is the function, and when I print the distance, it is always equal to zero, as opposed to being equal to the int i returned from the FindDist coroutine. However, if I define distance as a public variable outside the function, it will be equal to i, as returned from the FindDist coroutine.

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

public class NewBehaviourScript : MonoBehaviour
{

    public int distance_public = new int();

    IEnumerator FindDist(System.Action<int> callBack)
    {

        for (int x = 0; x < 4; x++)
        {
            if (x == 3)
            {
                yield return x;
                callBack(x);
                break;

            }

        }


    }

    string get_hit_chance()
    {
        int distance = 0;
        StartCoroutine(
            FindDist((int i) => {
                distance = i;
                distance_public = i;
            })

        );
        print(distance);
        print(distance_public);
        float chance = 70 * (100 - distance * distance) / 100;
        chance = Mathf.Floor(chance);
        return chance.ToString() + "%";
        
    }

    void Update()
    {
        print(get_hit_chance());

    }

}

Why is this happening and how can I make the distance equal to i without defining it outside the get_hit_chance() function, by this i mean distance_public in this case.

i tested this code and it prints in order 0, then 3, then 0 % hence showing that the class-level variable changes and the local variable doesnt

  • What you're saying doesn't make sense. It shouldn't matter if `distance` is defined locally or as a class-level variable. Can you please provide us with a [mcve] showing us both versions of the code ***that we can run***? – Enigmativity Jun 27 '21 at 10:53
  • i think i have fixed that, apoligies it is my first time using stack overflow in this capacity – Bash-The-Kernel Jun 27 '21 at 11:19
  • That's great to hear. Would be nice if you could post your solution, as not to leave the question open. [Answering your own question on SO](https://stackoverflow.com/help/self-answer) – Lookaji Jun 27 '21 at 11:25
  • @Bash-The-Kernel - The code you posted doesn't update either variable. Can you please clarify why you think it does? – Enigmativity Jun 27 '21 at 11:29
  • i havent solved the problem i just meant that i fixed my formatting of the problem (i think) – Bash-The-Kernel Jun 27 '21 at 11:32
  • @Bash-The-Kernel - You haven't posted a [mcve]. Please show the actual code that demonstrates your issue. – Enigmativity Jun 27 '21 at 11:48
  • @Enigmativity apologies mate, i have tested this code and it shows exactly what i mean, just apply it to an empty gameobject – Bash-The-Kernel Jun 27 '21 at 11:55
  • 2
    @Bash-The-Kernel - You're not seeing what you think you're seeing. Both `distance` and `distance_public` don't update immediately. The computation for `chance` happens on the default value of `distance`. It's only afterwards does Unity update both distance variables, but by that time the local variable is no longer in scope. – Enigmativity Jun 27 '21 at 12:24

1 Answers1

0

The StartCoroutine is an asynchronous procedure, as it can yield results (cfr. the documentation at MonoBehaviour.StartCoroutine.

What about moving all the code from print(distance); up to the else block inside the lambda response (as was visible from your first post), instead of that assignation of distance = i; like so:

System.Action<string> get_hit_chance() {
    int distance = 0;
    StartCoroutine(FindDist((int i) => {
        distance = i;
        print(distance);
        if (distance == 0) {
            return "0%";
        } else {
            float chance = 70 * (100 - distance * distance) / 100;
            chance = Mathf.Floor(chance);
            return chance.ToString() + "%";
        }
    }));
}
Lookaji
  • 1,023
  • 10
  • 21
  • thanks for the response, but the function get_hit_chance() needs to return a value which is derived from the distance – Bash-The-Kernel Jun 27 '21 at 11:12
  • Maybe It might solve your problem by declaring the `get_hit_chance()` as async: `System.Action get_hit_chance()`. Otherwise you might want to reconsider some design structure, as the call to `StartCoroutine` will be run on another thread, and the execution will continue straight away in printing the content of the `int` variable `distance` being still equal to its initialization value. It is not clear what you mean in declaring that variable `public` outside the function. More code might be needed. – Lookaji Jun 27 '21 at 11:17
  • i think i have made it clear what i mean by public variable now, thank you for replying. – Bash-The-Kernel Jun 27 '21 at 11:27
  • @Bash-The-Kernel - No, the public variable wasn't clear at all. – Enigmativity Jun 27 '21 at 11:28
  • i added distance_public, is it not there? – Bash-The-Kernel Jun 27 '21 at 11:31
  • also the code submitted here returns an error "anonymous function converted to a void returning delegate cannot return a value" – Bash-The-Kernel Jun 27 '21 at 11:34
  • also i just realised i was using the wrong term its not "public" its class-level, apologies – Bash-The-Kernel Jun 27 '21 at 11:36
  • @Lookaji any ideas? – Bash-The-Kernel Jun 27 '21 at 11:59
  • 1
    `asynchronous` is a bit misleading .. no it is not .. it is still executed in the Unity main thread .. but, and there you are right: @Bash-The-Kernel you **can not** return a value from a method starting the coroutine which determins the value! It is not possible since the corouinte possibly terminates in a later frame – derHugo Jun 27 '21 at 13:12
  • @Bash-The-Kernel, I already posted a guiding solution, it is your task to redesign the `get_hit_chance()` logic as to properly support the `StartCoroutine()` method as your can refer to the link to the documentation above. Having no ideas on what is your final goal, I might humbly suggest you to dig deeper around - if you are not familiar with - [asynchronous programming in C#](https://learn.microsoft.com/en-us/dotnet/standard/parallel-processing-and-concurrency). Starting with the .NET framework makes easier IMHO to grasp the concept, and then you can apply it to Unity easier. – Lookaji Jun 28 '21 at 10:11
  • hey mate, funnily enough i solved my particular problem without Ienumerators at all, so i apologise. – Bash-The-Kernel Jun 28 '21 at 10:56