Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by Captaingerbear · Apr 29, 2014 at 07:24 PM · coroutinecompileobject reference

Generate and Run Coroutine at runtime

Okay, this has been eating at me for weeks and I'm at my wits' end. I use coroutines with some regularity in my game, but for this particular part, I'm needing to generate a coroutine on the fly and run it. I've already got some code generating and executing at runtime, but it needs to be a coroutine so I can do things like suspend while waiting for user's input. Here is what I have so far.

 using Microsoft.CSharp;
 using UnityEngine;
 using System;
 using System.Collections;
 using System.CodeDom.Compiler;
 using System.Reflection;
 
 public class RuntimeCompiler : MonoBehaviour {
 
     CSharpCodeProvider provider = new CSharpCodeProvider();    
     
         
     public static RuntimeCompiler instance { get; private set; }
     
     void Awake()
     {
         if(instance == null)
             instance = this;
         else
             Debug.Log("There are multiple instances of the RuntimeCompiler engine in the scene.");
     }
     
     void OnDestroy()
     {
         instance = null;
     }
     
     public class MethodWrapper
         {
                 System.Reflection.MethodInfo method;
  
                 public MethodWrapper(System.Reflection.MethodInfo method)
                 {
                         this.method = method;
                 }
  
                 public void doIt()
                 {
                        IEnumerable en = (IEnumerable)method.Invoke(null, null);
                 }
         }
     
     public System.Action InterpretScript(string script){
         CompilerParameters parameters = new CompilerParameters();
         parameters.GenerateInMemory = true;
         parameters.ReferencedAssemblies.Add ("System.dll");
         parameters.ReferencedAssemblies.Add ("System.Core.dll");
         //parameters.ReferencedAssemblies.Add ("System.Collections.dll");
         parameters.ReferencedAssemblies.Add (typeof(Transform).Assembly.Location);
         parameters.ReferencedAssemblies.Add (typeof(MapExplore).Assembly.Location);
         CompilerResults results = provider.CompileAssemblyFromSource(parameters, GetCode(script));
         
         if(!results.Errors.HasErrors){
         
             var cls = results.CompiledAssembly.GetType("DynamicCode");
             var method = cls.GetMethod("DynamicMethod", BindingFlags.Static | BindingFlags.Public);
             return (new MethodWrapper(method)).doIt;
             
         }else{
         
             foreach (CompilerError error in results.Errors)
             {
                 Debug.Log(error.ErrorText);    
             }
             
             throw new System.Exception("Dunno Man");            
             
             //return null;
         }
         
         }
     
     public string[] GetCode(string script)
     {
         return new string[]
         {
             @"using System;
             using UnityEngine;
             using System.Collections;
             using System.Collections.Generic;
 
                 public class DynamicCode : MapShim
                 {
                     public static void DynamicMethod()
                     {
                     " + script + @"
                     }
                 }
             "
         };
     }
 }
 
 public class MapShim : MonoBehaviour
 {
    //A bunch of methods to make accessing game variables easier        
 }

So far this all works just fine. "Script" is supplied externally in a string, which is then interpreted into code and run when I invoke it.

*My first disclaimer is that I've had help getting this code working, so I'm a bit lost when it comes to making adjustments. What I need to do is instead have "Script" compiled into a coroutine and then have the invoke trigger that instead. I keep getting problems with object references when I try to do it the way I know how, and I suspect I'm just not structuring something correctly. Any suggestions?

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
0

Answer by Captaingerbear · Apr 29, 2014 at 08:59 PM

I actually managed to piece it together today after setting up a new dummy project where I could muck around without fear of breaking things. This is what I came up with -

The following code -

  return new string[]
 {
 @"using System;
 using UnityEngine;
 using System.Collections;
 using System.Collections.Generic;
  
 public class DynamicCode : MapShim
 {
 public static void DynamicMethod()
 {
 " + script + @"
 }
 }
 "
 };

is replaced with this new code -

         return new string[]
         {
             @"using System;
             using UnityEngine;
             using System.Collections;
             using System.Collections.Generic;
 
                 public class DynamicCode : MapShim
                 {
                             
                 private static DynamicCode inst;
                 public static DynamicCode Instance{
                     get{
                         if(inst == null){
                             var go = new GameObject(""DynamicCode"");
                             inst = go.AddComponent<DynamicCode>();
                         }
                         return inst;
                     }
                 }
 
 
                     public static void DynamicMethod(){
                         DynamicCode.Instance.StartCoroutine(CR());
                     }
 
                     public static IEnumerator CR(){
                         "+script+@"
                         yield return new WaitForSeconds(0f);
                     }
                 }
             "
         };


This gives me the results I wanted. That said, I am still wide open for suggestions on how I could accomplish this more gracefully.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

20 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Tasks with Coroutines don't work properly on play mode 2 Answers

Light Flickering Problem - Wrong objects get referenced by the script 0 Answers

Return value from coroutine to non monobehaviour 1 Answer

Sync WaitForSeconds with Particles 1 Answer

How to create a delay in a function being called in update? 2 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges