@@ -36,6 +36,9 @@ public class LLM : MonoBehaviour
3636 /// <summary> log the output of the LLM in the Unity Editor. </summary>
3737 [ Tooltip ( "log the output of the LLM in the Unity Editor." ) ]
3838 [ LLM ] public bool debug = false ;
39+ /// <summary> Wait for native debugger to connect to the backend </summary>
40+ [ Tooltip ( "Wait for native debugger to connect to the backend" ) ]
41+ [ LLM ] public bool UseNativeDebugger = false ;
3942 /// <summary> number of prompts that can happen in parallel (-1 = number of LLMCaller objects) </summary>
4043 [ Tooltip ( "number of prompts that can happen in parallel (-1 = number of LLMCaller objects)" ) ]
4144 [ LLMAdvanced ] public int parallelPrompts = - 1 ;
@@ -53,6 +56,8 @@ public class LLM : MonoBehaviour
5356 public bool started { get ; protected set ; } = false ;
5457 /// <summary> Boolean set to true if the server has failed to start. </summary>
5558 public bool failed { get ; protected set ; } = false ;
59+ /// <summary> Boolean set to true if the server has been destroyed. </summary>
60+ public bool destroyed { get ; protected set ; } = false ;
5661 /// <summary> Boolean set to true if the models were not downloaded successfully. </summary>
5762 public static bool modelSetupFailed { get ; protected set ; } = false ;
5863 /// <summary> Boolean set to true if the server has started and is ready to receive requests, false otherwise. </summary>
@@ -127,6 +132,13 @@ void OnValidate()
127132 public async void Awake ( )
128133 {
129134 if ( ! enabled ) return ;
135+ _ = Task . Run ( Load ) ;
136+ }
137+
138+ public async Awaitable Load ( )
139+ {
140+ await Awaitable . BackgroundThreadAsync ( ) ;
141+
130142#if ! UNITY_EDITOR
131143 modelSetupFailed = ! await LLMManager . Setup ( ) ;
132144#endif
@@ -142,9 +154,13 @@ public async void Awake()
142154 failed = true ;
143155 return ;
144156 }
145- await Task . Run ( ( ) => StartLLMServer ( arguments ) ) ;
157+ await StartLLMServerAsync ( arguments ) ;
146158 if ( ! started ) return ;
147- if ( dontDestroyOnLoad ) DontDestroyOnLoad ( transform . root . gameObject ) ;
159+ if ( dontDestroyOnLoad )
160+ {
161+ await Awaitable . MainThreadAsync ( ) ;
162+ DontDestroyOnLoad ( transform . root . gameObject ) ;
163+ }
148164 }
149165
150166 /// <summary>
@@ -476,10 +492,11 @@ private void StopLogging()
476492 DestroyStreamWrapper ( logStreamWrapper ) ;
477493 }
478494
479- private void StartLLMServer ( string arguments )
495+ private async Task StartLLMServerAsync ( string arguments )
480496 {
481497 started = false ;
482498 failed = false ;
499+ destroyed = false ;
483500 bool useGPU = numGPULayers > 0 ;
484501
485502 foreach ( string arch in LLMLib . PossibleArchitectures ( useGPU ) )
@@ -488,6 +505,19 @@ private void StartLLMServer(string arguments)
488505 try
489506 {
490507 InitLib ( arch ) ;
508+ #if UNITY_EDITOR
509+ if ( UseNativeDebugger )
510+ {
511+ if ( llmlib ? . LLM_IsDebuggerAttached == null )
512+ {
513+ LLMUnitySetup . Log ( $ "Tried architecture: { arch } is not debug library") ;
514+ Destroy ( ) ;
515+ continue ;
516+ }
517+
518+ await WaitNativeDebug ( ) ;
519+ }
520+ #endif
491521 InitService ( arguments ) ;
492522 LLMUnitySetup . Log ( $ "Using architecture: { arch } ") ;
493523 break ;
@@ -504,6 +534,7 @@ private void StartLLMServer(string arguments)
504534 catch ( Exception e )
505535 {
506536 error = $ "{ e . GetType ( ) } : { e . Message } ";
537+ Destroy ( ) ;
507538 }
508539 LLMUnitySetup . Log ( $ "Tried architecture: { arch } , error: " + error ) ;
509540 }
@@ -514,20 +545,39 @@ private void StartLLMServer(string arguments)
514545 return ;
515546 }
516547 CallWithLock ( StartService ) ;
517- LLMUnitySetup . Log ( "LLM service created" ) ;
548+ if ( started )
549+ LLMUnitySetup . Log ( "LLM service created" ) ;
518550 }
519551
520552 private void InitLib ( string arch )
521553 {
522554 llmlib = new LLMLib ( arch ) ;
523- CheckLLMStatus ( false ) ;
524555 }
525556
557+ #if UNITY_EDITOR
558+ private async Task WaitNativeDebug ( )
559+ {
560+ if ( llmlib ? . LLM_IsDebuggerAttached != null )
561+ {
562+ LLMUnitySetup . Log ( "waiting debugger" ) ;
563+ while ( ! destroyed )
564+ {
565+ if ( llmlib . LLM_IsDebuggerAttached ( ) )
566+ {
567+ LLMUnitySetup . Log ( "remote debugger attached" ) ;
568+ break ;
569+ }
570+ await Task . Delay ( 100 ) ;
571+ }
572+ }
573+ }
574+ #endif
575+
526576 void CallWithLock ( EmptyCallback fn )
527577 {
528578 lock ( startLock )
529579 {
530- if ( llmlib == null ) throw new DestroyException ( ) ;
580+ if ( llmlib == null || destroyed ) throw new DestroyException ( ) ;
531581 fn ( ) ;
532582 }
533583 }
@@ -556,9 +606,12 @@ private void StartService()
556606 {
557607 llmThread = new Thread ( ( ) => llmlib . LLM_Start ( LLMObject ) ) ;
558608 llmThread . Start ( ) ;
559- while ( ! llmlib . LLM_Started ( LLMObject ) ) { }
560- ApplyLoras ( ) ;
561- started = true ;
609+ while ( ! llmlib . LLM_Started ( LLMObject ) && ! destroyed ) { }
610+ if ( ! destroyed )
611+ {
612+ ApplyLoras ( ) ;
613+ started = true ;
614+ }
562615 }
563616
564617 /// <summary>
@@ -611,6 +664,7 @@ void AssertStarted()
611664 string error = null ;
612665 if ( failed ) error = "LLM service couldn't be created" ;
613666 else if ( ! started ) error = "LLM service not started" ;
667+ else if ( destroyed ) error = "LLM service is being destroyed" ;
614668 if ( error != null )
615669 {
616670 LLMUnitySetup . LogError ( error ) ;
@@ -807,6 +861,7 @@ public void CancelRequest(int id_slot)
807861 /// </summary>
808862 public void Destroy ( )
809863 {
864+ destroyed = true ;
810865 lock ( staticLock )
811866 lock ( startLock )
812867 {
0 commit comments