
æè¿ãç§ã¯é¢æ°åããã°ã©ãã³ã°ã«ãŸããŸãèå³ãæã¡ãèšèªãéžæãããšãã HaskellãšFïŒãšãã 2ã€ã®èšèªããéžæããŸããã
FïŒã§ã¯ãMSILã¢ã»ã³ããªã«ã³ã³ãã€ã«ã§ããããã«ãªããŸãããããã«ãããä»ã®Microsoft .Netèšèªã§FïŒã¯ã©ã¹ã©ã€ãã©ãªã䜿çšã§ããããã«ãªãã圌èªèº«ããããã䜿çšã§ããããã«ãªããŸããã ããã«å ããŠãç§ã¯Unity3Dã®åå¿è
ã§ããããMSILã«ã³ã³ãã€ã«ããå ŽåãUnityã§FïŒã¹ã¯ãªããã䜿çšã§ããŸããïŒ ã°ãŒã°ã«ã¯çããäžããïŒäººéã«ã¯äžå¯èœã§ãã ã¯ã©ã¹ã©ã€ãã©ãªãäœæãããããžã§ã¯ãã«UnityEngine.dllã©ã€ãã©ãªãžã®ãªã³ã¯ãé
眮ãããããã¢ã»ãããšããŠã³ã³ãã€ã«ããã³ã€ã³ããŒãããã©ã€ãã©ãªããçŽæ¥Mono-behaviorã³ã³ããŒãã³ããè¿œå ã§ããŸãããããã¯ããŸã䟿å©ã§ã¯ãããŸããã ãã ããGoogleãReflectionãããã³Unityã®ãã«ãã確èªããåŸããšãã£ã¿ãŒå
ã§ã®FïŒã¹ã¯ãªããã®äœæ¥ããçµã¿èŸŒã¿èšèªã®ã¹ã¯ãªããã䜿çšããäœæ¥ã«è¿ã¥ããïŒãã ãæ£ç¢ºã«ç¹°ãè¿ãããšã¯ã§ããŸããïŒããšã¯ã§ããŸããã 詳现ã¯habrakatã®äžã«ãããŸãã
ããŒããŒã
ç§ã¯äœãééã£ãããšãããããšãèªããŸãïŒãããŠããããããã§ããå¯èœæ§ãæãé«ãïŒããããŠãé倧ãªééããšããã»ã©å€§ããªééãã¯ãããŸããïŒããã§ããç§ã¯ãããã«ã€ããŠããŸãã¯ãããè¡ãæ¹æ³ãç¥ãããå¥ã®ã¢ã¯ã·ã§ã³ã®æ¹ãè¯ã/ãããã§ãïŒã ãã¬ãã¹ã¿ãŒå¹æãããå¯èœæ§ãããããã®èšäºã§èª¬æãããšã©ãŒ/ã°ãªããã¯çºçããŸããã ç§ã¯èªåã®è¡åãšèŠ³å¯ã説æããã ãã§ãã ç解ããŠæ±ã£ãŠãã ããã æåŸã«ãããã¯ç§ãšåå¿è ãåŠã³ãééããç¯ããããããä¿®æ£ããããã«å¿ èŠãªãã®ã§ãïŒ
Habrahabrã®ã¢ãã¬ãŒã¿ãŒã«æè¬ããŸããç§ã®ãªã¯ãšã¹ãã§ã ã©ã³ãã ã«éä¿¡ããããå ¬éã®æºåãã§ããŠããªããããã¯ããã©ããã«çœ®ããŠãããããšã«æè¬ããŸãã ããããã¯ããã£ãšæ³šæããŸãã
ããŒã1
ç®±ããåºããŠã©ã®ããã«èŠããŸãã
ããã¯ãã³ãªãã§ãããã©ã®ããã«èŠãããã§ãã æ¢ã«ã³ã³ãã€ã«ãããã©ã€ãã©ãªã1ã€ã®ç°¡åãªã¹ã¯ãªããã§äœ¿çšããŸãã
ïŒHaskellãã€ã©ã€ãã¯ãããšäžã§äœ¿çšãããŸããããŸã FïŒã§ããããšã«æ³šæããŠãã ããïŒ
//Please, don't try to change namespace namespace Assembly_FSharp_vs open UnityEngine; type public SphereMoving () = inherit UnityEngine.MonoBehaviour() member public this.Start () = UnityEngine.Debug.Log("initialized") member public this.Update() = let mutable newpos:Vector3 = Vector3.zero newpos.x <- Mathf.Sin(Time.time) newpos.y <- Mathf.Cos(Time.time) this.transform.position <- newpos
ãã®ã¹ã¯ãªããã¯å ã ãç§ã®ç·šéè -ã¹ã¯ãªããã«ãã£ãŠäœæãããŸããã ããã¯ãã³ã¡ã³ãã®ååšãšåå空éã®æ瀺çãªè¡šç€ºã«ãããã®ã§ãïŒä»¥äžã§ãã®åœ¹å²ã«ã€ããŠè©³ãã説æããŸãïŒããå°ãå€æŽããŸããã
ã©ã€ãã©ãªãã³ã³ãã€ã«ããŠãããžã§ã¯ãã«ã€ã³ããŒããããšã次ã®çµæãåŸãããŸãã

ããã¯ãèšäºã®åé ã§äžäŸ¿ãã«ã€ããŠè©±ããŠãããšãã®æå³ã§ã-è€æ°ã®ã©ã€ãã©ãªãäœæããããããç°ãªãå Žæã«ä¿æããå¿ èŠããããŸãïŒå°ãªããšãäœããã®å¯èŠæ§ãäœæããããïŒãŸãã¯é·ããªã¹ãã§äœããèŠã€ããããšããå Žåãããžã§ã¯ãã¯æé·ããŸãã
æ°é ãã®ããå¿åhabrauserã¯ãã§ã«æ°ã¥ããŠãããããæŸèæãããã€ããããŸãã-System.TypeLoadExceptionäŸå€ãã³ã³ãã€ã©ã«ãã£ãŠã¹ããŒãããããšãªãã€ã³ããŒããããããã«ã åã©ã€ãã©ãªã®é£ã«FSharp.Core.dllã©ã€ãã©ãªãé 眮ããå¿ èŠããããŸã ã
ãããŠæ£ç¢ºã«èšããšãFSharp.Core.dllã ãã§ãªãããã¹ãŠã®äŸåé¢ä¿ã®ã©ã€ãã©ãªãŒã¯ãUnityã³ã³ãã€ã©ãŒãåç¬ã§è§£æ±ºã§ããªã競åãåŒãèµ·ãããŸãã FïŒã䜿çšããã²ãŒã ã¯ããããã«å€ããªãããšãæããã«ãªããUnity3dã®äžã«äœããæžãããšã¯ã åç©ã®å¥œå¥å¿ããã®ã¿åãå ¥ããããããã§ã倧ããããªã¥ãŒã ã§ã¯ãããŸããã
ããã§ã®æãããªè§£æ±ºçã¯ããã¹ãŠã®FïŒãœãŒã¹ãããŒãã«é 眮ããããããã³ã³ãã€ã©ã«çŽæ¥éä¿¡ã§ãããšãã£ã¿ãŒã¹ã¯ãªããã䜿çšããããšã§ãã ã¡ãªã¿ã«ãã€ãã³ãã説æãããå°ãåã«ãåºå€§ãªåºå€§ãªåºå€§ãã«ã€ããŠãç§ã¯ãã®èšäºã«åºäŒãããããç§ã®ç 究ã®åºçºç¹ã«ãªããŸããã
次ã®éšåã®èª¬æã§ã¯ã2ã€ã®å Žåãé€ããã©ãããããããžã£ã³ã°ã«ã«æ·±ãå ¥ããŸããã
1. System.CodeDom.Compiler.CodeDomProviderã¯ã©ã¹ã¯ãFïŒã®ã³ã³ãã€ã©ãæäŸã§ããŸããã
2. System.CodeDom.Compileråå空éã®ãã¹ãŠã®ã¯ã©ã¹ã¯ãUnityã³ã³ãã€ã©ãŒã«åã«ãèŠããªããã ãã§ãã ãããžã§ã¯ãã«ãªã³ã¯ããããVisual Studioããã¹ãŠãæ£åžžã§ãããšèšã£ãŠããŠããã³ã³ãã€ã©ã¯åçŽã«å€§ãã倪ããã°ã衚瀺ããŸãããã®ãã°ã§ã¯ããã®æ¹æ³ã§ã¯å®è¡ã§ãããSystem.CodeDom.Compilerã®å 容ã倢èŠãŠããªãããšãããããŸãã System.CodeDom.Compilerãäœããã®åœ¢ã§åç §ããã©ã€ãã©ãªãæ¥ç¶ããå Žåã§ããã³ã³ãã€ã©ã¯ãšã«ãã匷ãå察ããŸãããã°ã«ã¯ã次ã®ãããªã¡ãã»ãŒãžã衚瀺ãããŸãã
Internal compiler error. See the console log for more information. output was:
Unhandled Exception: System.TypeLoadException: Could not load type 'System.CodeDom.Compiler.CompilerResults' from assembly 'System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.
ãããç®çã§ãªãå Žåãããã§è©±ã¯çµããã§ãããã®ããŒã ã¹ããŒã¹ã®ã¯ã©ã¹ã¯ãçŸåšã®ãã¡ã€ã³ã§äœ¿çšå¯èœãªã¢ã»ã³ããªã®ã³ã¬ã¯ã·ã§ã³ãåã«ãœãŒããããã°ã«ãã¹ãŠã®ã¿ã€ãã®ååã衚瀺ããã ãã§ãå®è¡æã«ã¢ã»ã³ããªã§èŠã€ããããšãã§ããŸããã€ãŸããReflectionã䜿çšããŠäœæã§ããŸããªããžã§ã¯ããšã¡ãœããã®åŒã³åºãïŒãã ããReflectionã¯ãã®åŸè»èã«ããšãæããŸããã©ãã§ã以äžã§èª¬æããŸãïŒã
ããŒã2
ãããã銬ãªãã
FïŒã®CodeDomProviderãåãåã£ãŠæäœããŸã
ãããã2çªç®ã®ãBUTãããŸã åé¿ã§ããå Žåãæåã®ãBUTãã¯ã©ãã§ããããã
ããã§ã¯ãã°ãŒã°ã«ã®éçšã§èŠã€ãã£ãFïŒPower Packã圹ã«ç«ã¡ãŸãããããã¯ãäœããã®æ¹æ³ã§FïŒã䜿çšãããã¹ãŠã®äººã«åœ¹ç«ã€ãšæããŸãã åŒæ°ïŒä»£ããã«ïŒãFSharpãïŒCïŒã®CodeDomProviderã®äœææ¹æ³ã«äŒŒãŠããŸã-åŒæ°ãCSharpãïŒããã³ãFïŒãïŒããæããŸããïŒïŒ
FïŒPower Packã¯ãSystem.CodeDom.Compileråå空éã®éåžžã®CodeDomProviderãšæ¯ã¹ãŠäœ¿çšäžã®éããã»ãšãã©ãªããåæãããŠããMicrosoft.FSharp.Compiler.CodeDom.FSharpCodeProviderãæäŸããŸãã
åé¡ã¯å°ããããã§ã-ãã©ã°ã¢ã³ããã¬ã€ã§ãããããã«ãèœãšãç©ŽããããŸãïŒ
1.ãã®ã©ã€ãã©ãªã¯.Net Frameworkããã±ãŒãžã«å«ãŸããŠããªãããããããžã§ã¯ãã«é 眮ããå¿ èŠããããŸãã
2. FSharpCodeProviderèªäœãSystem.CodeDom.Compilerããåã«ã¢ã¯ã»ã¹ãããããã³ã³ãã€ã«äžã«æ°žç¶çãªSystem.TypeLoadExceptionãååŸããå¯èœæ§ããããã¹ã¿ãžãªIntelliSenseãå å°ããŸããã
Xaosã®æå¿ã§ãç§ã¯ããããã£ãã®ã§ãReflectionãšActivatorã䜿çšããŠãã¹ãŠãããŸããã ãããããçµå±ã®ãšãããç§ã¯ã©ããã§ééããç¯ããŸããããäœããå€æŽããã«ã¯é ãããŸãã ãŸãããããã®ç®çã®ããã«ïŒåãFïŒçšã«ïŒç§ãæåã«æžããã©ã€ãã©ãªã¯ããã®ãããªããªãã¯ãªãã§ã³ã³ãã€ã«ãããïŒã€ãŸããReflectionãä»ããŠFSharpCodeProviderã§å®è¡ããã¡ãœããã¯ãããŸããã§ããïŒ System.CodeDom.Compileråå空éã®åé¡ãæ±ããåãåé¡ã¯ããªãã¬ã¯ã·ã§ã³ã«ãã£ãŠè§£æ±ºãããŸããã 奜å¥å¿oneçãªäººãªã誰ã§ãããã§çãããŒã¹ããç¥ãããšãã§ããŸã ã
奜å¥å¿ã®åŒ·ã人ã®ããã«ãFïŒã®ãšãã£ã¿ãŒã¯ã©ã¹ã³ãŒãã貌ãä»ããŸãã 泚æïŒ ãã®ã¯ã©ã¹ã§ã©ã€ãã©ãªãè¿œå ããåŸãã³ã³ãã€ã«ã®çµæãšããŠäœãèµ·ããããã©ã€ãã©ãªãã£ã¬ã¯ããªã«ãªããããããæ¶å»ããã®ãåé¡ã«ãªãããšãããããã®çµæãæ°žç¶çãªãæªéå°ããåŸãããŸãïŒãšãã£ã¿ã¯ã©ã¹ã湟æ²ããŠããããã«ãšãã£ã¿ãã¯ã©ãã·ã¥ããããïŒãšãã£ã¿ãŒãæå¹ã«ããããšãããšãã Libraryãã©ã«ããåé€ããå¿ èŠããããŸãããããã¯éåžžææªã®çµæããããããŸãã èŠåããã
CodeDomProviderã«æ»ããšãå€ãã®ããšãReflectionãä»ããŠè¡ãããŠããããšãæãåºããŸãã ãããŠãããã«çµ±èšã®è»èã§çŽæããããã©ã€ããããŸã -ã¢ã¯ãã£ããŒã¿ãŒã䜿çšããŠã¿ã€ãïŒïŒïŒSystem.CodeDom.Compiler.CompilerParametersãååŸããããšãããšãã äœæãããã¿ã€ãã¯MarshalByRefObjectãã掟çããªã ãããã NotSupportedExceptionãååŸããŸãã³ã³ãã€ã©ãŒã¯ãŸã ãã©ã¡ãŒã¿ãŒãèšå®ããå¿ èŠãããããã§ãã ãããè¡ãã«ã¯ãããŸãã«ããšã¬ã¬ã³ãã«è¡åããå¿ èŠã¯ãããŸãã-çŸåšã®ãã¡ã€ã³ã®ã¢ã»ã³ããªã³ã¬ã¯ã·ã§ã³ã§System.dllãèŠã€ããã¢ã»ã³ããªããå¿ èŠãªåãååŸããå¿ èŠããããŸãã
IEnumerator asmEnum = System.AppDomain.CurrentDomain.GetAssemblies().GetEnumerator(); while (asmEnum.MoveNext()) { Assembly asm = asmEnum.Current as Assembly; if (asm.FullName.Contains("System, V")) { comparamtype = asm.GetType("System.CodeDom.Compiler.CompilerParameters"); } if (asm.FullName.Contains("FSharp.Compiler.CodeDom")) { compilertype = asm.GetType("Microsoft.FSharp.Compiler.CodeDom.FSharpCodeProvider"); } }
ãã ããCompilerParametersãšFSharpCodeProviderã®äž¡æ¹ã®ã€ã³ã¹ã¿ã³ã¹ãååŸããã®ã¯ç°¡åã§ãã
object _params = System.Activator.CreateInstance(comparamtype, new object[] { new string[] { "System", "System.Core", UenginePath } }); comparamtype.GetProperty("IncludeDebugInformation").SetValue(_params, true, new object[] { }); comparamtype.GetProperty("OutputAssembly").SetValue(_params, @"Assets/Assembly/Assebly-FSharp-vs.dll", new object[] { }); object compiler = System.Activator.CreateInstance(compilertype);
CompilerParametersã€ã³ã¹ã¿ã³ã¹ã¯ã3ã€ã®å¿ èŠãªäŸåé¢ä¿ïŒã¯ãããã€ãã¹ã§ããããã¯åŸã§ä¿®æ£ãããŸãããã³ã³ãã€ã«ã«ã¯ååã§ãïŒã®ã¿ãåŒæ°ãšããŠäœæãããŸãã é åã®3çªç®ã®ã¡ã³ããŒã¯ãUnityEngine.dllã©ã€ãã©ãªãžã®ãã«ãã¹ãåéããããããã£ãè¿ãã次ã®ããã«ãªããŸãã
static string UenginePath { get { return UnityEditor.EditorApplication.applicationContentsPath + "/Managed/UnityEngine.dll"; } }
å°ããªããšã¯ããã¡ã€ã«ã®ãªã¹ããã³ã³ãã€ã«ããŠã³ã³ãã€ã©ã«éä¿¡ããããšã§ãã ãããããã1ã€åŸ®åŠãªéãããããŸããæåã«ãã®ã¹ã¯ãªãŒã³ã·ã§ãããæäŸããŸãã

ãããã§äœããããããããšã¹ã¿ãŒãªããã¯æã£ãã ãããŠãç§ã¯æ£ããèããŸãã-çµæã®ãšãã£ã¿ãŒã¹ã¯ãªãããæ¢ã«äœ¿çšããŠãããããžã§ã¯ãã®ã¹ã¯ãªãŒã³ã·ã§ããã瀺ããŸããã ãŸããç§ã¯èªåèªèº«ã«å ãããããšã¯ãããŸããã ãããªãè¡åã®æ¬è³ªãæ確ã«ãªãããã«ãç§ã¯ãããããªããã°ãªããŸããã§ããã ãããŠãããã«ãããŸãïŒã©ã€ãã©ãªå ã®ã¹ã¯ãªããã§ã¯ãªããã¹ã¯ãªããèŠçŽ ãã¯ãªãã¯ãããšãã«ã¢ã»ããã匷調衚瀺ãããããã«ã¯ãã¿ã€ã<=>ã¢ã»ããã®é¢é£ä»ããäœæããå¿ èŠããããŸãããããã£ãŠãã³ã³ãã€ã«çšã®ã¹ã¯ãªããã®ãªã¹ãã«ã¹ã¯ãªãããè¿œå ããŠãæå³ããããŸããã€ã³ããŒããããŸããã ããã確èªããã«ã¯ãAssetDatabaseã䜿çšããå¿ èŠããããŸãã åæã«ããã¢ã»ããã«ãããŸãïŒ=ã¢ã»ããã«ã€ã³ããŒãããããã©ã«ããŒãã ããããããã«ã€ããŠã¯åŸã§ã ãã®ã¹ãããã§ååŸããå¿ èŠããã£ããã®ã¯ãã§ã«è¡ãããŠããŸã-ã³ã³ãã€ã©ãŒãšãã®ãã©ã¡ãŒã¿ãŒã®ã€ã³ã¹ã¿ã³ã¹ãåãåã£ãŠäœ¿çšããæºåãããŸããã
ããŒã3
ã¹ãºã¡ã®å€§ç ²ãããã©ãã°ã¢ã³ããããããšãããããªæ€æ»å®
éåžžã®ãã©ãã°ã¢ã³ãããããã§ã³ã³ããŒãã³ãããªããžã§ã¯ãã«è¿œå ããããšã¯éåžžã«äŸ¿å©ã§ãã ããããå®éã«ã¯ãã¹ã¯ãªãŒã³ã·ã§ããã衚瀺ããåŸãç§ã¯å®å šãªçå®ãèªããŸããã§ãã-ç·šéè ã¯ã圌ã匷調ãããã®ããŸã ã¹ã¯ãªããã§ããããšãç解ããŸããã§ããã èªèãããªãã¢ã»ããïŒããšãã°ã.fsã¹ã¯ãªãããšåæ§ã«æªç¥ã®æ¡åŒµåãæã€ãã¡ã€ã«ïŒã¯ãUnityEngine.DefaultAssetã¿ã€ãã§ã€ã³ããŒããããŸãïŒæããã«ãInternalã§ããããããšãã£ã¿ãŒã¹ã¯ãªããã§ã¯äœ¿çšã§ããŸããããããã¯ãŸã£ããæ°ã«ããŸããïŒã ããããè³ç£ãªããžã§ã¯ãããã®å ŽæããçŽæ¥ååŸããããšã¯äžå¯èœã§ããããïŒãããã«ããŠããç§ã¯æ¹æ³ãèŠã€ããããŸããã§ããïŒãããã¯æ£å察ã«è¡ãããšãã§ããŸããæ¯figçã«èšãã°ã æšœãäœãå¿ èŠããããŸãã ïŒ
string[] _files = Directory.GetFiles("Assets/", "*.fs"); typenameToObject = new Dictionary<string, UnityEngine.Object>(); foreach (string file in _files) { UnityEngine.Object o = AssetDatabase.LoadAssetAtPath(file, typeof(UnityEngine.Object)); if (CollectCompileDeploy.typenameToObject != null) { CollectCompileDeploy.typenameToObject.Add(o.name, o); } else { return; } }
ããã¯ãŸãã«äœæããå¿ èŠããããã®ã§ãã.fsãã¡ã€ã«ãžã®ãã¹ã®ãªã¹ããããããããã€ã³ããŒããããã¢ã»ããã®ãªã¹ããååŸããŸãã ãã®ãããªã¢ã»ããã«ã¯ãFïŒã¹ã¯ãªããçšã®CustomInstectorã®äœææã«çŸãã1ã€ã®æ©èœããããŸããã€ãŸããUnityEngine.DefaultAssetã¯ããŠã£ã³ããŠã§ã€ã³ã¹ãã¯ã¿ãŒãŸãã¯å¥ã®ã¢ã¯ã·ã§ã³ãéžæããåŸã«ã®ã¿ AssetDatabaseã«ããŒããããŸãã ãããã£ãŠãããã§ã¯Directory.GetFilesã䜿çšããŠååŸãããã¹ã䜿çšããŠæåã§ããŒããããŸãã
FïŒã¹ã¯ãªããã¢ã»ããã®CustomInspectorã¯ãçŽç²ã«è¡šé¢çãªãã®ã§ããã次ã®ããã«ãªããŸãã

ãã®CustomInspectorã®ã³ãŒãã¯æ¬¡ã®ãšããã§ãã
[CustomEditor(typeof(UnityEngine.Object))] public class FSharpScriptInspector : Editor { public SerializedProperty test; string text; void OnEnable() { Repaint(); } public override void OnInspectorGUI() { GUI.enabled = true; if (!AssetDatabase.GetAssetPath(Selection.activeObject).EndsWith(".fs")) { DrawDefaultInspector(); } else { if (text == null) { StreamReader sr = File.OpenText(AssetDatabase.GetAssetPath(Selection.activeObject)); text = sr.ReadToEnd(); sr.Close(); } GUILayout.Label("Imported F# script"); EditorGUILayout.TextArea(text); } } }
å±æ§å±æ§CustomEditorã¯ãCustomInspectorãäœæããã¿ã€ãã瀺ããŸãã ãªããªã Unity3Dã¿ã€ãã®å§åçå€æ°ãUnityEngine.ObjectïŒã¢ã»ãããå«ãïŒãç¶æ¿ããŠããå Žåãã€ã³ã¹ãã¯ã¿ãŒãŠã£ã³ããŠã§.fsã¹ã¯ãªããã®ã¿ã«æç»ãããã¹ããã®ããã¹ãŠã®ã¢ã»ããã«æç»ãããããšã¯èš±å¯ãããŸããã ãããè¡ãã«ã¯ãAssetDatabase.GetAssetPathãä»ããŠã¢ã»ãããžã®ãã¹ãååŸããæ¡åŒµåã確èªããŸãã DrawDefaultInspectorã¡ãœããã«ã¯ç¹å¥ãªæ³šæãå¿ èŠã§ãã ååãæšæž¬ããããã«ããã®æ¹æ³ã§ã¯ããã©ã«ãã§ã€ã³ã¹ãã¯ã¿ãŒãæç»ããŸãã
ãã®DïŒDãå®è£ ããã«ã¯ãã€ãã³ãã远跡ããå¿ èŠããããŸããæåŸã®ã€ãã³ãã¯ãåžžã«Event.currentããããã£ããååŸã§ãã ãããã®å€ã®ãããããåžžã«è¿ããŸã ã ã€ã³ã¹ãã¯ã¿ãŒãŠã£ã³ããŠã§ãªããžã§ã¯ãããã©ãã°ãããšãå¿ èŠãªDrawïŒDropã€ãã³ããããããã£ããè¿ãããŸãããã ããã¹ã¯ãªãããªããžã§ã¯ãã¯ã²ãŒã ãªããžã§ã¯ãã«ã®ã¿è¿œå ã§ãããããã²ãŒã ãªããžã§ã¯ãã€ã³ã¹ãã¯ã¿ãŒãŠã£ã³ããŠã§ãããã®DïŒDã€ãã³ãã远跡ã§ããCustomInspectorãå¿ èŠã§ãã å¥åŠãªããšã§ããããããå®è£ ããããã«ã¯ããã§ã«2ã€ã®ãªãã·ã§ã³ããããŸãã
1. UnityEngine.GameObjectã¯ã©ã¹ã«CustomInspectorã䜿çšããŸã
2. UnityEngine.Transformã¯ã©ã¹ã«CustomInspectorã䜿çšããŸã

