2025-11-06 15:28:16 +09:00
using System ;
2025-10-24 11:55:43 +09:00
using System.Collections ;
2025-10-23 18:43:38 +09:00
using System.Collections.Generic ;
using System.IO ;
2025-10-30 09:31:05 +09:00
using System.Threading ;
2025-10-14 16:38:35 +09:00
using UnityEngine ;
2025-12-03 21:19:07 +09:00
/// <summary>
/// <20> <> <EFBFBD> ø<EFBFBD> <C3B8> <EFBFBD> <EFBFBD> ̼<EFBFBD> <CCBC> <EFBFBD> <20> <> Ʈ<EFBFBD> <C6AE> <20> <> <EFBFBD> <EFBFBD> Ʈ<EFBFBD> <C6AE> <EFBFBD> <EFBFBD> <20> <> ü <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> Ŭ<> <C5AC> <EFBFBD> <EFBFBD>
/// <20> ̱<EFBFBD> <CCB1> <EFBFBD> (Singleton) <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> ϸ<EFBFBD> , Model, View, Presenter <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> (<28> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> )<29> <> <20> <> <EFBFBD> <EFBFBD>
/// <20> <> <20> <> <EFBFBD> <EFBFBD> <20> <> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> ε<EFBFBD> , <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> ʱ<EFBFBD> ȭ, <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD>
/// </summary>
2025-10-14 16:38:35 +09:00
public class AppManager : MonoBehaviour
{
2025-11-04 11:36:19 +09:00
public static AppManager Instance { get ; private set ; }
2025-12-03 21:19:07 +09:00
// --- <20> ν <EFBFBD> <CEBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> Ҵ<EFBFBD> <20> <> (Static Views) ---
[Header("UI Views")]
[SerializeField] private ProgramView view ; // <20> <> <EFBFBD> α <CEB1> <20> <> <EFBFBD> <EFBFBD> UI
[SerializeField] private TCPView tcpView ; // <20> <> ǥ ǥ<> <C7A5> UI
[SerializeField] private RobotInfoView robotInfoView ; // <20> κ<EFBFBD> <20> <> <EFBFBD> <EFBFBD> UI
[SerializeField] private ProgramInfoView programInfoView ; // <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> UI
[SerializeField] private EnvView envView ; // <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> UI
[SerializeField] private PopupView popupView ; // <20> ˾<EFBFBD> UI
[Header("Scene Views & Controllers")]
2025-11-25 15:15:54 +09:00
[SerializeField] private GripperCollide gripperCollide ;
2025-12-03 21:19:07 +09:00
[SerializeField] private RobotController robotController ; // 3D <20> κ<EFBFBD> <20> <> <EFBFBD> <EFBFBD>
[SerializeField] private PointManagerView pointManagerView ; // <20> <> <EFBFBD> <EFBFBD> Ʈ <20> <> Ŀ <20> <> <EFBFBD> <EFBFBD>
[SerializeField] private PathLineView pathLineView ; // <20> ̵<EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD>
[SerializeField] private AudioSource robotAudio ; // <20> κ<EFBFBD> ȿ<> <C8BF> <EFBFBD> <EFBFBD> <20> ҽ <EFBFBD>
2025-10-30 09:31:05 +09:00
2025-12-03 21:19:07 +09:00
// --- <20> <> Ÿ<EFBFBD> <C5B8> <20> <> <EFBFBD> <EFBFBD> <20> <> (Interaction Views) ---
2025-11-11 13:21:20 +09:00
private InteractionView leftInteractionView ;
private InteractionView rightInteractionView ;
2025-12-03 21:19:07 +09:00
// --- <20> <> <EFBFBD> <EFBFBD> <20> <> <20> <> <EFBFBD> <EFBFBD> ---
[SerializeField] private float motorStatePollInterval = 1.0f ; // <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> Ȯ<> <C8AE> <20> ֱ<EFBFBD>
public CancellationTokenSource cancellationTokenSource ; // <20> <EFBFBD> <20> ۾<EFBFBD> <20> <> <EFBFBD> ҿ<EFBFBD> <20> <> ū
private bool isModelAndStaticViewsReady = false ; // <20> ʱ<EFBFBD> ȭ <20> Ϸ<EFBFBD> <20> <> <EFBFBD> <EFBFBD>
// --- MVP <20> ٽ<EFBFBD> <20> <> <EFBFBD> <EFBFBD> ---
private ProgramModel model ; // <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD>
private ProgramPresenter presenter ; // <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
// --- <20> <> Ʈ<EFBFBD> <C6AE> ũ <20> <> <EFBFBD> <EFBFBD> ---
2025-10-23 18:43:38 +09:00
private string hostip ;
private int tcpPort ;
private int udpPort ;
2025-12-03 21:19:07 +09:00
private string configFileName = "config.cfg" ; // <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> ̸<EFBFBD>
2025-11-04 11:36:19 +09:00
void Awake ( )
{
2025-12-03 21:19:07 +09:00
// <20> ̱<EFBFBD> <CCB1> <EFBFBD> <20> ʱ<EFBFBD> ȭ
2025-11-04 11:36:19 +09:00
if ( Instance ! = null & & Instance ! = this )
{
Destroy ( gameObject ) ;
}
else
{
Instance = this ;
}
2025-11-21 13:18:03 +09:00
2025-12-03 21:19:07 +09:00
// --- <20> <> Ʈ<EFBFBD> <C6AE> ũ <20> <> <EFBFBD> <EFBFBD> ȭ <20> <> <EFBFBD> <EFBFBD> (RTT <20> <> <EFBFBD> <EFBFBD> ) ---
// Nagle <20> ˰<EFBFBD> <CBB0> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> Ȱ<EFBFBD> <C8B0> ȭ:
// <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> Ͷ<EFBFBD> <CDB6> <EFBFBD> <20> <> <EFBFBD> ۿ<EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> ʰ<EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> Ͽ<EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> ð<EFBFBD> (Latency)<29> <> <20> <> <EFBFBD> <EFBFBD>
2025-11-21 13:18:03 +09:00
System . Net . ServicePointManager . UseNagleAlgorithm = false ;
2025-12-03 21:19:07 +09:00
// 100-Continue <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> :
// POST <20> <> û <20> <> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> ٸ<EFBFBD> <D9B8> <EFBFBD> <20> <> <EFBFBD> ʿ<EFBFBD> <CABF> <EFBFBD> <20> պ<EFBFBD> <20> ð<EFBFBD> <C3B0> <EFBFBD> <20> <> <EFBFBD> <EFBFBD>
2025-11-21 13:18:03 +09:00
System . Net . ServicePointManager . Expect100Continue = false ;
2025-12-03 21:19:07 +09:00
// <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <20> <> <EFBFBD> <EFBFBD> :
// <20> ⺻<EFBFBD> <E2BABB> <EFBFBD> <EFBFBD> <20> ÷<EFBFBD> HTTP <20> <> û<EFBFBD> <C3BB> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> ó<> <C3B3> <EFBFBD> ǵ<EFBFBD> <C7B5> <EFBFBD> <20> <>
2025-11-21 13:18:03 +09:00
System . Net . ServicePointManager . DefaultConnectionLimit = 10 ;
2025-11-04 11:36:19 +09:00
}
2025-10-14 16:38:35 +09:00
2025-10-23 18:43:38 +09:00
async void Start ( )
2025-10-14 16:38:35 +09:00
{
2025-12-03 21:19:07 +09:00
// 1. <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> ε<EFBFBD> (IP/Port)
2025-10-23 18:43:38 +09:00
LoadConfig ( ) ;
2025-10-14 16:38:35 +09:00
2025-12-03 21:19:07 +09:00
// 2. <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <20> ʱ<EFBFBD> ȭ (<28> <> Ʈ<EFBFBD> <C6AE> ũ <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> )
2025-11-04 11:36:19 +09:00
model = new ProgramModel ( hostip , tcpPort , udpPort , robotController ) ;
2025-10-23 18:43:38 +09:00
await model . InitializeAsync ( ) ;
2025-12-03 21:19:07 +09:00
// 3. <20> ʼ <EFBFBD> View <20> Ҵ<EFBFBD> Ȯ<> <C8AE>
2025-11-14 13:50:31 +09:00
if ( view = = null | | tcpView = = null | | robotInfoView = = null | | programInfoView = = null | | envView = = null | | robotController = = null | |
2025-11-06 15:28:16 +09:00
pointManagerView = = null | | popupView = = null | | pathLineView = = null )
{
Debug . LogError ( "AppManager<65> <72> <20> ν <EFBFBD> <CEBD> <EFBFBD> <EFBFBD> Ϳ <EFBFBD> [Static Views]<5D> <> <20> <> <EFBFBD> <EFBFBD> <20> Ҵ<EFBFBD> <D2B4> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> " , this ) ;
return ;
}
2025-11-04 11:36:19 +09:00
isModelAndStaticViewsReady = true ;
2025-12-03 21:19:07 +09:00
// 4. Presenter <20> <> <EFBFBD> <EFBFBD> <20> õ<EFBFBD> (InteractionView<65> <77> <20> <> <EFBFBD> ϵ<EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD>
2025-11-04 11:36:19 +09:00
TryCreatePresenter ( ) ;
}
2025-12-03 21:19:07 +09:00
/// <summary>
/// InteractionView(<28> <> Ʈ<EFBFBD> ѷ<EFBFBD> )<29> <> <20> ʱ<EFBFBD> ȭ<EFBFBD> <C8AD> <20> <> ȣ <> <C8A3> <EFBFBD> Ͽ<EFBFBD> <20> ڽ<EFBFBD> <DABD> <EFBFBD> AppManager<65> <72> <20> <> <EFBFBD> <EFBFBD>
/// </summary>
2025-11-04 11:36:19 +09:00
public void RegisterView ( InteractionView Iview )
{
2025-11-11 13:21:20 +09:00
if ( Iview . handSide = = HandSide . Left )
{
this . leftInteractionView = Iview ;
}
else if ( Iview . handSide = = HandSide . Right )
{
this . rightInteractionView = Iview ;
}
2025-11-04 11:36:19 +09:00
2025-12-03 21:19:07 +09:00
// <20> <> <EFBFBD> <EFBFBD> <20> <> Ʈ<EFBFBD> ѷ<EFBFBD> <D1B7> <EFBFBD> <20> غ<EFBFBD> <D8BA> Ǹ<EFBFBD> Presenter <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> ٽ<EFBFBD> <20> õ<EFBFBD>
2025-11-04 11:36:19 +09:00
TryCreatePresenter ( ) ;
}
2025-12-03 21:19:07 +09:00
/// <summary>
/// <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> (Model, Static Views, Interaction Views)<29> <> <20> غ<EFBFBD> <D8BA> Ǿ<EFBFBD> <C7BE> <EFBFBD> <EFBFBD> <EFBFBD> Ȯ<> <C8AE> <EFBFBD> ϰ<EFBFBD> ,
/// <20> غ<EFBFBD> <D8BA> Ǿ<EFBFBD> <C7BE> ٸ<EFBFBD> Presenter<65> <72> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> Ͽ<EFBFBD> MVP <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> ϼ<EFBFBD>
/// </summary>
2025-11-04 11:36:19 +09:00
private void TryCreatePresenter ( )
{
2025-12-03 21:19:07 +09:00
// <20> ̹<EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> Ǿ<EFBFBD> <C7BE> ų<EFBFBD> , <20> ʼ <EFBFBD> <20> <> <EFBFBD> Ұ<EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> ϸ<EFBFBD> <20> ߴ <EFBFBD>
2025-11-04 11:36:19 +09:00
if ( presenter ! = null ) return ;
2025-11-11 13:21:20 +09:00
if ( ! isModelAndStaticViewsReady | | leftInteractionView = = null | | rightInteractionView = = null )
2025-11-06 15:28:16 +09:00
{
return ;
}
2025-11-19 18:38:48 +09:00
cancellationTokenSource = new CancellationTokenSource ( ) ;
2025-11-06 15:28:16 +09:00
try
{
presenter = new ProgramPresenter (
model ,
view ,
tcpView ,
2025-11-11 18:36:52 +09:00
robotInfoView ,
2025-11-13 21:23:28 +09:00
programInfoView ,
2025-11-14 13:50:31 +09:00
envView ,
2025-11-25 15:15:54 +09:00
gripperCollide ,
2025-11-11 13:21:20 +09:00
leftInteractionView , rightInteractionView ,
2025-11-06 15:28:16 +09:00
pointManagerView ,
popupView ,
2025-11-19 18:38:48 +09:00
pathLineView ,
robotAudio ,
cancellationTokenSource
2025-11-06 15:28:16 +09:00
) ;
}
catch ( Exception e )
{
Debug . LogError ( $"Presenter <20> <> <EFBFBD> <EFBFBD> <EFBFBD> ڿ<EFBFBD> <DABF> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <EFBFBD> : {e.Message}\n{e.StackTrace}" ) ;
return ; // <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD>
}
2025-11-04 11:36:19 +09:00
2025-12-03 21:19:07 +09:00
// <20> ʱ<EFBFBD> ȭ <20> ļ<EFBFBD> <20> ۾<EFBFBD>
2025-10-15 10:39:44 +09:00
presenter . RegisterControlledRobot ( robotController ) ;
2025-12-03 21:19:07 +09:00
_ = presenter . UpdateMotorStateAsync ( ) ; // <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> ʱ<EFBFBD> Ȯ<> <C8AE>
2025-11-04 11:36:19 +09:00
2025-12-03 21:19:07 +09:00
// <20> <> <EFBFBD> <EFBFBD> <D7B6> <EFBFBD> <EFBFBD> <EFBFBD> <20> ۾<EFBFBD> <20> <> <EFBFBD> <EFBFBD> (<28> <> ġ <20> <> <EFBFBD> <EFBFBD> ȭ, <20> <> <EFBFBD> <EFBFBD> üũ <20> <> )
2025-11-04 11:36:19 +09:00
_ = model . GetTCPAsync ( cancellationTokenSource . Token ) ;
_ = model . StartMovementCheckLoopAsync ( cancellationTokenSource . Token ) ;
2025-11-19 18:38:48 +09:00
_ = model . GetMovementState ( cancellationTokenSource . Token ) ;
2025-10-15 10:39:44 +09:00
2025-10-14 16:38:35 +09:00
view . DisplayProgram ( null ) ;
2025-12-03 21:19:07 +09:00
// <20> ֱ<EFBFBD> <D6B1> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> Ȯ<> <C8AE> <20> <> ƾ <20> <> <EFBFBD> <EFBFBD>
2025-10-24 11:55:43 +09:00
StartCoroutine ( PollMotorStateCoroutine ( ) ) ;
2025-10-14 16:38:35 +09:00
}
2025-10-23 18:43:38 +09:00
2025-11-19 18:38:48 +09:00
private void OnDestroy ( )
{
if ( Instance = = this )
{
cancellationTokenSource ? . Cancel ( ) ;
cancellationTokenSource ? . Dispose ( ) ;
}
}
2025-12-03 21:19:07 +09:00
/// <summary>
/// StreamingAssets <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> config.cfg <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> о <EFBFBD> IP<49> <50> Port <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> ε<EFBFBD>
/// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> ⺻<EFBFBD> <E2BABB> (127.0.0.1:8888)<29> <> <20> <> <EFBFBD> <EFBFBD>
/// </summary>
2025-10-23 18:43:38 +09:00
private void LoadConfig ( )
{
// <20> ⺻<EFBFBD> <E2BABB> <20> <> <EFBFBD> <EFBFBD> (<28> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> ã<> <C3A3> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> )
string defaultIp = "127.0.0.1" ;
int defaultPort = 8888 ;
string path = Path . Combine ( Application . streamingAssetsPath , configFileName ) ;
if ( File . Exists ( path ) )
{
try
{
var config = new Dictionary < string , string > ( ) ;
string [ ] lines = File . ReadAllLines ( path ) ;
foreach ( string line in lines )
{
if ( string . IsNullOrWhiteSpace ( line ) | | line . Trim ( ) . StartsWith ( "#" ) )
continue ;
string [ ] parts = line . Split ( '=' ) ;
if ( parts . Length = = 2 )
{
config [ parts [ 0 ] . Trim ( ) ] = parts [ 1 ] . Trim ( ) ;
}
}
if ( config . ContainsKey ( "IP_ADDRESS" ) )
{
hostip = config [ "IP_ADDRESS" ] ;
}
else
{
hostip = defaultIp ;
Debug . LogWarning ( $"config <20> <> <EFBFBD> Ͽ<EFBFBD> IP_ADDRESS Ű<> <C5B0> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> ϴ<EFBFBD> . <20> ⺻<EFBFBD> <E2BABB> ({defaultIp}) <20> <> <EFBFBD> <EFBFBD> ." ) ;
}
if ( config . ContainsKey ( "TCP_PORT" ) )
{
if ( int . TryParse ( config [ "TCP_PORT" ] , out int parsedPort ) )
{
tcpPort = parsedPort ;
}
else
{
tcpPort = defaultPort ;
Debug . LogWarning ( $"config <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> TCP_PORT <20> <> <EFBFBD> <EFBFBD> <20> ߸<EFBFBD> <DFB8> Ǿ<EFBFBD> <C7BE> <EFBFBD> <EFBFBD> ϴ<EFBFBD> . <20> ⺻<EFBFBD> <E2BABB> ({defaultPort}) <20> <> <EFBFBD> <EFBFBD> ." ) ;
}
}
else
{
tcpPort = defaultPort ;
Debug . LogWarning ( $"config <20> <> <EFBFBD> Ͽ<EFBFBD> TCP_PORT Ű<> <C5B0> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> ϴ<EFBFBD> . <20> ⺻<EFBFBD> <E2BABB> ({defaultPort}) <20> <> <EFBFBD> <EFBFBD> ." ) ;
}
if ( config . ContainsKey ( "UDP_PORT" ) )
{
if ( int . TryParse ( config [ "UDP_PORT" ] , out int parsedPort ) )
{
udpPort = parsedPort ;
}
else
{
udpPort = defaultPort ;
Debug . LogWarning ( $"config <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> UDP_PORT <20> <> <EFBFBD> <EFBFBD> <20> ߸<EFBFBD> <DFB8> Ǿ<EFBFBD> <C7BE> <EFBFBD> <EFBFBD> ϴ<EFBFBD> . <20> ⺻<EFBFBD> <E2BABB> ({defaultPort}) <20> <> <EFBFBD> <EFBFBD> ." ) ;
}
}
else
{
udpPort = defaultPort ;
Debug . LogWarning ( $"config <20> <> <EFBFBD> Ͽ<EFBFBD> UDP_PORT Ű<> <C5B0> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> ϴ<EFBFBD> . <20> ⺻<EFBFBD> <E2BABB> ({defaultPort}) <20> <> <EFBFBD> <EFBFBD> ." ) ;
}
Debug . Log ( $"Config <20> ε<EFBFBD> <20> <> <EFBFBD> <EFBFBD> : {hostip}:{tcpPort}/{udpPort}" ) ;
}
catch ( System . Exception e )
{
Debug . LogError ( $"Config <20> <> <EFBFBD> <EFBFBD> <20> ε<EFBFBD> <20> <> <20> <> <EFBFBD> <EFBFBD> <20> <EFBFBD> : {e.Message}. <20> ⺻<EFBFBD> <E2BABB> <20> <> <EFBFBD> <EFBFBD> ." ) ;
hostip = defaultIp ;
tcpPort = defaultPort ;
udpPort = defaultPort ;
}
}
else
{
Debug . LogWarning ( $"{configFileName} <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ã<> <C3A3> <20> <> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> ϴ<EFBFBD> . <20> ⺻<EFBFBD> <E2BABB> ({defaultIp}:{defaultPort}) <20> <> <EFBFBD> <EFBFBD> ." ) ;
hostip = defaultIp ;
tcpPort = defaultPort ;
udpPort = defaultPort ;
}
}
2025-10-24 11:55:43 +09:00
2025-12-03 21:19:07 +09:00
/// <summary>
/// <20> ֱ<EFBFBD> <D6B1> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> κ<EFBFBD> <CEBA> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> (ON/OFF)<29> <> Ȯ<> <C8AE> <EFBFBD> Ͽ<EFBFBD> UI<55> <49> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> ϴ<EFBFBD> <20> ڷ<EFBFBD> ƾ
/// </summary>
2025-10-24 11:55:43 +09:00
private IEnumerator PollMotorStateCoroutine ( )
{
while ( true )
{
yield return new WaitForSeconds ( motorStatePollInterval ) ;
_ = presenter . UpdateMotorStateAsync ( ) ;
}
}
2025-10-14 16:38:35 +09:00
}