Search Unity

[Solved] Repeatedly invoke a method with parameters every X period of time without MonoBehaviour?

Discussion in 'Scripting' started by Deleted User, Mar 30, 2015.

  1. Deleted User

    Deleted User

    Guest

    Any hint, advice, or pointers would be greatly appreciated. :)
     
  2. _met44

    _met44

    Joined:
    Jun 1, 2013
    Posts:
    633
    Best pointers starts -I think- with asking why you think you need that ?

    That can give you hints to the anwser.
     
  3. Deleted User

    Deleted User

    Guest

    I'm writing an extension method for Transform that modifies the size of the transform over a period of time. I want to be able to do a simple "transform.Grow(maxSize: 5f, rate: .5f);". Also I think it'll give me good insight into delaying method calls (something I need to do for my ability system).
     
  4. _met44

    _met44

    Joined:
    Jun 1, 2013
    Posts:
    633
    If your transform isn't going to be de-activated you can use StartCoroutine and Invoke.

    Other option is to spawn your own GO to have as much control over its lifetime as you can.
     
  5. Deleted User

    Deleted User

    Guest

    StartCoroutine and Invoke rely on MonoBehaviour though.

    I was thinking of using tasks but it seems it's not available in Unity.
     
  6. _met44

    _met44

    Joined:
    Jun 1, 2013
    Posts:
    633
    Ah right, you're in extension method sorry.

    You can do threads but i don't think you'll be able to scale your object from it, all you can do with it is calculation/processing then pull data back to main thread so it's of no use in your case.

    Then what about making a singleton of a component that spawns itself on a new GO if it doesn't exist ?
     
  7. Deleted User

    Deleted User

    Guest

    Yea I wanted to do threads but apparently I can't touch anything from Unity with them. :/

    I'll try the Singleton approach although I kinda wanted to avoid it.
     
  8. pws-devs

    pws-devs

    Joined:
    Feb 2, 2015
    Posts:
    63
    Try looking at System.Timers, although I would suggest the Singleton approach instead.as you would want to avoid making new threads
     
  9. rakkarage

    rakkarage

    Joined:
    Feb 3, 2014
    Posts:
    683
    one solution/workaround to that is to use loom to queue on main thread

    example of me using it with parse threads
    Code (CSharp):
    1. public static void Register(string email, string password)
    2. {
    3.     try
    4.     {
    5.         ParseUser user = new ParseUser() { Username = email, Email = email, Password = password };
    6.         user.SignUpAsync().ContinueWith(t =>
    7.         {
    8.             if (t.IsFaulted || t.IsCanceled)
    9.                 Loom.QueueOnMainThread(() => { RegisterFail(t.Exception); });
    10.             else
    11.                 Loom.QueueOnMainThread(() => { RegisterSucceed(); });
    12.         });
    13.     }
    14.     catch (Exception e)
    15.     {
    16.         RegisterFail(e);
    17.     }
    18. }
    19.  
    loom code from here:
    http://answers.unity3d.com/questions/305882/how-do-i-invoke-functions-on-the-main-thread.html
    Code (CSharp):
    1. using System;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using System.Threading;
    5. using UnityEngine;
    6. public class Loom : MonoBehaviour
    7. {
    8.     public static int maxThreads = 8;
    9.     private static Loom _current;
    10.     private static bool initialized;
    11.     private static int numThreads;
    12.     private List<Action> _actions = new List<Action>();
    13.     private int _count;
    14.     private List<Action> _currentActions = new List<Action>();
    15.     private List<DelayedQueueItem> _currentDelayed = new List<DelayedQueueItem>();
    16.     private List<DelayedQueueItem> _delayed = new List<DelayedQueueItem>();
    17.     public static Loom Current
    18.     {
    19.         get
    20.         {
    21.             Initialize();
    22.             return _current;
    23.         }
    24.     }
    25.     public static void QueueOnMainThread(Action action)
    26.     {
    27.         QueueOnMainThread(action, 0f);
    28.     }
    29.     public static void QueueOnMainThread(Action action, float time)
    30.     {
    31.         if (time != 0)
    32.         {
    33.             lock (Current._delayed)
    34.             {
    35.                 Current._delayed.Add(new DelayedQueueItem { time = Time.time + time, action = action });
    36.             }
    37.         }
    38.         else
    39.         {
    40.             lock (Current._actions)
    41.             {
    42.                 Current._actions.Add(action);
    43.             }
    44.         }
    45.     }
    46.     public static Thread RunAsync(Action a)
    47.     {
    48.         Initialize();
    49.         while (numThreads >= maxThreads)
    50.         {
    51.             Thread.Sleep(1);
    52.         }
    53.         Interlocked.Increment(ref numThreads);
    54.         ThreadPool.QueueUserWorkItem(RunAction, a);
    55.         return null;
    56.     }
    57.     private static void Initialize()
    58.     {
    59.         if (!initialized)
    60.         {
    61.             if (!Application.isPlaying)
    62.                 return;
    63.             initialized = true;
    64.             var g = new GameObject("Loom");
    65.             _current = g.AddComponent<Loom>();
    66.         }
    67.     }
    68.     private static void RunAction(object action)
    69.     {
    70.         try
    71.         {
    72.             ((Action)action)();
    73.         }
    74.         catch
    75.         {
    76.         }
    77.         finally
    78.         {
    79.             Interlocked.Decrement(ref numThreads);
    80.         }
    81.     }
    82.     private void Awake()
    83.     {
    84.         _current = this;
    85.         initialized = true;
    86.     }
    87.     private void OnDisable()
    88.     {
    89.         if (_current == this)
    90.         {
    91.             _current = null;
    92.         }
    93.     }
    94.     private void Update()
    95.     {
    96.         lock (_actions)
    97.         {
    98.             _currentActions.Clear();
    99.             _currentActions.AddRange(_actions);
    100.             _actions.Clear();
    101.         }
    102.         foreach (var a in _currentActions)
    103.         {
    104.             a();
    105.         }
    106.         lock (_delayed)
    107.         {
    108.             _currentDelayed.Clear();
    109.             _currentDelayed.AddRange(_delayed.Where(d => d.time <= Time.time));
    110.             foreach (var item in _currentDelayed)
    111.                 _delayed.Remove(item);
    112.         }
    113.         foreach (var delayed in _currentDelayed)
    114.         {
    115.             delayed.action();
    116.         }
    117.     }
    118.     public struct DelayedQueueItem
    119.     {
    120.         public Action action;
    121.         public float time;
    122.     }
    123. }
    124.  
     
    Deleted User likes this.
  10. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Attach a MonoBehaviour and run your functionality there with a coroutine or invoke repeating. There is no particular reason not to use a MonoBehaviour. Right tool, right job.
     
    _met44 likes this.