DrawDefaultInspectorã䜿çšããããšã«ããé çã®çš®ããããŸãã çµå±ãã€ãã³ãããã£ããããã ãã§æžã¿ãŸããããå®éã«ã¯ãCustomInspectorã¯äœããæç»ããå¿ èŠããããŸãã ãŸãã¯ãDrawDefaultInspectorãåŒã³åºããŸãããã¹ã¯ãªãŒã³ã·ã§ããã¯ãããäœã«ã€ãªãã£ããã瀺ããŠããŸãã
ãããããã¹ãŠã倱ãããããã§ã¯ãããŸããããªããªã ãŠã£ã³ããŠã¯éåžžã«ã·ã³ãã«ã§ã埩å ããããšã¯é£ãããããŸããã Vector3æ§é ã®3ã€ã®ãã£ãŒã«ããäœæããã ãã§ååã§ãã
1. ãªã€ã©ãŒè§ã®åœ¢ã§ãªããžã§ã¯ããå転ããã«ã¯
2.ãªããžã§ã¯ãã®äœçœ®ã«ã€ããŠ
3.ãªããžã§ã¯ãã®ã¹ã±ãŒã«ã®å€ã«ã€ããŠ
ãªã€ã©ãŒå€ããåå æ°ãžã®è§åºŠå€ã¯ ã Quaternion.Eulerã¡ãœããã«ãã£ãŠå€æãããŸãã
ãã®CustomInspectorã®ã³ãŒãã¯æ¬¡ã®ãšããã§ãã
using UnityEngine; using System.Collections; using UnityEditor; using System.IO; using System.Collections.Generic; [CustomEditor(typeof(UnityEngine.Transform))] public class ComponentCI : Editor { Vector3 position; void OnEnable() { Repaint(); } public override void OnInspectorGUI() { EditorGUILayout.BeginVertical(); (this.target as Transform).localRotation = Quaternion.Euler(EditorGUILayout.Vector3Field("Local Rotation", (this.target as Transform).localRotation.eulerAngles)); (this.target as Transform).localPosition = EditorGUILayout.Vector3Field("Local Position", (this.target as Transform).localPosition); (this.target as Transform).localScale = EditorGUILayout.Vector3Field("Local Scale", (this.target as Transform).localScale); EditorGUILayout.EndVertical(); if (Event.current.type == EventType.DragPerform) { if (AssetDatabase.GetAssetPath(DragAndDrop.objectReferences[0]).EndsWith(".fs")) { (this.target as Transform).gameObject.AddComponent(DragAndDrop.objectReferences[0].name); } } } }
ã³ãŒããããèŠããšãå®å šã«æ確ã§ã¯ãªã詳现ãæããã«ãªããŸã-ããããã€ãã³ãäžã«è¿œå ãããã³ã³ããŒãã³ãã¯ã©ãã§ããïŒ
GameObject.AddComponentã®ãªãŒããŒããŒãã®1ã€ã¯ã ã¹ã¯ãªããåãåŒæ°ãšããŠåããŸãããå®éã«ã¯ã¿ã€ãåã§ããããã®ã¹ã¯ãªãããé 眮ãããå¿ é ããŒã ã¹ããŒã¹ã¯ãã§ã«æ±ºå®ãããŠããŸãã
ããã§ãã¹ã¯ãªããã®DïŒDã®æºåãã§ããŸããã ä»ã ãããã¯ããŸãã«ããšã¬ã¬ã³ãã«èŠããŸããã ãã®ãããªã€ã³ã¹ãã¯ã¿ãŒãŠã£ã³ããŠãäœæããã«ã¯ãFïŒã¹ã¯ãªããããšã«CustomInspectorãäœæããå¿ èŠããããŸãã ã€ã³ã¹ãã¯ã¿ãŒã³ãŒãïŒäŸãšããŠSphereMovingã¯ã©ã¹ã䜿çšïŒïŒ
ïŒVisualStudioã®èªåæžåŒèšå®ã䜿çšãããŸãããå®éã«ã¯ãã³ãŒãã¯æžåŒèšå®ãšã€ã³ãã³ããªãã§äœæãããŸããããã¯ã誰ãããã®çµæãèªããšèšç®ãããªãã£ãããã§ãïŒ
using System; using System.Collections.Generic; using System.Linq; using System.Text; using UnityEngine; using UnityEditor; using System.IO; [CustomEditor(typeof(Assembly_FSharp_vs.SphereMoving))] [CanEditMultipleObjects] public class ins_SphereMoving : Editor { public SerializedProperty prop1; public List<SerializedProperty> props; void OnEnable() { props = new List<SerializedProperty>(); System.Reflection.FieldInfo[] fields = typeof(Assembly_FSharp_vs.SphereMoving).GetFields(); foreach (System.Reflection.FieldInfo field in fields) { SerializedProperty mp = serializedObject.FindProperty(field.Name); if (mp != null) { props.Add(mp); } } Repaint(); } public override void OnInspectorGUI() { if (UnityEditor.EditorApplication.isCompiling) { EditorGUILayout.LabelField("Can't show anything during compilation"); //I don't want to live on this scope anymore! return; } try { EditorGUILayout.ObjectField("Script", CollectCompileDeploy.typenameToObject.ContainsKey("SphereMoving") ? CollectCompileDeploy.typenameToObject["SphereMoving"] : null, typeof(UnityEngine.Object), false); EditorGUILayout.BeginVertical(); foreach (SerializedProperty p in props) { EditorGUILayout.PropertyField(p); EditorGUILayout.Space(); } this.serializedObject.ApplyModifiedProperties(); EditorGUILayout.EndVertical(); } catch { } } }
ã€ã³ã¹ãã¯ã¿ãŒã«ã€ããŠè©±ãå§ãããšãã1ã€ã®éèŠãªè©³çŽ°ã瀺ããŸããã§ãã-Unity3Dã€ã³ã¹ãã¯ã¿ãŒã¯ã©ã¹ã¯ã SerializedObjectã¯ã©ã¹ãšSerializedPropertyã¯ã©ã¹ã䜿çšããŠã€ã³ã¹ãã¯ã¿ãŒãŠã£ã³ããŠã«å ¥åãããå€ãä¿åãããããã®å€ãèªåã§ä¿åããå¿ èŠã¯ãããŸããã ããªããåŸãããšãã§ãããã«ãããèŠãããšãã§ããããã«
ãããã®åãSerializedPropertyã®ã€ãã¬ãŒã¿ã§ããããã®ãã¶ã€ã³ãæ£ãã䜿çšããæ¹æ³ãç解ã§ããŸããã§ããããã®çµæã次ã®ãããªæ··ä¹±ãçããŸããã

ããããæã«ã¯ãããæªåããŸããã
ãªããããèµ·ãã£ãŠããã®ããäœãééããã®ãïŒ ããããç¬ã¯åœŒãç¥ã£ãŠããŸãã ãããã£ãŠãå床ãªãã¬ã¯ã·ã§ã³ãè¡ãããã¹ãŠã®ãã£ãŒã«ãã®ååãååŸãã SerializedObject.FindPropertyã¡ãœããã䜿çšããŠSerializedPropertyãååŸããŸãã CanEditMultipleObjectså±æ§ã¯ ãåããªããžã§ã¯ãã«ããè€æ°ã®åäžã¹ã¯ãªããã®ã€ã³ã¹ãã¯ã¿ãŒã衚瀺ã§ããããã«ããããã«å¿ èŠã§ããããã§ã¯ãªãã·ã§ã³ã§ããã 念ã®ããã«æ®ããŠãããŸãã ãŸããObjectFieldã§ããã¹ã¯ãªãããã£ãŒã«ããå ·äœçã«è¿œå ããã€ã³ããŒãããã.fsãã¡ã€ã«ã§ããUnityEngine.DefaultAssetãªããžã§ã¯ããéä¿¡ããå¿ èŠãããããšã泚ç®ã«å€ããŸãã ãã®åŸããã®ãã£ãŒã«ããã¯ãªãã¯ãããšãã©ã€ãã©ãªå ã®ã¹ã¯ãªããã§ã¯ãªãã.fsãã¡ã€ã«ã匷調衚瀺ãããŸãã
ãããã£ãŠãçµæã¯æ¬¡ã®ããã«ãªããŸãã

ãã®åçãèŠããšãæ°é ãã®ããèªè ã¯å«ã¶ã§ãããïŒ ç§ã®åºã§ã®å¥è·¡ã¯äœã§ããããïŒ
ã¯ããããã ãã§ã¯ãããŸããã
ããŒã4
ããã«-ããæ·±ãã ã¡ãã¥ãŒãå±éããã¹ã¯ãªãããäœæããVisual Studioãœãªã¥ãŒã·ã§ã³ãã¡ã€ã«ãæŽæ°ããŸã

ããã«ãFïŒã¹ã¯ãªããã§ã®äœæ¥ãCïŒ/ Boo / UnityScriptã§ã®äœæ¥ã«ããè¿ã¥ããããã«ãã¡ãã¥ãŒãAsets-> Createããšã³ã³ããã¹ãã¡ãã¥ãŒã«é ç®ãFïŒScriptããè¿œå ãããããžã§ã¯ããã¡ã€ã«ã®çæãšãã¡ã€ã«ãžã®ãããžã§ã¯ãã®è¿œå ãè¿œå ããå¿ èŠããããŸã決å®ïŒããã«ã€ããŠã¯ä»¥äžã§è©³ãã説æããŸãïŒã å€æããããã«ããããžã§ã¯ãã€ã³ã¹ãã¯ã¿ãŒã®ã³ã³ããã¹ãã¡ãã¥ãŒãã¡ãã¥ãŒã§ã
Assets->Create, :
[MenuItem("Assets/Create/F# script")] public static void CreateFS() { string path = AssetDatabase.GetAssetPath(Selection.activeObject); string addNum = ""; if (Selection.activeInstanceID <= 0) { path="Assets"; } if (path.Contains(".")) { path =Directory.GetParent(path).ToString(); } while (File.Exists(path + "/NewBehaviourScript" + addNum.ToString() + ".fs")) { addNum = addNum == "" ? (1).ToString() : (int.Parse(addNum) + 1).ToString(); } path = path + "/NewBehaviourScript" + addNum.ToString() + ".fs"; StreamWriter sw = File.CreateText(path); sw.WriteLine("//Please, don't try to change namespace"); sw.WriteLine("namespace Assembly_FSharp_vs"); sw.WriteLine("type public " + "NewBehaviourScript" + addNum.ToString() + " () ="); sw.WriteLine(" inherit UnityEngine.MonoBehaviour()"); sw.WriteLine(" [<DefaultValue>] val mutable showdown1 : UnityEngine.Vector3"); sw.WriteLine(" [<DefaultValue>] val mutable showdown2 : UnityEngine.Vector3"); sw.WriteLine(" [<DefaultValue>] val mutable showdown3: int"); sw.WriteLine(" member public this.Start () = UnityEngine.Debug.Log(\"initialized\")"); sw.Flush(); sw.Close(); AssetDatabase.LoadAssetAtPath(path,Type.GetType("UnityEngine.DefaultAsset,UnityEngine")); AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport); }

//Please, don't try to change namespace namespace Assembly_FSharp_vs type public NewBehaviourScript1 () = inherit UnityEngine.MonoBehaviour() [<DefaultValue>] val mutable showdown1 : UnityEngine.Vector3 [<DefaultValue>] val mutable showdown2 : UnityEngine.Vector3 [<DefaultValue>] val mutable showdown3: int member public this.Start () = UnityEngine.Debug.Log("initialized")
â , ! .fs Visual Studio, , , , , IDE (, UnityEngine ). , :
<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <ProductVersion>8.0.30703</ProductVersion> <SchemaVersion>2.0</SchemaVersion> <ProjectGuid>{ACFBFD03-C456-E983-5028-ACC6C3ACEA62}</ProjectGuid> <OutputType>Library</OutputType> <RootNamespace>Assembly_FSharp_vs</RootNamespace> <AssemblyName>Assembly_FSharp_vs</AssemblyName> <TargetFrameworkVersion>v4.0</TargetFrameworkVersion> <Name>Assembly-FSharp-vs</Name> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <DebugSymbols>true</DebugSymbols> <DebugType>full</DebugType> <Optimize>false</Optimize> <Tailcalls>false</Tailcalls> <OutputPath>bin\Debug\</OutputPath> <DefineConstants>DEBUG;TRACE</DefineConstants> <WarningLevel>3</WarningLevel> <DocumentationFile>bin\Debug\Assembly_FSharp_vs.XML</DocumentationFile> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <DebugType>pdbonly</DebugType> <Optimize>true</Optimize> <Tailcalls>true</Tailcalls> <OutputPath>bin\Release\</OutputPath> <DefineConstants>TRACE</DefineConstants> <WarningLevel>3</WarningLevel> <DocumentationFile>bin\Release\Assembly_FSharp_vs.XML</DocumentationFile> </PropertyGroup> <ItemGroup> <Reference Include="mscorlib" /> <Reference Include="FSharp.Core" /> <Reference Include="System" /> <Reference Include="System.Core" /> <Reference Include="System.Numerics" /> <Reference Include="D:/Program Files/Unity3.5/Editor/Data/Managed/UnityEngine.dll" /> </ItemGroup> <ItemGroup> <Compile Include="Assets/NewBehaviourScript.fs" /> <Compile Include="Assets/SphereMoving.fs" /> </ItemGroup> <Import Project="$(MSBuildExtensionsPath32)\FSharp\1.0\Microsoft.FSharp.Targets" Condition="!Exists('$(MSBuildBinPath)\Microsoft.Build.Tasks.v4.0.dll')" /> <Import Project="$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets" Condition=" Exists('$(MSBuildBinPath)\Microsoft.Build.Tasks.v4.0.dll')" /> <!-- To modify your build process, add your task inside one of the targets below and uncomment it. Other similar extension points exist, see Microsoft.Common.targets. <Target Name="BeforeBuild"> </Target> <Target Name="AfterBuild"> </Target> --> </Project>

UnityEditor.VisualStudioIntegration.SolutionGuidGenerator ( , " SolutionGUIDGenerator Unity3d" ( ) 1 , .
, , ). GUID , . â . , , , ( ) :
Project("ACFBFD03-C456-E983-5028-ACC6C3ACEA62") = ".\FSharp-csharp", "Assembly-FSharp-vs.fsproj", "{9512B9D0-6FAE-8F85-778C-B28C5421520D}" EndProject
â GUID . â GUID .
, «F#->Update soltuion file».
, :
static string xmlSourceFileDataEnter = "<Compile Include=\""; static string xlmSourceFileDataEnding = "\" />"; [MenuItem("F#/Update solution file")] public static void UpdateSolution() { if(File.Exists("Assembly-FSharp-vs.fsproj")) { File.Delete("Assembly-FSharp-vs.fsproj"); } StreamWriter sw = File.CreateText("Assembly-FSharp-vs.fsproj"); sw.WriteLine(xmlEnterData); foreach (UnityEngine.Object file in typenameToObject.Values) { sw.Write(xmlSourceFileDataEnter); sw.Write(AssetDatabase.GetAssetPath(file)); sw.WriteLine(xlmSourceFileDataEnding); } sw.WriteLine(xmlFinishData); sw.Flush(); sw.Close(); sw.Dispose(); string[] slnfiles = Directory.GetFiles(".","*-csharp.sln"); if (slnfiles != null && slnfiles.Length>0) { StreamReader sr = File.OpenText(slnfiles[0]); List<string> lines = new List<string>(); while (!sr.EndOfStream) { string readenLine = sr.ReadLine(); lines.Add(readenLine); if (readenLine.Contains("Assembly-FSharp-vs.fsproj")) { sr.Close(); sr.Dispose(); return; } } sr.Close(); sr.Dispose(); sw = File.CreateText(slnfiles[0]); List<string>.Enumerator linesEnum = lines.GetEnumerator(); linesEnum.MoveNext(); sw.WriteLine(linesEnum.Current); linesEnum.MoveNext(); sw.WriteLine(linesEnum.Current); string slinname = slnfiles[0].Remove(slnfiles[0].LastIndexOf(".sln")); sw.WriteLine("Project(\"" + UnityEditor.VisualStudioIntegration.SolutionGuidGenerator.GuidForProject("Assembly-FSharp-vs") + "\") = \"" + slinname + "\", \"Assembly-FSharp-vs.fsproj\", \"{"+UnityEditor.VisualStudioIntegration.SolutionGuidGenerator.GuidForSolution(slinname)+"}\""); sw.WriteLine("EndProject"); while (linesEnum.MoveNext()) { sw.WriteLine(linesEnum.Current); } sw.Flush(); sw.Close(); sw.Dispose(); } }

UnityEngine , GUID . «Update solution file»âŠ
, «Manual rebuild». , F# , , , . , , , UnityEngine.Object, . , , Unity , , . , , F# .
- , - . ProgressBar':


UnityEngine.Object . .
, . , , Unity3d . , .
PS ExecuteInEditMode MonoBehaviour ( Monobehaviour.Update ) - , . , Edit-time unity script, C#, ?
Edit-time

, . , , , - , yield-, . , , - yield- - . , :
public class UniversalEnumerator : IEnumerator { List<Func<object>> allCodeFrames = new List<Func<object>>(); IEnumerator codeEnum; Func<object> finishAction = null; public Func<object> FinishAction { get { return finishAction; } set { finishAction = value; } } public void Add(Func<object> code) { allCodeFrames.Add(code); } public void _Finalize() { codeEnum = allCodeFrames.GetEnumerator(); } public object Current { get { return codeEnum.Current; } } public bool MoveNext() { bool res = codeEnum.MoveNext(); if (res) { (codeEnum.Current as Func<object>)(); } else { if (FinishAction != null) { return FinishAction()!=null; } } return res; } public void Reset() { codeEnum = null; allCodeFrames.Clear(); FinishAction = null; } }
, Add Func . MoveNext _Finalize codeEnum.Current. FinishAction â , , . , False, , ( , , ). UpdateLoop . InitializeOnLoad:
static UniversalEnumerator currentRoutine; static CollectCompileDeploy() { UnityEditor.EditorApplication.update += new EditorApplication.CallbackFunction(() => { if (currentRoutine != null) { if (!currentRoutine.MoveNext()) { currentRoutine = null; } } }); Initialize(); }
Recompile UniversalEnumerator.
public enum CompilationState { GATHER =1, COMPIL, VALIDATION, SOLUTION, DONE, NONE } public static UniversalEnumerator Recompile() { UniversalEnumerator myEnum = new UniversalEnumerator(); _current = CompilationState.GATHER; CompilationProgressWindow.Init(); myEnum.Add(() => { files.Clear(); ReassingTypes(); return null; }); bool exitall = false; myEnum.Add(() => { if (File.Exists("Assets/Assembly/Assembly-FSharp-vs.dll")) { AssetDatabase.DeleteAsset("Assets/Assembly/Assembly-FSharp-vs.dll"); File.Delete("Assets/Assembly/Assembly-FSharp-vs.dll"); } if (files.Count == 0) { Debug.Log("seems like no any F# file here.terminating"); _current = CompilationState.NONE; exitall = true; } return null; }); System.Type comparamtype = null; System.Type compilertype = null; myEnum.Add(() => { if (exitall) { return null; } UniversalEnumerator bufferedRoutine = currentRoutine; UniversalEnumerator nroutine = new UniversalEnumerator(); IEnumerator asmEnum = System.AppDomain.CurrentDomain.GetAssemblies().GetEnumerator(); while (asmEnum.MoveNext()) { Assembly asm = asmEnum.Current as Assembly; nroutine.Add(() => { if (asm.FullName.Contains("System, V")) { comparamtype = asm.GetType("System.CodeDom.Compiler.CompilerParameters"); } if (asm.FullName.Contains("FSharp.Compiler.CodeDom")) { compilertype = asm.GetType("Microsoft.FSharp.Compiler.CodeDom.FSharpCodeProvider"); } return null; }); } nroutine.FinishAction = () => { currentRoutine = bufferedRoutine; return new object(); }; nroutine._Finalize(); currentRoutine = nroutine; return null; }); myEnum.Add(() => { if (exitall) { return null; } UnityEditor.EditorApplication.LockReloadAssemblies(); try { object _params = System.Activator.CreateInstance(comparamtype, new object[] { new string[] { "System", "System.Core", UenginePath } }); comparamtype.GetProperty("IncludeDebugInformation").SetValue(_params, true, new object[] { }); comparamtype.GetProperty("OutputAssembly").SetValue(_params, @"Assets/Assembly/Assebly-FSharp-vs.dll", new object[] { }); object compiler = System.Activator.CreateInstance(compilertype); List<string> __fls = new List<string>(); foreach(UnityEngine.Object asset in typenameToObject.Values) { __fls.Add(AssetDatabase.GetAssetPath(asset)); } _current = CompilationState.COMPIL; object _output = compilertype.GetMethod("CompileAssemblyFromFile").Invoke(compiler, new object[] { _params, __fls.ToArray() }); compiled = _output.GetType().GetProperty("CompiledAssembly").GetValue(_output, new object[] { }) as Assembly; foreach (object message in _output.GetType().GetProperty("Output").GetValue(_output, new object[] { }) as System.Collections.Specialized.StringCollection) { Debug.Log(message); } foreach (object error in (_output.GetType().GetProperty("Errors").GetValue(_output, new object[] { }) as System.Collections.CollectionBase)) { Debug.LogError(error); } if (compiled != null) { _current = CompilationState.VALIDATION; UniversalEnumerator bufferedRoutine = currentRoutine; UniversalEnumerator nroutine = ValidateInspectors(); nroutine.Add(() => { _current = CompilationState.SOLUTION; UpdateSolution(); _current = CompilationState.DONE; CompilationProgressWindow.Remove(); AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate); return null; }); nroutine._Finalize(); nroutine.FinishAction = () => { currentRoutine = bufferedRoutine; return new object(); }; currentRoutine = nroutine; } else { Debug.LogError("compiled assembly is still not visible!"); } } catch { } UnityEditor.EditorApplication.UnlockReloadAssemblies(); return null; }); myEnum._Finalize(); return myEnum; }
.
. :
UniversalEnumerator bufferedRoutine = currentRoutine; UniversalEnumerator nroutine = new UniversalEnumerator(); nroutine.Add(() => { // . return null; }); nroutine.FinishAction = () => { currentRoutine = bufferedRoutine; return new object(); }; nroutine._Finalize(); currentRoutine = nroutine;
UniversalEnumerator, currentRoutine UniversalEnumerator, FinishAction. new object() , MoveNext false, FinishAction , , EditorUpdateLoop MoveNext , false, currentRoutine null. - UniversalRoutine, , , .
1. .. Mono, IsBackground . , .
2. : Thread.Abort Unity3D : - . â . â (Debug.Log, ) ⊠, .. , . , .
, .
enum' CompilationState, . _current:
private static CompilationState __current = CompilationState.NONE; public static CompilationState _current { get { return CollectCompileDeploy.__current; } set { CollectCompileDeploy.__current = value; if (CompilationProgressWindow.me != null) { CompilationProgressWindow.me.Repaint(); } } }
, CompilationProgressWindow â , EditorWindow . Repaint , - , , . â .
using System; using System.Collections.Generic; using System.Linq; using System.Text; using UnityEditor; using UnityEngine; using System.Runtime.InteropServices; public class CompilationProgressWindow : EditorWindow { public static CompilationProgressWindow me; [StructLayout(LayoutKind.Sequential)] public struct WndRect { public int Left; public int Top; public int Right; public int Bottom; } #if UNITY_EDITOR && UNITY_STANDALONE_WIN [DllImport("user32.dll")] static extern IntPtr GetForegroundWindow(); [DllImport("user32.dll", SetLastError = true)] static extern bool GetWindowRect(IntPtr hWnd, out WndRect rect); public static Vector2 GetWNDSize() { WndRect r = new WndRect(); GetWindowRect(GetForegroundWindow(), out r); return new Vector2(r.Right - r.Left, r.Bottom - r.Top); ; } #else public static Vector2 GetWNDSize() { return Vector2.zero; } #endif public static void Init() { if (me == null) { Vector2 mainWND = GetWNDSize(); CompilationProgressWindow window = (CompilationProgressWindow)EditorWindow.GetWindow(typeof(CompilationProgressWindow), true, "F# Compilation progress", true); window.position = new Rect(mainWND.x/2-200, mainWND.y / 2 - 50, 400, 100); window.title = "F# compilation progress"; window.Focus(); me = window; } else { me.Focus(); } } void OnGUI() { string msg = ""; switch (CollectCompileDeploy._current) { case CollectCompileDeploy.CompilationState.GATHER: msg = "Gathering data"; break; case CollectCompileDeploy.CompilationState.NONE: this.Close(); break; case CollectCompileDeploy.CompilationState.COMPIL: msg = "Compiling F# assembly"; break; case CollectCompileDeploy.CompilationState.DONE: msg = "Done! Wait for assembly import and enjoy"; break; case CollectCompileDeploy.CompilationState.SOLUTION: msg = "Preparing solution files for usage"; break; case CollectCompileDeploy.CompilationState.VALIDATION: msg = "Validating editor scripts"; break; } EditorGUI.ProgressBar(new Rect(0, 0, 400, 100), ((float)CollectCompileDeploy._current) / 5f, msg); } public void OnLostFocus() { this.Focus(); } public static void Remove() { if (me != null) { me.Close(); } else { } } }
switch, . GetWNDSize. GetForegroundWindow System.Diagnostics.Process.GetCurrentProcess MainWindowTitle null, GetWindowRect , MainWindowHandle , (0,0). , . , , , , - , () . , , - Apple, , , . Unity3D . , . , , CollectCompileDeploy._current CompilationState.NONE.
. UnityPackage . ( « »?).



PS F# . . , .
UPD1 : , ( Flash â ). UnityPackage . gnoblin ' Android.
UPD2 : Google Docs