{"id":1274,"date":"2017-09-04T13:36:41","date_gmt":"2017-09-04T05:36:41","guid":{"rendered":"http:\/\/39.100.100.179\/?p=1274"},"modified":"2017-09-08T19:32:11","modified_gmt":"2017-09-08T11:32:11","slug":"unity3d%e4%b9%8beditor%e6%89%a9%e5%b1%95%e5%ad%a6%e4%b9%a0","status":"publish","type":"post","link":"http:\/\/www.u3d8.com\/?p=1274","title":{"rendered":"Unity3D\u4e4bEditor\u6269\u5c55\u5b66\u4e60"},"content":{"rendered":"<p>\u8f6c\u8f7d\uff1a<a href=\"http:\/\/blog.csdn.net\/jjiss318\/article\/details\/7435708#comments\">http:\/\/blog.csdn.net\/jjiss318\/article\/details\/7435708#comments<\/a><\/p>\n<p>Unity3D\u63d0\u4f9b\u4e86\u5f3a\u5927\u7684\u7f16\u8f91\u5668\u6269\u5c55\u673a\u5236\uff0c\u5728\u9879\u76ee\u5f00\u53d1\u4e2d\uff0c\u5982\u679c\u53ef\u4ee5\u5c06\u4e00\u4e9b\u7e41\u7410\u7684\u5de5\u4f5c\u653e\u5728\u7f16\u8f91\u5668\u6269\u5c55\u4e2d\u8fdb\u884c\uff0c\u5219\u4f1a\u5927\u5927\u63d0\u9ad8\u6548\u7387\u3002\u672c\u6587\u5bf9\u7f16\u8f91\u5668\u6269\u5c55\u8fdb\u884c\u4e86\u4e00\u4e9b\u603b\u7ed3\uff0c\u5e0c\u671b\u5bf9\u6709\u5174\u8da3\u7f16\u5199\u7f16\u8f91\u5668\u6269\u5c55\u7684\u5f00\u53d1\u4eba\u5458\u6709\u6240\u5e2e\u52a9\u3002\u5f53\u6211\u4eec\u7f16\u5199\u4e00\u4e2a\u7f16\u8f91\u5668\u6269\u5c55\u65f6\uff0c\u4e00\u822c\u53ef\u4ee5\u4ece\u4ee5\u4e0b\u56db\u4e2a\u7c7b\u7ee7\u627f\uff1a<\/p>\n<p>1 .\u00a0<strong>ScriptableObject \u00a0<\/strong><\/p>\n<p>\u6700\u5e38\u89c1\u7684\u5c0f\u529f\u80fd\u6269\u5c55\uff0c\u4e00\u822c\u4e0d\u7528\u7a97\u53e3\u7684\u7f16\u8f91\u6269\u5c55\uff0c\u53ef\u4ee5\u4ece\u8fd9\u4e2a\u7c7b\u4e2d\u7ee7\u627f\uff0c\u5982\u4ee5\u4e0b\u4ee3\u7801\u6240\u793a\uff1a<\/p>\n<pre class=\"lang:c# decode:true \">using UnityEngine;  \r\nusing UnityEditor;  \r\nusing System.Collections;  \r\n  \r\npublic class AddChild : ScriptableObject  \r\n{  \r\n    [MenuItem (\"GameObject\/Add Child ^n\")]  \r\n    static void MenuAddChild()  \r\n    {  \r\n        Transform[] transforms = Selection.GetTransforms(SelectionMode.TopLevel | SelectionMode.OnlyUserModifiable);  \r\n  \r\n        foreach(Transform transform in transforms)  \r\n        {  \r\n            GameObject newChild = new GameObject(\"_Child\");  \r\n            newChild.transform.parent = transform;  \r\n        }  \r\n    }  \r\n}<\/pre>\n<p>\u8fd9\u4e2a\u6269\u5c55\u811a\u672c\u4ece\u83dc\u5355\u7684\u201cGameObject-&gt;Add Child\u201d\u542f\u52a8\uff0c\u529f\u80fd\u662f\u7ed9Hierarchy\u7a97\u53e3\u4e2d\u9009\u4e2d\u7684\u5bf9GameObject\u6dfb\u52a0\u4e00\u4e2a\u540d\u5b57\u4e3a\u201c_Child\u201d\u7684\u5b50GameObject\uff0c\u8fd9\u6837\u53ef\u4ee5\u514d\u53bb\u4eceHierarchy\u7a97\u53e3\u7684\u6839\u8282\u70b9\u62d6\u62fd\u65b0\u521b\u5efa\u7684GameObject\u5230\u5f53\u524d\u9009\u4e2d\u8282\u70b9\u7684\u9ebb\u70e6\uff0c\u56e0\u4e3a\u5728<a class=\"replace_word\" title=\"Unity3D\u77e5\u8bc6\u5e93\" href=\"http:\/\/lib.csdn.net\/base\/unity3d\" target=\"_blank\">unity3d<\/a>\u7f16\u8f91\u5668\u4e2d\uff0c\u521b\u5efa\u4e00\u4e2aEmptyObject\u4f1a\u5728Hierarchy\u7a97\u53e3\u7684\u6839\u8282\u70b9\u51fa\u73b0\uff0c\u65e0\u8bba\u5f53\u524d\u9009\u4e2d\u7684\u8282\u70b9\u5bf9\u8c61\u662f\u54ea\u4e2a\u3002<\/p>\n<p>2 .<strong>ScriptableWizard \u00a0 \u00a0 \u00a0<\/strong><\/p>\n<p>\u9700\u8981\u5bf9\u6269\u5c55\u7684\u53c2\u6570\u8fdb\u884c\u8bbe\u7f6e\uff0c\u7136\u540e\u518d\u8fdb\u884c\u529f\u80fd\u89e6\u53d1\u7684\uff0c\u53ef\u4ee5\u4ece\u8fd9\u4e2a\u7c7b\u8fdb\u884c\u6d3e\u751f\u3002\u5b83\u5df2\u7ecf\u5b9a\u5236\u597d\u4e86\u56db\u4e2a\u6d88\u606f\u54cd\u5e94\u51fd\u6570\uff0c\u5f00\u53d1\u8005\u5bf9\u5176\u8fdb\u884c\u586b\u5145\u5373\u53ef\u3002<\/p>\n<p>(1)\u00a0OnWizardUpdate<\/p>\n<p>\u5f53\u6269\u5c55\u7a97\u53e3\u6253\u5f00\u65f6\u6216\u7528\u6237\u5bf9\u7a97\u53e3\u7684\u5185\u5bb9\u8fdb\u884c\u6539\u52a8\u65f6\uff0c\u4f1a\u8c03\u7528\u6b64\u51fd\u6570\u3002\u4e00\u822c\u4f1a\u5728\u8fd9\u91cc\u9762\u663e\u793a\u5e2e\u52a9\u6587\u5b57\u548c\u8fdb\u884c\u5185\u5bb9\u6709\u6548\u6027\u9a8c\u8bc1\uff1b<\/p>\n<p>(2)OnWizardCreate<\/p>\n<p>\u8fd9\u662f\u7528\u6237\u70b9\u51fb\u7a97\u53e3\u7684Create\u6309\u94ae\u65f6\u8fdb\u884c\u7684\u64cd\u4f5c\uff0c\u4eceScriptableWizard\u7684\u540d\u5b57\u53ef\u4ee5\u770b\u51fa\uff0c\u8fd9\u662f\u4e00\u79cd\u7c7b\u4f3c\u5411\u5bfc\u7684\u7a97\u53e3\u00a0\uff0c\u800c\u8fd9\u79cd\u7a97\u53e3\u6211\u4eec\u5728Visual Studio\u4e2d\u7ecf\u5e38\u4f1a\u4f7f\u7528\u5230\uff0c\u5982\u4e0b\u56fe\uff1a<\/p>\n<p><a href=\"http:\/\/www.u3d8.com\/wp-content\/uploads\/2017\/09\/1333800452_7379.jpg\" data-lightbox=\"image_lg\"><img title=\"Unity3D\u4e4bEditor\u6269\u5c55\u5b66\u4e60 - \u7b2c1\u5f20  | u3d8\u6280\u672f\u5206\u4eab\" alt=\"Unity3D\u4e4bEditor\u6269\u5c55\u5b66\u4e60 - \u7b2c1\u5f20  | u3d8\u6280\u672f\u5206\u4eab\"  loading=\"lazy\" class=\"size-full wp-image-1275 aligncenter\"  data-src=\"http:\/\/www.u3d8.com\/wp-content\/uploads\/2017\/09\/1333800452_7379.jpg\" width=\"611\" height=\"523\" srcset=\"http:\/\/www.u3d8.com\/wp-content\/uploads\/2017\/09\/1333800452_7379.jpg 611w, http:\/\/www.u3d8.com\/wp-content\/uploads\/2017\/09\/1333800452_7379-300x257.jpg 300w\" sizes=\"(max-width: 611px) 100vw, 611px\" \/><\/a><\/p>\n<p>\u53ea\u4e0d\u8fc7Unity3D\u4e2d\u7684ScriptableWizard\u7a97\u53e3\u53ea\u80fd\u8fdb\u884c\u5c0f\u4e8e\u6216\u7b49\u4e8e\u4e24\u4e2a\u6309\u94ae\u7684\u5b9a\u5236\uff0c\u4e00\u4e2a\u5c31\u662f\u6240\u8c13\u7684Create\u6309\u94ae\uff0c\u53e6\u5916\u4e00\u4e2a\u5219\u7b3c\u7edf\u79f0\u4e4b\u4e3aOther\u6309\u94ae\u3002ScriptableWizard.DisplayWizard\u8fd9\u4e2a\u9759\u6001\u51fd\u6570\u7528\u4e8e\u5bf9ScriptableWizard\u7a97\u53e3\u6807\u9898\u548c\u6309\u94ae\u540d\u5b57\u7684\u5b9a\u5236\u3002<\/p>\n<p>(3)\u00a0OnDrawGizmos<\/p>\n<p>\u5728\u7a97\u53e3\u53ef\u89c1\u65f6\uff0c\u6bcf\u4e00\u5e27\u90fd\u4f1a\u8c03\u7528\u8fd9\u4e2a\u51fd\u6570\u3002\u5728\u5176\u4e2d\u8fdb\u884cGizmos\u7684\u7ed8\u5236\uff0c\u4e5f\u5c31\u662f\u8f85\u52a9\u7f16\u8f91\u7684\u7ebf\u6846\u4f53\u3002Unity\u7684Gizmos\u7c7b\u63d0\u4f9b\u4e86DrawRayDrawLine ,DrawWireSphere ,DrawSphere ,DrawWireCube ,DrawCubeDrawIcon ,DrawGUITexture \u529f\u80fd\u3002\u8fd9\u4e2a\u529f\u80fd\u5728Unity3D \u76843.4\u7248\u672c\u4e2d<a class=\"replace_word\" title=\"\u8f6f\u4ef6\u6d4b\u8bd5\u77e5\u8bc6\u5e93\" href=\"http:\/\/lib.csdn.net\/base\/softwaretest\" target=\"_blank\">\u6d4b\u8bd5<\/a>\u4e86\u4e00\u4e0b\uff0c\u53d1\u73b0\u6ca1\u6709\u4efb\u4f55Gizmos\u7ed8\u5236\u51fa\u6765<img title=\"Unity3D\u4e4bEditor\u6269\u5c55\u5b66\u4e60 - \u7b2c2\u5f20  | u3d8\u6280\u672f\u5206\u4eab\" alt=\"Unity3D\u4e4bEditor\u6269\u5c55\u5b66\u4e60 - \u7b2c2\u5f20  | u3d8\u6280\u672f\u5206\u4eab\" src=\"http:\/\/static.blog.csdn.net\/xheditor\/xheditor_emot\/default\/sad.gif\" \/><\/p>\n<p>(4)\u00a0OnWizardOtherButton<\/p>\n<p>\u672c\u6587\u5728(2) \u4e2d\u5df2\u7ecf\u63d0\u53ca\uff0cScriptableWizard\u7a97\u53e3\u6700\u591a\u53ef\u4ee5\u5b9a\u5236\u4e24\u4e2a\u6309\u94ae\uff0c\u4e00\u4e2a\u662fCreate\uff0c\u53e6\u5916\u4e00\u4e2a\u79f0\u4e4b\u4e3aOther\uff0c\u8fd9\u4e2a\u51fd\u6570\u4f1a\u5728other\u6309\u94ae\u88ab\u70b9\u51fb\u65f6\u8c03\u7528\u3002\u4e0b\u9762\u662f\u4e00\u4e2a\u4f7f\u7528ScriptableWizard\u8fdb\u884c\u7f16\u8f91\u6269\u5c55\u7684\u4f8b\u5b50\uff1a<\/p>\n<pre class=\"lang:c# decode:true \">using UnityEditor;  \r\nusing UnityEngine;  \r\nusing System.Collections;  \r\n  \r\n\/\/\/ &lt;summary&gt;  \r\n\/\/\/ \u5bf9\u4e8e\u9009\u5b9aGameObject\uff0c\u8fdb\u884c\u6307\u5b9acomponent\u7684\u6279\u91cf\u6dfb\u52a0  \r\n\/\/\/ &lt;\/summary&gt;  \r\npublic class AddRemoveComponentsRecursively : ScriptableWizard  \r\n{  \r\n    public string componentType = null;  \r\n  \r\n    \/\/\/ &lt;summary&gt;  \r\n    \/\/\/ \u5f53\u6ca1\u6709\u4efb\u4f55GameObject\u88ab\u9009\u4e2d\u7684\u65f6\u5019\uff0c\u5c06\u83dc\u5355disable\uff08\u6ce8\u610f\uff0c\u8fd9\u4e2a\u51fd\u6570\u540d\u53ef\u4ee5\u968f\u610f\u53d6\uff09  \r\n    \/\/\/ &lt;\/summary&gt;  \r\n    \/\/\/ &lt;returns&gt;&lt;\/returns&gt;  \r\n    [MenuItem(\"GameObject\/Add or remove components recursively...\", true)]  \r\n    static bool CreateWindowDisabled()  \r\n    {  \r\n        return Selection.activeTransform;  \r\n    }  \r\n  \r\n    \/\/\/ &lt;summary&gt;  \r\n    \/\/\/ \u521b\u5efa\u7f16\u8f91\u7a97\u53e3\uff08\u6ce8\u610f\uff0c\u8fd9\u4e2a\u51fd\u6570\u540d\u53ef\u4ee5\u968f\u610f\u53d6\uff09  \r\n    \/\/\/ &lt;\/summary&gt;  \r\n    [MenuItem(\"GameObject\/Add or remove components recursively...\")]  \r\n    static void CreateWindow()  \r\n    {  \r\n        \/\/ \u5b9a\u5236\u7a97\u53e3\u6807\u9898\u548c\u6309\u94ae\uff0c\u5176\u4e2d\u7b2c\u4e8c\u4e2a\u53c2\u6570\u662fCreate\u6309\u94ae\uff0c\u7b2c\u4e09\u4e2a\u5219\u5c5e\u4e8eother\u6309\u94ae  \r\n        \/\/ \u5982\u679c\u4e0d\u60f3\u4f7f\u7528other\u6309\u94ae\uff0c\u5219\u53ef\u8c03\u7528DisplayWizard\u7684\u4e24\u53c2\u6570\u7248\u672c  \r\n        ScriptableWizard.DisplayWizard&lt;AddRemoveComponentsRecursively&gt;(  \r\n            \"Add or remove components recursivly\",  \r\n            \"Add\", \"Remove\");  \r\n    }  \r\n  \r\n    \/\/\/ &lt;summary&gt;  \r\n    \/\/\/ \u7a97\u53e3\u521b\u5efa\u6216\u7a97\u53e3\u5185\u5bb9\u66f4\u6539\u65f6\u8c03\u7528  \r\n    \/\/\/ &lt;\/summary&gt;  \r\n    void OnWizardUpdate()  \r\n    {  \r\n        helpString = \"Note: Duplicates are not created\";  \r\n  \r\n        if (string.IsNullOrEmpty(componentType))  \r\n        {  \r\n            errorString = \"Please enter component class name\";  \r\n            isValid = false;  \r\n        }  \r\n        else  \r\n        {  \r\n            errorString = \"\";  \r\n            isValid = true;  \r\n        }  \r\n    }  \r\n  \r\n    \/\/\/ &lt;summary&gt;  \r\n    \/\/\/ \u70b9\u51fbAdd\u6309\u94ae\uff08\u5373Create\u6309\u94ae\uff09\u8c03\u7528  \r\n    \/\/\/ &lt;\/summary&gt;  \r\n    void OnWizardCreate()  \r\n    {  \r\n        int c = 0;  \r\n        Transform[] ts = Selection.GetTransforms(SelectionMode.Deep);  \r\n        foreach (Transform t in ts)  \r\n        {  \r\n            if (t.gameObject.GetComponent(componentType) == null)  \r\n            {  \r\n                if (t.gameObject.AddComponent(componentType) == null)  \r\n                {  \r\n                    Debug.LogWarning(\"Component of type \" + componentType + \" does not exist\");  \r\n                    return;  \r\n                }  \r\n                c++;  \r\n            }  \r\n        }  \r\n        Debug.Log(\"Added \" + c + \" components of type \" + componentType);  \r\n    }  \r\n  \r\n    \/\/\/ &lt;summary&gt;  \r\n    \/\/\/ \u70b9\u51fbRemove\uff08\u5373other\u6309\u94ae\uff09\u8c03\u7528  \r\n    \/\/\/ &lt;\/summary&gt;  \r\n    void OnWizardOtherButton()  \r\n    {  \r\n        int c = 0;  \r\n        Transform[] ts = Selection.GetTransforms(SelectionMode.Deep);  \r\n        foreach (Transform t in ts)  \r\n        {  \r\n            if (t.GetComponent(componentType) != null)  \r\n            {  \r\n                DestroyImmediate(t.GetComponent(componentType));  \r\n                c++;  \r\n            }  \r\n        }  \r\n        Debug.Log(\"Removed \" + c + \" components of type \" + componentType);  \r\n        Close();  \r\n    }  \r\n}<\/pre>\n<p>\u5176\u8fd0\u884c\u7a97\u53e3\u5982\u4e0b\u6240\u793a\uff1a <a href=\"http:\/\/www.u3d8.com\/wp-content\/uploads\/2017\/09\/1333802898_2557.jpg\" data-lightbox=\"image_lg\"><img title=\"Unity3D\u4e4bEditor\u6269\u5c55\u5b66\u4e60 - \u7b2c3\u5f20  | u3d8\u6280\u672f\u5206\u4eab\" alt=\"Unity3D\u4e4bEditor\u6269\u5c55\u5b66\u4e60 - \u7b2c3\u5f20  | u3d8\u6280\u672f\u5206\u4eab\"  loading=\"lazy\" class=\"aligncenter size-large wp-image-1276\"  data-src=\"http:\/\/www.u3d8.com\/wp-content\/uploads\/2017\/09\/1333802898_2557.jpg\" width=\"326\" height=\"266\" srcset=\"http:\/\/www.u3d8.com\/wp-content\/uploads\/2017\/09\/1333802898_2557.jpg 326w, http:\/\/www.u3d8.com\/wp-content\/uploads\/2017\/09\/1333802898_2557-300x245.jpg 300w\" sizes=\"(max-width: 326px) 100vw, 326px\" \/><\/a><\/p>\n<p><strong>3 .\u00a0<\/strong><strong>EditorWindow<\/strong><\/p>\n<p>\u8f83\u590d\u6742\u7684\u529f\u80fd\uff0c\u9700\u8981\u591a\u4e2a\u7075\u6d3b\u7684\u63a7\u4ef6\uff0c\u5b9e\u73b0\u81ea\u7531\u6d6e\u52a8\u548c\u52a0\u5165\u5176\u4ed6\u7a97\u53e3\u7684tab\uff0c\u53ef\u4ee5\u4ece\u8fd9\u4e2a\u7c7b\u6d3e\u751f\uff0c\u8fd9\u79cd\u7a97\u53e3\u7684\u7a97\u4f53\u529f\u80fd\u548cScene\uff0cHierarchy\u7b49\u7a97\u53e3\u5b8c\u5168\u4e00\u81f4\u3002\u4e0b\u9762\u8fd9\u4e2a\u4f8b\u5b50\u5b9e\u73b0\u4e86GameObject\u7684\u7a7a\u95f4\u5bf9\u9f50\u548c\u62f7\u8d1d\uff08\u4e5f\u5c31\u662f\u5c06GameObject A\u4f5c\u4e3a\u57fa\u51c6\uff0c\u9009\u4e2d\u5176\u4ed6\u7684GameObject\u8fdb\u884c\u5bf9\u51c6\u6216\u7a7a\u95f4\u4f4d\u7f6e\u62f7\u8d1d\uff09\uff0c\u5bf9\u9f50\u548c\u62f7\u8d1d\u63d0\u9ad8\u4e86\u4e86\u5f00\u53d1\u8005\u6446\u653e\u7269\u4ef6\u7684\u6548\u7387\uff1b\u53e6\u5916\u8fd8\u6709\u968f\u673a\u548c\u566a\u58f0\uff0c\u540e\u4e24\u8005\u7528\u4e8e\u6446\u653e\u5927\u91cf\u540c\u7c7b\u7269\u4ef6\u7684\u65f6\u5019\u53ef\u4ee5\u4f7f\u7528\uff0c\u6bd4\u5982\u4e00\u5927\u5806\u6563\u843d\u7684\u74f6\u5b50\u3002<\/p>\n<pre class=\"lang:c# decode:true \">\/\/  \r\n\/\/ Transform Utilities.  \r\n\/\/  \r\n\/\/ This window contains four useful tools for asset placing and manipulation: Align, Copy, Randomize and Add noise.  \r\n\/\/  \r\n\/\/ Put this into Assets\/Editor and once compiled by Unity you find  \r\n\/\/ the new functionality in Window -&gt; TransformUtilities, or simply press Ctrl+t (Cmd+t for Mac users)  \r\n\/\/   \r\n\/\/ Developed by Daniel   \r\n\/\/ http:\/\/www.silentkraken.com  \r\n\/\/ e-mail: seth@silentkraken.com  \r\n\/\/  \r\n\/\/ \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/  \r\n  \r\nusing UnityEngine;  \r\nusing UnityEditor;  \r\n  \r\npublic class TransformUtilitiesWindow : EditorWindow   \r\n{  \r\n    \/\/Window control values  \r\n    public int toolbarOption = 0;  \r\n    public string[] toolbarTexts = {\"Align\", \"Copy\", \"Randomize\", \"Add noise\"};  \r\n  \r\n    private bool xCheckbox = true;  \r\n    private bool yCheckbox = true;  \r\n    private bool zCheckbox = true;  \r\n  \r\n    private Transform source;  \r\n    private float randomRangeMin = 0f;  \r\n    private float randomRangeMax = 1f;  \r\n    private int alignSelectionOption = 0;  \r\n    private int alignSourceOption = 0;  \r\n  \r\n    \/\/\/ &lt;summary&gt;  \r\n    \/\/\/ Retrives the TransformUtilities window or creates a new one  \r\n    \/\/\/ &lt;\/summary&gt;  \r\n    [MenuItem(\"Window\/TransformUtilities %t\")]  \r\n    static void Init()  \r\n    {  \r\n        TransformUtilitiesWindow window = (TransformUtilitiesWindow)EditorWindow.GetWindow(typeof(TransformUtilitiesWindow));  \r\n        window.Show();  \r\n    }  \r\n      \r\n    \/\/\/ &lt;summary&gt;  \r\n    \/\/\/ Window drawing operations  \r\n    \/\/\/ &lt;\/summary&gt;  \r\n    void OnGUI ()   \r\n    {  \r\n        toolbarOption = GUILayout.Toolbar(toolbarOption, toolbarTexts);  \r\n        switch (toolbarOption)  \r\n        {  \r\n            case 0:  \r\n                CreateAxisCheckboxes(\"Align\");  \r\n                CreateAlignTransformWindow();  \r\n                break;  \r\n            case 1:  \r\n                CreateAxisCheckboxes(\"Copy\");  \r\n                CreateCopyTransformWindow();  \r\n                break;  \r\n            case 2:  \r\n                CreateAxisCheckboxes(\"Randomize\");  \r\n                CreateRandomizeTransformWindow();  \r\n                break;  \r\n            case 3:  \r\n                CreateAxisCheckboxes(\"Add noise\");  \r\n                CreateAddNoiseToTransformWindow();  \r\n                break;  \r\n        }  \r\n    }  \r\n  \r\n    \/\/\/ &lt;summary&gt;  \r\n    \/\/\/ Draws the 3 axis checkboxes (x y z)  \r\n    \/\/\/ &lt;\/summary&gt;  \r\n    \/\/\/ &lt;param name=\"operationName\"&gt;&lt;\/param&gt;  \r\n    private void CreateAxisCheckboxes(string operationName)  \r\n    {  \r\n        GUILayout.Label(operationName + \" on axis\", EditorStyles.boldLabel);  \r\n  \r\n        GUILayout.BeginHorizontal();  \r\n            xCheckbox = GUILayout.Toggle(xCheckbox, \"X\");  \r\n            yCheckbox = GUILayout.Toggle(yCheckbox, \"Y\");  \r\n            zCheckbox = GUILayout.Toggle(zCheckbox, \"Z\");  \r\n        GUILayout.EndHorizontal();  \r\n  \r\n        EditorGUILayout.Space();  \r\n    }  \r\n  \r\n    \/\/\/ &lt;summary&gt;  \r\n    \/\/\/ Draws the range min and max fields  \r\n    \/\/\/ &lt;\/summary&gt;  \r\n    private void CreateRangeFields()  \r\n    {  \r\n        GUILayout.Label(\"Range\", EditorStyles.boldLabel);  \r\n        GUILayout.BeginHorizontal();  \r\n        randomRangeMin = EditorGUILayout.FloatField(\"Min:\", randomRangeMin);  \r\n        randomRangeMax = EditorGUILayout.FloatField(\"Max:\", randomRangeMax);  \r\n        GUILayout.EndHorizontal();  \r\n        EditorGUILayout.Space();  \r\n    }  \r\n  \r\n    \/\/\/ &lt;summary&gt;  \r\n    \/\/\/ Creates the Align transform window  \r\n    \/\/\/ &lt;\/summary&gt;  \r\n    private void CreateAlignTransformWindow()  \r\n    {  \r\n        \/\/Source transform  \r\n        GUILayout.BeginHorizontal();  \r\n        GUILayout.Label(\"Align to: \\t\");  \r\n        source = EditorGUILayout.ObjectField(source, typeof(Transform)) as Transform;  \r\n        GUILayout.EndHorizontal();  \r\n  \r\n        string[] texts = new string[4] { \"Min\", \"Max\", \"Center\", \"Pivot\" };  \r\n  \r\n        \/\/Display align options  \r\n        EditorGUILayout.BeginHorizontal();  \r\n        EditorGUILayout.BeginVertical();  \r\n        GUILayout.Label(\"Selection:\", EditorStyles.boldLabel);  \r\n        alignSelectionOption = GUILayout.SelectionGrid(alignSelectionOption, texts, 1);  \r\n        EditorGUILayout.EndVertical();  \r\n        EditorGUILayout.BeginVertical();  \r\n        GUILayout.Label(\"Source:\", EditorStyles.boldLabel);  \r\n        alignSourceOption = GUILayout.SelectionGrid(alignSourceOption, texts, 1);  \r\n        EditorGUILayout.EndVertical();  \r\n        EditorGUILayout.EndHorizontal();  \r\n  \r\n        EditorGUILayout.Space();  \r\n  \r\n        \/\/Position  \r\n        if (GUILayout.Button(\"Align\"))  \r\n        {  \r\n            if (source != null)  \r\n            {  \r\n                \/\/Add a temporary box collider to the source if it doesn't have one  \r\n                Collider sourceCollider = source.collider;  \r\n                bool destroySourceCollider = false;  \r\n                if (sourceCollider == null)  \r\n                {  \r\n                    sourceCollider = source.gameObject.AddComponent&lt;BoxCollider&gt;();  \r\n                    destroySourceCollider = true;  \r\n                }  \r\n  \r\n                foreach (Transform t in Selection.transforms)  \r\n                {  \r\n                    \/\/Add a temporary box collider to the transform if it doesn't have one  \r\n                    Collider transformCollider = t.collider;  \r\n                    bool destroyTransformCollider = false;  \r\n                    if (transformCollider == null)  \r\n                    {  \r\n                        transformCollider = t.gameObject.AddComponent&lt;BoxCollider&gt;();  \r\n                        destroyTransformCollider = true;  \r\n                    }  \r\n  \r\n                    Vector3 sourceAlignData = new Vector3();  \r\n                    Vector3 transformAlignData = new Vector3();  \r\n  \r\n                    \/\/Transform  \r\n                    switch (alignSelectionOption)  \r\n                    {  \r\n                        case 0: \/\/Min  \r\n                            transformAlignData = transformCollider.bounds.min;  \r\n                            break;  \r\n                        case 1: \/\/Max  \r\n                            transformAlignData = transformCollider.bounds.max;  \r\n                            break;  \r\n                        case 2: \/\/Center  \r\n                            transformAlignData = transformCollider.bounds.center;  \r\n                            break;  \r\n                        case 3: \/\/Pivot  \r\n                            transformAlignData = transformCollider.transform.position;  \r\n                            break;  \r\n                    }  \r\n  \r\n                    \/\/Source  \r\n                    switch (alignSourceOption)  \r\n                    {  \r\n                        case 0: \/\/Min  \r\n                            sourceAlignData = sourceCollider.bounds.min;  \r\n                            break;  \r\n                        case 1: \/\/Max  \r\n                            sourceAlignData = sourceCollider.bounds.max;  \r\n                            break;  \r\n                        case 2: \/\/Center  \r\n                            sourceAlignData = sourceCollider.bounds.center;  \r\n                            break;  \r\n                        case 3: \/\/Pivot  \r\n                            sourceAlignData = sourceCollider.transform.position;  \r\n                            break;  \r\n                    }  \r\n  \r\n                    Vector3 tmp = new Vector3();  \r\n                    tmp.x = xCheckbox ? sourceAlignData.x - (transformAlignData.x - t.position.x) : t.position.x;  \r\n                    tmp.y = yCheckbox ? sourceAlignData.y - (transformAlignData.y - t.position.y) : t.position.y;  \r\n                    tmp.z = zCheckbox ? sourceAlignData.z - (transformAlignData.z - t.position.z) : t.position.z;  \r\n  \r\n                    \/\/Register the Undo  \r\n                    Undo.RegisterUndo(t, \"Align \" + t.gameObject.name + \" to \" + source.gameObject.name);  \r\n                    t.position = tmp;  \r\n                      \r\n                    \/\/Ugly hack!  \r\n                    \/\/Unity needs to update the collider of the selection to it's new position  \r\n                    \/\/(it stores in cache the collider data)  \r\n                    \/\/We can force the update by a change in a public variable (shown in the inspector),   \r\n                    \/\/then a call SetDirty to update the collider (it won't work if all inspector variables are the same).  \r\n                    \/\/But we want to restore the changed property to what it was so we do it twice.  \r\n                    transformCollider.isTrigger = !transformCollider.isTrigger;  \r\n                    EditorUtility.SetDirty(transformCollider);  \r\n                    transformCollider.isTrigger = !transformCollider.isTrigger;  \r\n                    EditorUtility.SetDirty(transformCollider);  \r\n  \r\n                    \/\/Destroy the collider we added  \r\n                    if (destroyTransformCollider)  \r\n                    {  \r\n                        DestroyImmediate(transformCollider);  \r\n                    }  \r\n                }  \r\n  \r\n                \/\/Destroy the collider we added  \r\n                if (destroySourceCollider)  \r\n                {  \r\n                    DestroyImmediate(sourceCollider);  \r\n                }  \r\n            }  \r\n            else  \r\n            {  \r\n                EditorUtility.DisplayDialog(\"Error\", \"There is no source transform\", \"Ok\");  \r\n                EditorApplication.Beep();  \r\n            }  \r\n        }  \r\n    }  \r\n  \r\n    \/\/\/ &lt;summary&gt;  \r\n    \/\/\/ Creates the copy transform window  \r\n    \/\/\/ &lt;\/summary&gt;  \r\n    private void CreateCopyTransformWindow()  \r\n    {  \r\n        \/\/Source transform  \r\n        GUILayout.BeginHorizontal();  \r\n            GUILayout.Label(\"Copy from: \\t\");  \r\n            source = EditorGUILayout.ObjectField(source, typeof(Transform)) as Transform;  \r\n        GUILayout.EndHorizontal();  \r\n  \r\n        EditorGUILayout.Space();  \r\n  \r\n        \/\/Position  \r\n        if (GUILayout.Button(\"Copy Position\"))  \r\n        {  \r\n            if (source != null)  \r\n            {  \r\n                foreach (Transform t in Selection.transforms)  \r\n                {  \r\n                    Vector3 tmp = new Vector3();  \r\n                    tmp.x = xCheckbox ? source.position.x : t.position.x;  \r\n                    tmp.y = yCheckbox ? source.position.y : t.position.y;  \r\n                    tmp.z = zCheckbox ? source.position.z : t.position.z;  \r\n  \r\n                    Undo.RegisterUndo(t, \"Copy position\");  \r\n                    t.position = tmp;  \r\n                }  \r\n            }  \r\n            else  \r\n            {  \r\n                EditorUtility.DisplayDialog(\"Error\", \"There is no source transform\", \"Ok\");  \r\n                EditorApplication.Beep();  \r\n            }  \r\n        }  \r\n  \r\n        \/\/Rotation  \r\n        if (GUILayout.Button(\"Copy Rotation\"))  \r\n        {  \r\n            if (source != null)  \r\n            {  \r\n                foreach (Transform t in Selection.transforms)  \r\n                {  \r\n                    Vector3 tmp = new Vector3();  \r\n                    tmp.x = xCheckbox ? source.rotation.eulerAngles.x : t.rotation.eulerAngles.x;  \r\n                    tmp.y = yCheckbox ? source.rotation.eulerAngles.y : t.rotation.eulerAngles.y;  \r\n                    tmp.z = zCheckbox ? source.rotation.eulerAngles.z : t.rotation.eulerAngles.z;  \r\n                    Quaternion tmp2 = t.rotation;  \r\n                    tmp2.eulerAngles = tmp;  \r\n  \r\n                    Undo.RegisterUndo(t, \"Copy rotation\");  \r\n                    t.rotation = tmp2;  \r\n                }  \r\n            }  \r\n            else  \r\n            {  \r\n                EditorUtility.DisplayDialog(\"Error\", \"There is no source transform\", \"Ok\");  \r\n                EditorApplication.Beep();  \r\n            }  \r\n        }  \r\n  \r\n        \/\/Local Scale  \r\n        if (GUILayout.Button(\"Copy Local Scale\"))  \r\n        {  \r\n            if (source != null)  \r\n            {  \r\n                foreach (Transform t in Selection.transforms)  \r\n                {  \r\n                    Vector3 tmp = new Vector3();  \r\n                    tmp.x = xCheckbox ? source.localScale.x : t.localScale.x;  \r\n                    tmp.y = yCheckbox ? source.localScale.y : t.localScale.y;  \r\n                    tmp.z = zCheckbox ? source.localScale.z : t.localScale.z;  \r\n  \r\n                    Undo.RegisterUndo(t, \"Copy local scale\");  \r\n                    t.localScale = tmp;  \r\n                }  \r\n            }  \r\n            else  \r\n            {  \r\n                EditorUtility.DisplayDialog(\"Error\", \"There is no source transform\", \"Ok\");  \r\n                EditorApplication.Beep();  \r\n            }  \r\n        }  \r\n    }  \r\n  \r\n    \/\/\/ &lt;summary&gt;  \r\n    \/\/\/ Creates the Randomize transform window  \r\n    \/\/\/ &lt;\/summary&gt;  \r\n    private void CreateRandomizeTransformWindow()  \r\n    {  \r\n        CreateRangeFields();  \r\n  \r\n        \/\/Position  \r\n        if (GUILayout.Button(\"Randomize Position\"))  \r\n        {  \r\n            foreach (Transform t in Selection.transforms)  \r\n            {  \r\n                Vector3 tmp = new Vector3();  \r\n                tmp.x = xCheckbox ? Random.Range(randomRangeMin, randomRangeMax) : t.position.x;  \r\n                tmp.y = yCheckbox ? Random.Range(randomRangeMin, randomRangeMax) : t.position.y;  \r\n                tmp.z = zCheckbox ? Random.Range(randomRangeMin, randomRangeMax) : t.position.z;  \r\n  \r\n                Undo.RegisterUndo(t, \"Randomize position\");  \r\n                t.position = tmp;  \r\n            }  \r\n        }  \r\n  \r\n        \/\/Rotation  \r\n        if (GUILayout.Button(\"Randomize Rotation\"))  \r\n        {  \r\n            foreach (Transform t in Selection.transforms)  \r\n            {  \r\n                Vector3 tmp = new Vector3();  \r\n                tmp.x = xCheckbox ? Random.Range(randomRangeMin, randomRangeMax) : t.rotation.eulerAngles.x;  \r\n                tmp.y = yCheckbox ? Random.Range(randomRangeMin, randomRangeMax) : t.rotation.eulerAngles.y;  \r\n                tmp.z = zCheckbox ? Random.Range(randomRangeMin, randomRangeMax) : t.rotation.eulerAngles.z;  \r\n                Quaternion tmp2 = t.rotation;  \r\n                tmp2.eulerAngles = tmp;  \r\n  \r\n                Undo.RegisterUndo(t, \"Randomize rotation\");  \r\n                t.rotation = tmp2;  \r\n            }  \r\n        }  \r\n  \r\n        \/\/Local Scale  \r\n        if (GUILayout.Button(\"Randomize Local Scale\"))  \r\n        {  \r\n            foreach (Transform t in Selection.transforms)  \r\n            {  \r\n                Vector3 tmp = new Vector3();  \r\n                tmp.x = xCheckbox ? Random.Range(randomRangeMin, randomRangeMax) : t.localScale.x;  \r\n                tmp.y = yCheckbox ? Random.Range(randomRangeMin, randomRangeMax) : t.localScale.y;  \r\n                tmp.z = zCheckbox ? Random.Range(randomRangeMin, randomRangeMax) : t.localScale.z;  \r\n  \r\n                Undo.RegisterUndo(t, \"Randomize local scale\");  \r\n                t.localScale = tmp;  \r\n            }  \r\n        }  \r\n    }  \r\n  \r\n    \/\/\/ &lt;summary&gt;  \r\n    \/\/\/ Creates the Add Noise To Transform window  \r\n    \/\/\/ &lt;\/summary&gt;  \r\n    private void CreateAddNoiseToTransformWindow()  \r\n    {  \r\n        CreateRangeFields();  \r\n  \r\n        \/\/Position  \r\n        if (GUILayout.Button(\"Add noise to Position\"))  \r\n        {  \r\n            foreach (Transform t in Selection.transforms)  \r\n            {  \r\n                Vector3 tmp = new Vector3();  \r\n                tmp.x = xCheckbox ? Random.Range(randomRangeMin, randomRangeMax) : 0;  \r\n                tmp.y = yCheckbox ? Random.Range(randomRangeMin, randomRangeMax) : 0;  \r\n                tmp.z = zCheckbox ? Random.Range(randomRangeMin, randomRangeMax) : 0;  \r\n  \r\n                Undo.RegisterUndo(t, \"Add noise to position\");  \r\n                t.position += tmp;  \r\n            }  \r\n        }  \r\n  \r\n        \/\/Rotation  \r\n        if (GUILayout.Button(\"Add noise to Rotation\"))  \r\n        {  \r\n            foreach (Transform t in Selection.transforms)  \r\n            {  \r\n                Vector3 tmp = new Vector3();  \r\n                tmp.x = xCheckbox ?  t.rotation.eulerAngles.x + Random.Range(randomRangeMin, randomRangeMax) : 0;  \r\n                tmp.y = yCheckbox ?  t.rotation.eulerAngles.y + Random.Range(randomRangeMin, randomRangeMax) : 0;  \r\n                tmp.z = zCheckbox ?  t.rotation.eulerAngles.z + Random.Range(randomRangeMin, randomRangeMax) : 0;  \r\n  \r\n                Undo.RegisterUndo(t, \"Add noise to rotation\");  \r\n                t.rotation = Quaternion.Euler(tmp);  \r\n            }  \r\n        }  \r\n  \r\n        \/\/Local Scale  \r\n        if (GUILayout.Button(\"Add noise to Local Scale\"))  \r\n        {  \r\n            foreach (Transform t in Selection.transforms)  \r\n            {  \r\n                Vector3 tmp = new Vector3();  \r\n                tmp.x = xCheckbox ? Random.Range(randomRangeMin, randomRangeMax) : 0;  \r\n                tmp.y = yCheckbox ? Random.Range(randomRangeMin, randomRangeMax) : 0;  \r\n                tmp.z = zCheckbox ? Random.Range(randomRangeMin, randomRangeMax) : 0;  \r\n  \r\n                Undo.RegisterUndo(t, \"Add noise to local scale\");  \r\n                t.localScale += tmp;  \r\n            }  \r\n        }  \r\n    }  \r\n}<\/pre>\n<p>\u5176\u7a97\u53e3\u5982\u4e0b\u56fe\u6240\u793a\uff1a<\/p>\n<p><a href=\"http:\/\/www.u3d8.com\/wp-content\/uploads\/2017\/09\/1333814545_3246.jpg\" data-lightbox=\"image_lg\"><img title=\"Unity3D\u4e4bEditor\u6269\u5c55\u5b66\u4e60 - \u7b2c4\u5f20  | u3d8\u6280\u672f\u5206\u4eab\" alt=\"Unity3D\u4e4bEditor\u6269\u5c55\u5b66\u4e60 - \u7b2c4\u5f20  | u3d8\u6280\u672f\u5206\u4eab\"  loading=\"lazy\" class=\"aligncenter size-full wp-image-1277\"  data-src=\"http:\/\/www.u3d8.com\/wp-content\/uploads\/2017\/09\/1333814545_3246.jpg\" width=\"329\" height=\"278\" srcset=\"http:\/\/www.u3d8.com\/wp-content\/uploads\/2017\/09\/1333814545_3246.jpg 329w, http:\/\/www.u3d8.com\/wp-content\/uploads\/2017\/09\/1333814545_3246-300x253.jpg 300w\" sizes=\"(max-width: 329px) 100vw, 329px\" \/><\/a><\/p>\n<p><strong>4.\u00a0<\/strong><strong>Editor<\/strong><\/p>\n<p>\u5bf9\u67d0\u81ea\u5b9a\u4e49\u7ec4\u4ef6\u8fdb\u884c\u89c2\u5bdf\u7684Inspector\u7a97\u53e3\uff0c\u53ef\u4ee5\u4ece\u5b83\u6d3e\u751f\u3002\u5982\u4e0b\u4ee3\u7801\u6240\u793a\uff1a<\/p>\n<p>\u4ee3\u7801\u7247\u6bb51\u5b9a\u4e49\u4e86\u4e00\u4e2a\u540d\u4e3aStar\u7684\u7ec4\u4ef6\uff1a<\/p>\n<pre class=\"lang:c# decode:true \">using System;  \r\nusing UnityEngine;  \r\n  \r\n[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]  \r\npublic class Star : MonoBehaviour {  \r\n  \r\n    [Serializable]  \r\n    public class Point {  \r\n        public Color color;  \r\n        public Vector3 offset;  \r\n    }  \r\n  \r\n    public Point[] points;  \r\n    public int frequency = 1;  \r\n    public Color centerColor;  \r\n  \r\n    private Mesh mesh;  \r\n    private Vector3[] vertices;  \r\n    private Color[] colors;  \r\n    private int[] triangles;  \r\n  \r\n    void Start () {  \r\n        GetComponent&lt;MeshFilter&gt;().mesh = mesh = new Mesh();  \r\n        mesh.name = \"Star Mesh\";  \r\n  \r\n        if(frequency &lt; 1){  \r\n            frequency = 1;  \r\n        }  \r\n        if(points == null || points.Length == 0){  \r\n            points = new Point[]{ new Point()};  \r\n        }  \r\n  \r\n        int numberOfPoints = frequency * points.Length;  \r\n        vertices = new Vector3[numberOfPoints + 1];  \r\n        colors = new Color[numberOfPoints + 1];  \r\n        triangles = new int[numberOfPoints * 3];  \r\n        float angle = -360f \/ numberOfPoints;  \r\n        colors[0] = centerColor;  \r\n        for(int iF = 0, v = 1, t = 1; iF &lt; frequency; iF++){  \r\n            for(int iP = 0; iP &lt; points.Length; iP += 1, v += 1, t += 3){  \r\n                vertices[v] = Quaternion.Euler(0f, 0f, angle * (v - 1)) * points[iP].offset;  \r\n                colors[v] = points[iP].color;  \r\n                triangles[t] = v;  \r\n                triangles[t + 1] = v + 1;  \r\n            }  \r\n        }  \r\n        triangles[triangles.Length - 1] = 1;  \r\n  \r\n        mesh.vertices = vertices;  \r\n        mesh.colors = colors;  \r\n        mesh.triangles = triangles;  \r\n    }  \r\n}<\/pre>\n<p>\u4ee3\u7801\u7247\u6bb52\u5b9a\u4e49\u4e86\u5bf9Star\u7ec4\u4ef6\u8fdb\u884c\u89c2\u6d4b\u7684Inspector\u7a97\u53e3\uff1a<\/p>\n<pre class=\"lang:c# decode:true \">using UnityEditor;  \r\nusing UnityEngine;  \r\n  \r\n[CustomEditor(typeof(Star))]  \r\npublic class StarInspector : Editor {  \r\n  \r\n    private static GUIContent  \r\n        insertContent = new GUIContent(\"+\", \"duplicate this point\"),  \r\n        deleteContent = new GUIContent(\"-\", \"delete this point\"),  \r\n        pointContent = GUIContent.none;  \r\n  \r\n    private static GUILayoutOption  \r\n        buttonWidth = GUILayout.MaxWidth(20f),  \r\n        colorWidth = GUILayout.MaxWidth(50f);  \r\n  \r\n    private SerializedObject star;  \r\n    private SerializedProperty  \r\n        points,  \r\n        frequency,  \r\n        centerColor;  \r\n  \r\n    void OnEnable () { \u2026 }  \r\n  \r\n    public override void OnInspectorGUI () {  \r\n        star.Update();  \r\n  \r\n        GUILayout.Label(\"Points\");  \r\n        for(int i = 0; i &lt; points.arraySize; i++){  \r\n            EditorGUILayout.BeginHorizontal();  \r\n            SerializedProperty point = points.GetArrayElementAtIndex(i);  \r\n            EditorGUILayout.PropertyField(point.FindPropertyRelative(\"offset\"), pointContent);  \r\n            EditorGUILayout.PropertyField(point.FindPropertyRelative(\"color\"), pointContent, colorWidth);  \r\n  \r\n            if(GUILayout.Button(insertContent, EditorStyles.miniButtonLeft, buttonWidth)){  \r\n                points.InsertArrayElementAtIndex(i);  \r\n            }  \r\n            if(GUILayout.Button(deleteContent, EditorStyles.miniButtonRight, buttonWidth)){  \r\n                points.DeleteArrayElementAtIndex(i);  \r\n            }  \r\n  \r\n            EditorGUILayout.EndHorizontal();  \r\n        }  \r\n  \r\n        EditorGUILayout.PropertyField(frequency);  \r\n        EditorGUILayout.PropertyField(centerColor);  \r\n  \r\n        star.ApplyModifiedProperties();  \r\n    }  \r\n}<\/pre>\n<p>\u5176Inspector\u7a97\u53e3\u5982\u4e0b\u56fe\u6240\u793a\uff1a<\/p>\n<p><a href=\"http:\/\/www.u3d8.com\/wp-content\/uploads\/2017\/09\/1333804978_9205.jpg\" data-lightbox=\"image_lg\"><img title=\"Unity3D\u4e4bEditor\u6269\u5c55\u5b66\u4e60 - \u7b2c5\u5f20  | u3d8\u6280\u672f\u5206\u4eab\" alt=\"Unity3D\u4e4bEditor\u6269\u5c55\u5b66\u4e60 - \u7b2c5\u5f20  | u3d8\u6280\u672f\u5206\u4eab\"  loading=\"lazy\" class=\"aligncenter size-full wp-image-1278\"  data-src=\"http:\/\/www.u3d8.com\/wp-content\/uploads\/2017\/09\/1333804978_9205.jpg\" width=\"348\" height=\"188\" srcset=\"http:\/\/www.u3d8.com\/wp-content\/uploads\/2017\/09\/1333804978_9205.jpg 348w, http:\/\/www.u3d8.com\/wp-content\/uploads\/2017\/09\/1333804978_9205-300x162.jpg 300w\" sizes=\"(max-width: 348px) 100vw, 348px\" \/><\/a><\/p>\n<p>\u8bf4\u5230\u8fd9\u91cc\uff0c\u5927\u5bb6\u5bf9ScriptableObject,\u00a0ScriptableWizard, EditorWindow\u548cEditor\u5e94\u8be5\u90fd\u6709\u5e94\u6709\u4e86\u4e00\u5b9a\u4e86\u89e3\u3002\u5176\u4e2dEditorWindow\u548cEditor\u90fd\u7ee7\u627f\u4e86ScriptableObject\uff0c\u800cScritableWizard\u5219\u7ee7\u627f\u4e86EditorWindow\u6d3e\u3002\u5728\u5b9e\u9645\u5f00\u53d1\u5e94\u7528\u4e2d\uff0c\u5e94\u8be5\u6839\u636e\u9700\u6c42\u7684\u7279\u70b9\uff0c\u7075\u6d3b\u4f7f\u7528\u8fd9\u56db\u4e2a\u7c7b\u8fdb\u884c\u7f16\u8f91\u5668\u6269\u5c55\u3002<\/p>\n<p>\u53c2\u8003\u8d44\u6599\uff1a<\/p>\n<p>1.\u00a0<a href=\"http:\/\/catlikecoding.com\/unity\/tutorials\/star\/\" target=\"_blank\">http:\/\/catlikecoding.com\/unity\/tutorials\/star\/<\/a><\/p>\n<p>2.\u00a0<a href=\"http:\/\/www.unifycommunity.com\/wiki\" target=\"_blank\">http:\/\/www.unifycommunity.com\/wiki<\/a><\/p>\n<p>3. <a href=\"http:\/\/www.blog.silentkraken.com\/2010\/02\/06\/transformutilities\/\">http:\/\/www.blog.silentkraken.com\/2010\/02\/06\/transformutilities\/<\/a><\/p>\n<p>4.<a href=\"http:\/\/unity3d.com\/support\/documentation\/ScriptReference\" target=\"_blank\">http:\/\/unity3d.com\/support\/documentation\/ScriptReference<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u8f6c\u8f7d\uff1ahttp:\/\/blog.csdn.net\/jjiss318\/article &hellip; <a href=\"http:\/\/www.u3d8.com\/?p=1274\">\u7ee7\u7eed\u9605\u8bfb <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[297],"tags":[294,296,295,293],"_links":{"self":[{"href":"http:\/\/www.u3d8.com\/index.php?rest_route=\/wp\/v2\/posts\/1274"}],"collection":[{"href":"http:\/\/www.u3d8.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.u3d8.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.u3d8.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.u3d8.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1274"}],"version-history":[{"count":2,"href":"http:\/\/www.u3d8.com\/index.php?rest_route=\/wp\/v2\/posts\/1274\/revisions"}],"predecessor-version":[{"id":1280,"href":"http:\/\/www.u3d8.com\/index.php?rest_route=\/wp\/v2\/posts\/1274\/revisions\/1280"}],"wp:attachment":[{"href":"http:\/\/www.u3d8.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1274"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.u3d8.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1274"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.u3d8.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1274"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}