Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Pass pointer into function?

Discussion in 'Scripting' started by CG_Echtzeitschmiede, May 14, 2015.

  1. CG_Echtzeitschmiede

    CG_Echtzeitschmiede

    Joined:
    Feb 19, 2015
    Posts:
    93
    Here is what I'd like to have:

    Code (CSharp):
    1. Vignetting vignettingComponent = Camera.main.GetComponent<Vignetting>();
    2.  
    3. StartCoroutine(ChangeValue(???vignettingComponent.intensity???));
    4. StartCoroutine(ChangeValue(???vignettingComponent.blur???));
    5.  
    6. // This Coroutine is extremely simplified for the example
    7. public IEnumerator ChangeValue(???float pointer??? value)
    8. {
    9.     value = 0f;
    10.     while (value < 1f)
    11.     {
    12.         value += Time.time;
    13.         yield return 0;
    14.     }
    15. }
     
  2. Fajlworks

    Fajlworks

    Joined:
    Sep 8, 2014
    Posts:
    344
    You can do something similar using "out" keyword:
    https://msdn.microsoft.com/en-us/library/vstudio/ee332485(v=vs.100).aspx

    Code (CSharp):
    1.     void Start()
    2.     {
    3.         int value;
    4.         Method(out value);
    5.      
    6.         Debug.Log("value:"+value);
    7.     }
    8.  
    9.     void Method(out int i)
    10.     {
    11.         i = 1337;
    12.     }
    13.  
    However, I'm not sure if this approach will work with coroutines, because program cannot guarantee that the variable will exist during the lifetime of the coroutine.
     
  3. CG_Echtzeitschmiede

    CG_Echtzeitschmiede

    Joined:
    Feb 19, 2015
    Posts:
    93
    I already attempted with the out, it throws an error telling me that iterators cannot have ref or out parameters :-/

    This doesn't necessarily need to be a Coroutine, but I'm looking for a way to elegantly make this happen for whatever float parameter I want to change over time without having to copy and paste code dozens of times. And I don't know how to do that.
     
  4. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    You can't use ref or out for iterator methods using yield statements. Passing local scope variables to an iterator method is impossible, the scope of the iterator can easily last longer then the scope of the local variable. Thus your pointer could be accessing a random spot of memory with something completely different in it. With very weird, unintended results.

    If you are desperate you can pass around a specific field or property using reflection. This is probably the best way to deal with your use case.

    If you are really, really, ..., really desperate, you can write unsafe code and use memory pointers directly. You probably don't want to do this.
     
  5. CG_Echtzeitschmiede

    CG_Echtzeitschmiede

    Joined:
    Feb 19, 2015
    Posts:
    93
    Thank you for your answers. Could you or someone else maybe elaborate on those two options as I have no experience with either?

    In the meantime I found a solution that works. I've never used lambdas or actions, so I don't know whether this solution has potential performance or safety issues?

    Code (CSharp):
    1. Vignetting vignettingComponent = Camera.main.GetComponent<Vignetting>();
    2.  
    3. StartCoroutine(ChangeValue((x) => vignettingComponent.intensity = x));
    4.  
    5. public IEnumerator ChangeValue(System.Action<float> action)
    6. {
    7.     value = 0f;
    8.     while (value < 1f)
    9.     {
    10.         value += Time.time;
    11.         action(value);
    12.         yield return 0;
    13.     }
    14. }
     
    Kiwasi likes this.
  6. Fajlworks

    Fajlworks

    Joined:
    Sep 8, 2014
    Posts:
    344
    I think this solution with lambda is just fine :) as long as vignettingComponent will not be destroyed in meantime
     
  7. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Huh. That works too. I hadn't even considered using a lambda function this way. I see no problem with doing this.

    You'd only go down the reflection path if you needed to change an arbitrary variable that was set at run time.
     
  8. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Adding a null check to the lambda function would probably be wise.
     
  9. CG_Echtzeitschmiede

    CG_Echtzeitschmiede

    Joined:
    Feb 19, 2015
    Posts:
    93
    Alright, thanks to both of you!