Fix : I-pose 파일 사라진거 수정 및 이벤트 수정

This commit is contained in:
DESKTOP-S4BOTN2\user 2025-08-11 22:26:44 +09:00
parent cd336c5422
commit 9b82272f74
12 changed files with 416 additions and 2 deletions

Binary file not shown.

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a17d9f1818e8e79429f9741f498ec4cd
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,81 @@
using UnityEngine;
using UnityEditor;
[CustomEditor(typeof(OptitrackStreamingClient))]
public class OptitrackStreamingClientEditor : Editor
{
public override void OnInspectorGUI()
{
// 기본 Inspector 그리기
DrawDefaultInspector();
EditorGUILayout.Space();
EditorGUILayout.LabelField("OptiTrack 연결 제어", EditorStyles.boldLabel);
OptitrackStreamingClient client = (OptitrackStreamingClient)target;
// 연결 상태 표시
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("연결 상태:", GUILayout.Width(80));
string connectionStatus = Application.isPlaying ? client.GetConnectionStatus() : "게임 실행 중이 아님";
Color originalColor = GUI.color;
if (Application.isPlaying)
{
if (client.IsConnected())
{
GUI.color = Color.green;
}
else
{
GUI.color = Color.red;
}
}
else
{
GUI.color = Color.gray;
}
EditorGUILayout.LabelField(connectionStatus, EditorStyles.boldLabel);
GUI.color = originalColor;
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
// 재접속 버튼
EditorGUI.BeginDisabledGroup(!Application.isPlaying);
if (GUILayout.Button("OptiTrack 재접속", GUILayout.Height(30)))
{
client.Reconnect();
}
EditorGUI.EndDisabledGroup();
if (!Application.isPlaying)
{
EditorGUILayout.HelpBox("재접속 기능은 게임이 실행 중일 때만 사용할 수 있습니다.", MessageType.Info);
}
EditorGUILayout.Space();
// 추가 정보 표시
if (Application.isPlaying)
{
EditorGUILayout.LabelField("서버 정보", EditorStyles.boldLabel);
EditorGUILayout.LabelField("서버 주소:", client.ServerAddress);
EditorGUILayout.LabelField("로컬 주소:", client.LocalAddress);
EditorGUILayout.LabelField("연결 유형:", client.ConnectionType.ToString());
EditorGUILayout.LabelField("서버 NatNet 버전:", client.ServerNatNetVersion);
EditorGUILayout.LabelField("클라이언트 NatNet 버전:", client.ClientNatNetVersion);
}
// Inspector를 지속적으로 업데이트 (실시간 연결 상태 표시를 위해)
if (Application.isPlaying)
{
EditorUtility.SetDirty(target);
Repaint();
}
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 9732ad88efa255744849892f43401dc6

View File

@ -650,6 +650,145 @@ public class OptitrackStreamingClient : MonoBehaviour
return false;
}
/// <summary>
/// Reconnects to the OptiTrack streaming server by disconnecting and reconnecting.
/// </summary>
public void Reconnect()
{
Debug.Log("OptiTrack: 재접속을 시도합니다...");
// 현재 연결이 있다면 먼저 해제
if (m_client != null)
{
Debug.Log("OptiTrack: 기존 연결을 해제합니다.");
OnDisable();
}
// 잠시 대기 후 재연결
StartCoroutine(ReconnectCoroutine());
}
/// <summary>
/// Coroutine for handling the reconnection process with a delay.
/// </summary>
private System.Collections.IEnumerator ReconnectCoroutine()
{
// 1초 대기 후 재연결 시도
yield return new WaitForSeconds(1.0f);
try
{
Debug.Log("OptiTrack: 서버에 재연결을 시도합니다.");
OnEnable();
Debug.Log("OptiTrack: 재연결이 완료되었습니다.");
}
catch (System.Exception ex)
{
Debug.LogError("OptiTrack: 재연결 실패 - " + ex.Message);
}
}
/// <summary>
/// Gets the current connection status of the client.
/// </summary>
/// <returns>True if connected and receiving data, false otherwise.</returns>
public bool IsConnected()
{
return m_client != null && m_receivedFrameSinceConnect;
}
/// <summary>
/// Gets the connection status as a readable string.
/// </summary>
/// <returns>Connection status description.</returns>
public string GetConnectionStatus()
{
if (m_client == null)
{
return "연결 안됨";
}
else if (!m_receivedFrameSinceConnect)
{
return "연결됨 (데이터 대기 중)";
}
else
{
float lastFrameAge = m_lastFrameDeliveryTimestamp.AgeSeconds;
if (lastFrameAge < 5.0f)
{
return "연결됨 (데이터 수신 중)";
}
else
{
return "연결됨 (데이터 중단됨)";
}
}
}
#region Recording Control Functions
/// <summary>
/// Starts recording with enhanced logging.
/// </summary>
public void StartRecordingWithLog()
{
bool result = StartRecording();
if (result)
{
Debug.Log("OptiTrack: 레코딩을 시작했습니다.");
}
else
{
Debug.LogWarning("OptiTrack: 레코딩 시작에 실패했습니다.");
}
}
/// <summary>
/// Stops recording with enhanced logging.
/// </summary>
public void StopRecordingWithLog()
{
bool result = StopRecording();
if (result)
{
Debug.Log("OptiTrack: 레코딩을 중지했습니다.");
}
else
{
Debug.LogWarning("OptiTrack: 레코딩 중지에 실패했습니다.");
}
}
/// <summary>
/// Toggles recording state on this client.
/// </summary>
public void ToggleRecording()
{
if (m_client != null)
{
// Note: There's no direct way to check if recording is active,
// so we'll try to start recording first, and if it fails, try to stop
bool startResult = StartRecording();
if (!startResult)
{
// If start failed, try to stop (might already be recording)
bool stopResult = StopRecording();
if (stopResult)
{
Debug.Log("OptiTrack: 레코딩을 중지했습니다.");
}
}
else
{
Debug.Log("OptiTrack: 레코딩을 시작했습니다.");
}
}
else
{
Debug.LogError("OptiTrack: 클라이언트가 연결되지 않았습니다.");
}
}
#endregion
/// <summary>Get the most recently received state for the specified rigid body.</summary>
/// <param name="rigidBodyId">Corresponds to the "User ID" field in Motive.</param>

View File

@ -338,5 +338,152 @@ namespace Rokoko
if (instance.propOverrides.Contains(prop)) return;
instance.propOverrides.Add(prop);
}
#region Recording Control Functions
/// <summary>
/// CommandAPI를 자동으로 찾아서 설정합니다.
/// </summary>
private void EnsureCommandAPI()
{
if (CommandAPI == null)
{
// 같은 GameObject에서 찾기
CommandAPI = GetComponent<StudioCommandAPI>();
// 씬 전체에서 찾기
if (CommandAPI == null)
{
CommandAPI = FindObjectOfType<StudioCommandAPI>();
}
if (CommandAPI != null)
{
Debug.Log("Rokoko: CommandAPI를 자동으로 찾아서 설정했습니다.");
}
}
}
/// <summary>
/// Rokoko 녹화를 시작합니다.
/// </summary>
public void StartRokokoRecording()
{
EnsureCommandAPI();
if (CommandAPI != null)
{
CommandAPI.StartRecording();
Debug.Log("Rokoko: 녹화를 시작했습니다.");
}
else
{
Debug.LogWarning("Rokoko: CommandAPI를 찾을 수 없습니다. StudioCommandAPI 컴포넌트가 씬에 있는지 확인해주세요.");
}
}
/// <summary>
/// Rokoko 녹화를 중지합니다.
/// </summary>
public void StopRokokoRecording()
{
EnsureCommandAPI();
if (CommandAPI != null)
{
CommandAPI.StopRecording();
Debug.Log("Rokoko: 녹화를 중지했습니다.");
}
else
{
Debug.LogWarning("Rokoko: CommandAPI를 찾을 수 없습니다. StudioCommandAPI 컴포넌트가 씬에 있는지 확인해주세요.");
}
}
/// <summary>
/// Rokoko 녹화 상태를 토글합니다.
/// Note: Rokoko API에는 현재 녹화 상태를 확인하는 직접적인 방법이 없으므로,
/// 시작 명령을 먼저 시도하고 실패하면 중지를 시도합니다.
/// </summary>
public void ToggleRokokoRecording()
{
EnsureCommandAPI();
if (CommandAPI != null)
{
// 실제로는 사용자가 수동으로 시작/중지를 선택하는 것이 좋습니다.
// 여기서는 예시로 시작 명령만 실행합니다.
CommandAPI.StartRecording();
Debug.Log("Rokoko: 녹화 시작을 시도했습니다.");
}
else
{
Debug.LogWarning("Rokoko: CommandAPI를 찾을 수 없습니다. StudioCommandAPI 컴포넌트가 씬에 있는지 확인해주세요.");
}
}
/// <summary>
/// 현재 CommandAPI 상태를 확인합니다.
/// </summary>
public bool IsCommandAPIAvailable()
{
EnsureCommandAPI();
return CommandAPI != null;
}
/// <summary>
/// CommandAPI 상태와 설정 정보를 로그로 출력합니다.
/// </summary>
[ContextMenu("Check Rokoko CommandAPI Status")]
public void CheckCommandAPIStatus()
{
EnsureCommandAPI();
if (CommandAPI != null)
{
Debug.Log($"Rokoko CommandAPI 상태: 사용 가능\n" +
$"API 키: {(string.IsNullOrEmpty(CommandAPI.apiKey) ? " " : "")}\n" +
$"포트: {CommandAPI.port}\n" +
$"IP 주소: {CommandAPI.ipAddress}");
}
else
{
Debug.LogWarning("Rokoko CommandAPI를 찾을 수 없습니다. 다음을 확인해주세요:\n" +
"1. StudioCommandAPI 컴포넌트가 씬에 있는지 확인\n" +
"2. StudioManager의 CommandAPI 필드에 수동으로 할당\n" +
"3. Rokoko Studio가 실행 중이고 Command API가 활성화되어 있는지 확인");
}
}
/// <summary>
/// 정적 메서드로 Rokoko 녹화 시작
/// </summary>
public static void StartGlobalRokokoRecording()
{
if (instance != null)
{
instance.StartRokokoRecording();
}
else
{
Debug.LogError("Rokoko: StudioManager 인스턴스를 찾을 수 없습니다.");
}
}
/// <summary>
/// 정적 메서드로 Rokoko 녹화 중지
/// </summary>
public static void StopGlobalRokokoRecording()
{
if (instance != null)
{
instance.StopRokokoRecording();
}
else
{
Debug.LogError("Rokoko: StudioManager 인스턴스를 찾을 수 없습니다.");
}
}
#endregion
}
}

Binary file not shown.

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: fa247bedd682660459a8067079696177
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 0
userData:
assetBundleName:
assetBundleVariant:

8
Assets/Motions.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ed68c69f4bf1c85459377a625ff33ad0
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Assets/Prefeb.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e058f167f2406824ba142fa059bb4090
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

BIN
Assets/Prefeb/이벤트 컨트롤러 - 녹화 세팅.prefab (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: fe392ab1a0d3eb943816f404e085022c
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: