分享

Unity很多容易遗漏的地方

 tiancaiwrk 2018-08-03

一. 编辑器下复制Component的快捷方式:
     UnityEditorInternal.ComponentUtility.CopyComponent(from);
     UnityEditorInternal.ComponentUtility.PasteComponentValues(to);
     UnityEditorInternal.ComponentUtility.PasteComponentAsNew(gameObject);

二. 创建UI节点的方式:
     new GameObject("Name", typeof(RectTransform)); // 这样才会给你创建RectTransform

三. 获取BuildSettings里面场景的信息方式:
     var scenes = UnityEditor.EditorBuildSettings.scenes;
     var activeScenes = UnityEditor.EditorBuildSettingsScene.GetActiveSceneList(scenes );

四. 任意位置的选择菜单:
     UnityEditor.EditorUtility.DisplayCustomMenu -- 指定位置出现菜单
     UnityEditor.GenericMenu -- 在当前鼠标位置出现

五. 初始化顺序:
     场景读取以及场景中的脚本的初始化顺序如下
     1. Awake
     2. UnityEngine.SceneManagement.SceneManager.sceneLoaded
     3. Start

六. 关于CustomPropertyDrawer的使用, 下面有个例子:
​using System;
using UnityEditor;
using UnityEngine;

​public class EnumFlagAttribute : UnityEngine.PropertyAttribute
{
    public EnumFlagAttribute() {}
}​
​[CustomPropertyDrawer(typeof(EnumFlagAttribute))]
public class EnumFlagsAttributeDrawer : PropertyDrawer
{
 
    public override void OnGUI(Rect _position, SerializedProperty _property, GUIContent _label)
    {
        int buttonsIntValue = 0;
        int enumLength = _property.enumNames.Length;
        bool[] buttonPressed = new bool[enumLength];
        float buttonWidth = (_position.width - EditorGUIUtility.labelWidth) / enumLength;
 
        EditorGUI.LabelField(new Rect(_position.x, _position.y, EditorGUIUtility.labelWidth, _position.height), _label);
 
        EditorGUI.BeginChangeCheck ();
 
        for (int i = 0; i < enumLength; i++) {
 
            // Check if the button is/was pressed
            if ( ( _property.intValue & (1 << i) ) == 1 << i ) {
                buttonPressed[i] = true;
            }
 
            Rect buttonPos = new Rect (_position.x + EditorGUIUtility.labelWidth + buttonWidth * i, _position.y, buttonWidth, _position.height);
 
            buttonPressed[i] = GUI.Toggle(buttonPos, buttonPressed[i], _property.enumNames[i],  "Button");
 
            if (buttonPressed[i])
                buttonsIntValue += 1 << i;
        }
 
        if (EditorGUI.EndChangeCheck()) {
            _property.intValue = buttonsIntValue;
        }
    }
}
​给Enum变量添加这个属性之后, 就会被按照代码的方式进行绘制(Inspector)

​七. 入口函数是可以做的, 使用属性
​ [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
​被标记的静态函数会在程序启动后第一个调用, 如果打包之后没有打包场景的情况下,
​Unity会自动生成一个默认场景, 这样在这个函数里读取场景的话, 应该就能把自动生成的
​场景给顶掉.

​八. 菜单的Toggle方式
​        const string T1Name = "Tools/Test/TT/T1";
        private static bool selected = false;

        [MenuItem(T1Name, true, 105)]
        public static bool T1_Init()
        {
            Menu.SetChecked(T1Name, selected);
            return true;
        }

        [MenuItem(T1Name, false, 105)]
        public static void T1_Func()
        {
            selected = false == selected;
            Menu.SetChecked(T1Name, selected);
        }
​想要给一个菜单提供Toggle的可视化, 需要使用两个函数, 一个是Init就是在每次菜单展开
​之前都会调用一次, 然后Menu.SetChecked标记这个菜单的Toggle UI, 每次点击则进入
​T1_Func函数,

​九. 在有自动布局组件的时候(UnityEngine.UI.LayoutGroup) 可能是
        ​HorizontalLayoutGroup,
​        VerticalLayoutGroup,
​        Grid 等, 在重新设置了里面的元素之后, 它不会自动刷新, 需要手动调用
​LayoutRebuilder.ForceRebuildLayoutImmediate(rect);
​        PS : 在很多情况下, 这个函数也不是那么好用的, 实际情况还是需要 关闭-打开 组件的
​        方式才能​正确让它重排, 我要吐血了, 测试了很多方法, 只有下面这类的才能正确排列
​// Do Sth    
​Core.CoroutineRoot.Instance.RunWaitFrames(2, () =>
{
                    this.transform.LoopComponentsInChildren<LayoutGroup>((_group) =>
                    {
                        _group.enabled = false;
                        _group.enabled = true;
                    });
                    LayoutRebuilder.ForceRebuildLayoutImmediate(this.rect);               
​ });
          

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多