Maya의 MeshSync를 조금 더 편리하게 만듭니다.

14072 단어 C#mayaUnity

소개



이것은 Maya Advent Calendar 2020 16 일째 기사입니다.

작은 재료이며 알려진지도 모릅니다 만, MeshSync의 도입이나 소개의 안내를 하는데에 신경이 쓰이고 있던 부분이 있었으므로 정리해 보았습니다. 문장 중에는 꽤 Unity 색이 강합니다. 양해 바랍니다.

MeshSync 란 무엇입니까?



복잡하게 정리하면 아티스트 작업에 포커스 한 프로세스 간 통신의 Unity 버전입니다. 애셋의 퀄리티는 반복 횟수에 비례하지만, 최근의 스마트폰 앱 제작은 Unity 측에서 조정하면서 에셋 편집을 하지 않고 퀄리티를 올릴 수 없는 요소가 아마 증가했기 때문에 MeshSync와 같은 실시간 미리보기 기능은 필수입니다.

MeshSync를 이용한 작업의 도선을 생각했을 때,
1. PlayMode 중에 수정할 객체를 찾습니다.
2. Prefab의 FBX 경로를 확인합니다.
3. Maya에서 위의 FBX (ma)를 열고 MeshSync 관련 명령 실행
의 3 단계를 밟을 필요가 자산마다 매회 발생하기 때문에 이것을 하나로 정리하고 싶었습니다.

편집기 확장 스크립트



Maya의 userSetup.py와 같은 아래 준비를 불필요하게 하면서 C# 스크립트 1 파일에 기능을 정리해 보겠습니다. 일부 하드 코드하고 있는 부분이 있으므로, 자신의 환경으로 읽어 주세요.

포인트로서 이하의 조건으로 처리를 분기시키고 있습니다.
  • Maya가 시작되지 않음
  • 명령 줄 인수에 MEL을 전달하여 시작 + 업데이트

  • Maya가 시작 중입니다.
  • commandport에 MEL을 직접 전달하여 업데이트


  • 여담으로 MeshSync 구성 요소의 속성을 Maya로 보내고 싶지만 멤버는 internal입니다.

    액세스하는 방법이 없어도 되지만, 그것들을 포함하면 Adkare 내용의 범위를 벗어나 Unity 쪽에 쓰지 않으면 안 될 것 같으므로, 여기서는 생략합니다.
    using System.Text;
    using System.Diagnostics;
    using System.Net.Sockets;
    using UnityEditor;
    using UnityEngine;
    
    public class RemoteControll
    {
        public static void Send(dynamic request)
        {
            using (var client = new TcpClient("127.0.0.1", 7001))
            {
                var data = Encoding.UTF8.GetBytes(request);
                using (var stream = client.GetStream())
                {
                    stream.Write(data, 0, data.Length);
                }
    
                client.Dispose();
            }
        }
    }
    
    [InitializeOnLoad]
    public static class SceneViewCameraTool
    {
        static SceneViewCameraTool()
        {
            SceneView.onSceneGUIDelegate += (sceneView) =>
            {
                Handles.BeginGUI();
                using (new GUILayout.VerticalScope(GUI.skin.box, GUILayout.Width(100)))
                {
                    GUILayout.Label("Tool");
    
                    if (GUILayout.Button("MeshSync", GUILayout.Width(100)))
                    {
                        var app = "/Applications/Autodesk/maya2017/Maya.app/Contents/bin/maya";
                        var port = "if(`commandPort -q \\\":7001\\\"` == false) commandPort -name \\\":7001\\\";";
                        var cmd = "UnityMeshSync_Export;";
    
                        if (Process.GetProcessesByName("maya").Length > 0)
                        {
                            RemoteControll.Send(
                                cmd +
                                $"viewPlace -p -an true -eye {sceneView.camera.transform.position.x} {sceneView.camera.transform.position.y} {sceneView.camera.transform.position.z} -fov {sceneView.camera.fieldOfView} `lookThru -q`;");
                            return;
                        }
    
                        var selection = Selection.activeGameObject;
                        if (selection != null)
                        {
                            var meshsync = GameObject.Find("MeshSyncServer");
                            if (meshsync == null)
                            {
                                EditorApplication.ExecuteMenuItem("GameObject/MeshSync/Create Server");
                                Selection.activeGameObject = selection;
                            }
    
                            var fbx = AssetDatabase.GetAssetPath(
                                PrefabUtility.GetCorrespondingObjectFromOriginalSource(selection));
                            fbx = Application.dataPath.Replace("Assets", "") + fbx;
    
                            var setup = $"evalDeferred \\\"UnityMeshSync_Settings -p 8080; {cmd}\\\" -lp;";
                            var args = $"-file \"{fbx}\" -hideConsole -nosplash -command \"{port} {setup}\"";
    
                            var process = new Process
                            {
                                StartInfo =
                                {
                                    FileName = app, Arguments = args,
                                    WindowStyle = ProcessWindowStyle.Hidden | ProcessWindowStyle.Minimized,
                                    CreateNoWindow = true
                                }
                            };
                            process.Start();
                        }
                    }
                }
    
                Handles.EndGUI();
            };
        }
    }
    

    평상시는 듀얼 디스플레이로 작업되고 있는 분도 많다고 생각합니다만, 캡쳐의 형편상 1화면으로 수록했습니다. SceneView에서의 확장에 관해서는 완전히 개인적인 취향입니다.



    보충사항
    UnityMeshSync_ ~ 명령은 plugin이 로드된 후에 되므로, evalDeferred 그리고 지연 실행합니다.
    viewPlace 커멘드는 Unity측의 화각을 재현해 보기 위해서, 덤 정도로 사용해 보았습니다.

    Prefab에서 직접 FBX의 경로를 참조하고 있습니다만, 실제로 각 회사 각 프로젝트에 의해 대상을 재작성할 필요가 있을까 생각합니다.

    결론



    내제 엔진 환경이라고 (기분 좋게 사내의 개발자가 만들어 주고 있기 때문에) 그다지 신경쓰지 않았던 것도, 상용 엔진은 그러한 가려운 곳을 스스로 만들어 편리하게 하는지, 지폐로 두드린 자산으로 해결할 수밖에 없습니다.

    세세한 처리에서도 귀찮게 하지 않고 해 두면, 시간 단축이 되어 후가 편해지네요.

    TODO


  • Camera 동기화
  • Material 참조
  • Component 교체
  • 좋은 웹페이지 즐겨찾기