unity3d 场景管理器插件_unity3d 场景管理算法 - CSDN
精华内容
参与话题
  • Unity3D 11-SceneManager场景管理用法总结

    万次阅读 2017-07-04 16:58:39
    一、Unity关卡Unity 使用过程中关卡加载和卸载是大多数三维引擎都要提供的基本功能。 因为关卡切换在游戏中非常常用。 在之前的版本中Unity的关卡切换使用的是:Application.loadedLevel();看看Application类,...

    一、Unity关卡

    Unity 使用过程中关卡加载和卸载是大多数三维引擎都要提供的基本功能。
    因为关卡切换在游戏中非常常用。
    在之前的版本中Unity的关卡切换使用的是:

    Application.loadedLevel();

    看看Application类,此时这个类的功能比较繁杂,比较多。只看与关卡相关的:

     [Obsolete("Use SceneManager.LoadScene")]
            public static void LoadLevel(string name);
    
            [Obsolete("Use SceneManager.LoadScene")]
            public static void LoadLevel(int index);
    
            [Obsolete("Use SceneManager.LoadScene")]
            public static void LoadLevelAdditive(string name);
    
            [Obsolete("Use SceneManager.LoadScene")]
            public static void LoadLevelAdditive(int index);
      //
            // 摘要:
            //     ///
            //     Unloads all GameObject associated with the given scene. Note that assets are
            //     currently not unloaded, in order to free up asset memory call Resources.UnloadAllUnusedAssets.
            //     ///
            //
            // 参数:
            //   index:
            //     Index of the scene in the PlayerSettings to unload.
            //
            //   scenePath:
            //     Name of the scene to Unload.
            //
            // 返回结果:
            //     ///
            //     Return true if the scene is unloaded.
            //     ///
            [Obsolete("Use SceneManager.UnloadScene")]
            public static bool UnloadLevel(string scenePath);
            //
            // 摘要:
            //     ///
            //     Unloads all GameObject associated with the given scene. Note that assets are
            //     currently not unloaded, in order to free up asset memory call Resources.UnloadAllUnusedAssets.
            //     ///
            //
            // 参数:
            //   index:
            //     Index of the scene in the PlayerSettings to unload.
            //
            //   scenePath:
            //     Name of the scene to Unload.
            //
            // 返回结果:
            //     ///
            //     Return true if the scene is unloaded.
            //     ///
            [Obsolete("Use SceneManager.UnloadScene")]
            public static bool UnloadLevel(int index);

    注解:
    这是之前的Application中的关卡的加载和卸载。
    当然现在在新版本(Unity5.3以上)中,有了新的变化,那就是SceneManager类了处理。

    二、Untiy的SceneManager类

    自从Unity5.3版本,Unity 的关卡切换就添加了新的SceneManager的类来处理。
    当然要安装过了Unity文档帮助,并且给下面路径一样,就可以知道在本地打开。
    本地链接:
    file:///C:/Program%20Files/Unity5.3.0/Editor/Data/Documentation/en/Manual/UpgradeGuide53.html
    也可以在Unity中搜索SceneManager来查看。

    #region 程序集 UnityEngine, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
    // H:\Unity\UnityProject\ShiftLevels\Library\UnityAssemblies\UnityEngine.dll
    #endregion
    
    using UnityEngine.Internal;
    
    namespace UnityEngine.SceneManagement
    {
        //
        // 摘要:
        //     ///
        //     Scene management at run-time.
        //     ///
        public class SceneManager
        {
            public SceneManager();
    
    
            public static int sceneCount { get; }
            //
    
            public static int sceneCountInBuildSettings { get; }
    
    
            public static Scene GetActiveScene();
    
            public static Scene[] GetAllScenes();
            // 参数:
            //   index:
            //     Index of the scene to get. Index must be greater than or equal to 0 and less
            //     than SceneManager.sceneCount.
            public static Scene GetSceneAt(int index);
    
            // 返回结果:
            //     ///
            //     The scene if found or an invalid scene if not.
            //     ///
            public static Scene GetSceneByName(string name);
    
            //     Searches all scenes added to the SceneManager for a scene that has the given
            //     asset path.
            //     ///
            //
            // 参数:
            //   scenePath:
            //     Path of the scene. Should be relative to the project folder. Like: "AssetsMyScenesMyScene.unity".
            public static Scene GetSceneByPath(string scenePath);
            [ExcludeFromDocs]
            public static void LoadScene(int sceneBuildIndex);
            [ExcludeFromDocs]
            public static void LoadScene(string sceneName);
    
            // 参数:
            //   sceneName:
            //     Name of the scene to load.
            //
            //   sceneBuildIndex:
            //     Index of the scene in the Build Settings to load.
            //
            //   mode:
            //     Allows you to specify whether or not to load the scene additively. See SceneManagement.LoadSceneMode
            //     for more information about the options.
            public static void LoadScene(int sceneBuildIndex, [DefaultValue("LoadSceneMode.Single")] LoadSceneMode mode);
    
            // 参数:
            //   sceneName:
            //     Name of the scene to load.
            //
            //   sceneBuildIndex:
            //     Index of the scene in the Build Settings to load.
            //
            //   mode:
            //     Allows you to specify whether or not to load the scene additively. See SceneManagement.LoadSceneMode
            //     for more information about the options.
            public static void LoadScene(string sceneName, [DefaultValue("LoadSceneMode.Single")] LoadSceneMode mode);
            [ExcludeFromDocs]
            public static AsyncOperation LoadSceneAsync(int sceneBuildIndex);
            [ExcludeFromDocs]
            public static AsyncOperation LoadSceneAsync(string sceneName);
    
            // 参数:
            //   sceneName:
            //     Name of the scene to load.
            //
            //   sceneBuildIndex:
            //     Index of the scene in the Build Settings to load.
            //
            //   mode:
            //     If LoadSceneMode.Single then all current scenes will be unloaded before loading.
            public static AsyncOperation LoadSceneAsync(int sceneBuildIndex, [DefaultValue("LoadSceneMode.Single")] LoadSceneMode mode);
    
            // 参数:
            //   sceneName:
            //     Name of the scene to load.
            //
            //   sceneBuildIndex:
            //     Index of the scene in the Build Settings to load.
            //
            //   mode:
            //     If LoadSceneMode.Single then all current scenes will be unloaded before loading.
            public static AsyncOperation LoadSceneAsync(string sceneName, [DefaultValue("LoadSceneMode.Single")] LoadSceneMode mode);
            //
    
            // 参数:
            //   sourceScene:
            //     The scene that will be merged into the destination scene.
            //
            //   destinationScene:
            //     Existing scene to merge the source scene into.
            public static void MergeScenes(Scene sourceScene, Scene destinationScene);
            //
            // 摘要:
            //     ///
            //     Move a GameObject from its current scene to a new scene. /// It is required that
            //     the GameObject is at the root of its current scene.
            //     ///
            //
            // 参数:
            //   go:
            //     GameObject to move.
            //
            //   scene:
            //     Scene to move into.
            public static void MoveGameObjectToScene(GameObject go, Scene scene);
            //
    
            // 返回结果:
            //     ///
            //     Returns false if the scene is not loaded yet.
            //     ///
            public static bool SetActiveScene(Scene scene);
    
            //     ///
            public static bool UnloadScene(string sceneName);
            //
            // 摘要:
            //     ///
            //     Unloads all GameObjects associated with the given scene. Note that assets are
            //     currently not unloaded, in order to free up asset memory call Resources.UnloadAllUnusedAssets.
            //     ///
            //
            // 参数:
            //   sceneBuildIndex:
            //     Index of the scene in the Build Settings to unload.
            //
            //   sceneName:
            //     Name of the scene to unload.
            //
            // 返回结果:
            //     ///
            //     Returns true if the scene is unloaded.
            //     ///
            public static bool UnloadScene(int sceneBuildIndex);
        }
    }

    三、SceneManager对于获取场景的一些操作

    (一)
    SceneManager
    class in UnityEngine.SceneManagement
    描述:运行时的场景管理。
    静态变量sceneCount: 当前加载的场景的总数。
    前加载的场景的数量将被返回。
    sceneCountInBuildSettings : 在BuildSettings的号码。

    (二)
    CreateScene:在运行时创建一个空的新场景,使用给定的名称。
    在运行时创建一个空的新场景,使用给定的名称。
    新的场景将开放相加到层次与现有已经打开的场景。新场景的路径将是空的。此函数用于在运行时创建场景。创建一个场景编辑时间(例如,使编辑脚本或工具需要创建场景时),使用editorscenemanager.newscene。

    (三)
    public static SceneManagement.Scene GetActiveScene()
    现场的活动场景。
    描述:获取当前活动场景。
    当前活动的场景将被用来作为目标由脚本实例化新的游戏对象现场。

    using UnityEngine;
    using UnityEngine.SceneManagement;
    
    public class GetActiveSceneExample : MonoBehaviour
    {
        void Start()
        {
            Scene scene = SceneManager.GetActiveScene();
    
            Debug.Log("Active scene is '" + scene.name + "'.");
        }
    }

    (四)
    public static SceneManagement.Scene GetSceneAt(int index);
    index:场景索引。指数必须大于或等于0和小于scenemanager.scenecount。

    返回:
    根据给定的参数返回一个场景引用。
    获取现场在添加场景的场景管理器的列表索引:

    using UnityEditor;
    using UnityEditor.SceneManagement;
    using UnityEngine.SceneManagement;
    using UnityEngine;
    public class Example
    {
        // adds a menu item which gives a brief summary of currently open scenes
        [MenuItem("SceneExample/Scene Summary")]
        public static void ListSceneNames()
        {
            string output = "";
            if (SceneManager.sceneCount > 0)
            {
                for (int n = 0; n < SceneManager.sceneCount; ++n)
                {
                    Scene scene = SceneManager.GetSceneAt(n);
                    output += scene.name;
                    output += scene.isLoaded ? " (Loaded, " : " (Not Loaded, ";
                    output += scene.isDirty ? "Dirty, " : "Clean, ";
                    output += scene.buildIndex >=0 ? " in build)\n" : " NOT in build)\n";
                }
            }
            else
            {
                output = "No open scenes.";
            }
            EditorUtility.DisplayDialog("Scene Summary",output, "Ok");
        }
    }

    (五)

    public static SceneManagement.Scene GetActiveScene();
    获取当前活动场景。
    当前活动的场景将被用来作为目标由脚本实例化新对象。

    using UnityEngine;
    using UnityEngine.SceneManagement;
    
    public class GetActiveSceneExample : MonoBehaviour
    {
        void Start()
        {
            Scene scene = SceneManager.GetActiveScene();
    
            Debug.Log("Active scene is '" + scene.name + "'.");
        }
    }
    
    public static void LoadScene(int sceneBuildIndex, SceneManagement.LoadSceneMode mode = LoadSceneMode.Single);
    public static void LoadScene(string sceneName, SceneManagement.LoadSceneMode mode = LoadSceneMode.Single);

    sceneName: 需发加载的场景名称或路径。

    sceneBuildIndex:在“ Build Settings”加载中的场景的索引。

    Mode:允许您指定是否要加载相加现场。见LoadScene模式有关选项的详细信息。
    LoadSceneMode:在播放器加载一个场景时使用。
    Single:关闭所有当前场景和加载一个新场景。
    Additive:将场景添加到当前加载的场景中。
    你可以使用这个异步版本:LoadSceneAsync。

    using UnityEngine;
    using UnityEngine.SceneManagement;
    
    public class ExampleClass : MonoBehaviour {
        void Start () {
            // Only specifying the sceneName or sceneBuildIndex will load the scene with the Single mode
            SceneManager.LoadScene ("OtherSceneName", LoadSceneMode.Additive);
        }
    }

    四、5.3的实现代码

    上代码:

    /**************************************************************************
    Copyright:@maxdong
    Author: maxdong
    Date: 2017-07-04
    Description:加载关卡,可以分组加载和卸载。使用Unity版本为5.3.0.
    因为里面使用了场景管理的一个类,这个类在5.3.0以上版本才添加的。
    测试操作:使用空格键来切换场景,然后间隔5秒后才开始卸载。
    **************************************************************************/
    using UnityEngine;
    using System.Collections;
    using UnityEngine.SceneManagement;
    
    [System.Serializable]
    public class LevelOrder
    {
    
        [Header("每组关卡名称")]
        public string[] LevelNames;
    }
    
    public class ChangLevelsHasMain : MonoBehaviour
    {
        [Header("所有关卡列表")]
        public LevelOrder[] levelOrder;
        private static int index;
        private int totalLevels = 0;
        private int levelOrderLength;
    
        void Start ()
        {
            for (int i = 0; i < levelOrder.Length; i++)
            {
                totalLevels += levelOrder[i].LevelNames.Length;
            }
    
            if (totalLevels != SceneManager.sceneCountInBuildSettings)
            {
    
            }
            levelOrderLength = levelOrder.Length;
        }
    
        // Update is called once per frame
        void Update ()
        {
            if (Input.GetKeyDown(KeyCode.Space))
            {
                bool isOk = LoadNextLevels();
                if (isOk)
                {
                    InvokeRepeating("UnloadLastLevel", 2.0f, 5);
                }
            }
        }
    
        bool LoadNextLevels()
        {
            bool bResult = true;
            //index = index % levelOrderLength;
            if (index < 0 || index >= levelOrderLength)
            {
                bResult = false;
                return bResult;
            }
    
            int LoadTimes = levelOrder[index].LevelNames.Length;
            for (int i = 0; i < LoadTimes; i++)
            {
                SceneManager.LoadSceneAsync(levelOrder[index].LevelNames[i], LoadSceneMode.Additive);
            }
            return bResult;
        }
    
        void UnloadLastLevel()
        {
            if (index == 0)
            {
                index++;
                CancelInvoke("UnloadLastLevel");
                return;
            }
            // 上一組的關卡
            int TmpLast = (index - 1) >= 0 ? (index - 1) : levelOrderLength - 1;
            int LoadTimes = levelOrder[index].LevelNames.Length;
            for (int i = 0; i < LoadTimes; i++)
            {
                Scene Tmp = SceneManager.GetSceneByName(levelOrder[index].LevelNames[i]);
                if (!Tmp.isLoaded)
                {
                    return;
                }
            }
    
            // 下一關卡全部加載完畢後,卸載之前關卡
            for (int i = 0; i < levelOrder[TmpLast].LevelNames.Length; i++)
            {
                SceneManager.UnloadScene(levelOrder[TmpLast].LevelNames[i]);
            }
            index++;
            CancelInvoke("UnloadLastLevel");
        }
    }

    就这样就可以了。
    代码主要是按组来加载关卡,然后按组来卸载。
    测试中,按下空格键来加载,每组关卡在一定时间后,(这里设置的5秒)自动卸载前一组关卡。这里主地图是不卸载的,会一直存在的。

    怎么设置的呢?首先需要在Build setting中中把所有要处理的关卡放进来。要不就会在加载过程中报错。
    如下图:
    这里写图片描述

    然后把代码挂在主地图的任意对象对象上就可以了.
    这里写图片描述

    展开全文
  • 今天博主想和大家分享的是Unity3D场景编辑的扩展开发,相关的话题我们在Unity3D游戏开发之编辑扩展程序开发实例这篇文章中我们已经有所涉及,今天博主想特别针对场景编辑的扩展开发来进行下深入研究。...

      今天博主想和大家分享的是Unity3D场景编辑器的扩展开发,相关的话题我们在Unity3D游戏开发之编辑器扩展程序开发实例这篇文章中我们已经有所涉及,今天博主想特别针对场景编辑器的扩展开发来进行下深入研究。对于一个场景编辑器来说,它主要的作用是3D场景视图中实时显示、输入反馈和相关信息的更新。在Unity3D中提供了Editor、EditorWindow、GUILayout、EditorGUILayout、GUIUtility、EditorGUIUtility、Handles、Event等来完成这些工作。其中基于EditorWindow的这种扩展方式我们已经研究过了,这种扩展方式拥有自己的独立窗口使用OnGUI方法进行界面的绘制。今天我们想说的是基于Editor的这种扩展方式,这种扩展方式只能针对脚本,从脚本内容在Inspector里的显示布局到变量在Scene视图的可视化编辑,它都可以完全胜任。这里特别想说的是Handles和Event这两个类,这两个类分别提供了3D显示和输入反馈的功能,我们下面就来学习如何使用这些类来扩展Unity3D的场景编辑器。

    创建一个扩展的Transform组件

      Transform是Unity3D中一个基本的组件,下面我们来创建一个扩展的Transform组件,该组件可以对游戏体的坐标、旋转、缩放进行重置。首先,我们创建一个ExtendTransform的类,该类继承自Editor类:

    using UnityEngine;
    using System.Collections;
    using UnityEditor;
    
    [CustomEditor(typeof(Transform),true)]
    public class ExtendTransform : Editor 
    {
        /// <summary>
        /// Position属性
        /// </summary>
        private SerializedProperty mPos;
    
        /// <summary>
        /// Scale属性
        /// </summary>
        private SerializedProperty mScale;
    
        void OnEnable()
        {
            mPos = serializedObject.FindProperty("m_LocalPosition");
            mScale = serializedObject.FindProperty("m_LocalScale") ;
        }
    
        /// <summary>
        /// Inspector相关GUI函数
        /// </summary>
        public override void OnInspectorGUI()
        {
            EditorGUIUtility.labelWidth = 15;
            //获取最新的可序列化对象
            serializedObject.Update();
            //绘制物体的坐标、旋转和缩放
            DrawPosition();
            DrawRotate();
            DrawScale();
            //更新可序列化对象的属性
            serializedObject.ApplyModifiedProperties();
        }
    
        /// <summary>
        /// 绘制位置
        /// </summary>
        private void DrawPosition()
        {
            GUILayout.BeginHorizontal();
            {
                bool Reset = GUILayout.Button("P", GUILayout.Width(20f));
                EditorGUILayout.LabelField("Position");
                EditorGUILayout.PropertyField(mPos.FindPropertyRelative("x"));
                EditorGUILayout.PropertyField(mPos.FindPropertyRelative("y"));
                EditorGUILayout.PropertyField(mPos.FindPropertyRelative("z"));
                if(Reset) mPos.vector3Value = Vector3.zero;
            }
            GUILayout.EndHorizontal();
        }
    
        /// <summary>
        /// 绘制旋转
        /// </summary>
        private void DrawRotate()
        {
            Vector3 eulerAngles = ((Transform)target).eulerAngles;
            GUILayout.BeginHorizontal();
            {
                bool Reset = GUILayout.Button("R", GUILayout.Width(20f));
                EditorGUILayout.LabelField("Rotation", GUILayout.Width(70f));
                EditorGUILayout.LabelField("X", GUILayout.Width(13f));
                float angleX=EditorGUILayout.FloatField(eulerAngles.x, GUILayout.Width(56f));
                EditorGUILayout.LabelField("Y", GUILayout.Width(13f));
                float angleY = EditorGUILayout.FloatField(eulerAngles.y, GUILayout.Width(56f));
                EditorGUILayout.LabelField("Z", GUILayout.Width(13f));
                float angleZ = EditorGUILayout.FloatField(eulerAngles.z, GUILayout.Width(56f));
                ((Transform)target).eulerAngles = new Vector3(angleX, angleY, angleZ);
                if(Reset)
                {
                    eulerAngles = Vector3.zero;
                    ((Transform)target).eulerAngles = Vector3.zero;
                }
            }
            GUILayout.EndHorizontal();
        }
    
        /// <summary>
        /// 绘制缩放
        /// </summary>
        private void DrawScale()
        {
            GUILayout.BeginHorizontal();
            {
                bool Reset = GUILayout.Button("S", GUILayout.Width(20f));
                EditorGUILayout.LabelField("Scale");
                EditorGUILayout.PropertyField(mScale.FindPropertyRelative("x"));
                EditorGUILayout.PropertyField(mScale.FindPropertyRelative("y"));
                EditorGUILayout.PropertyField(mScale.FindPropertyRelative("z"));
                if (Reset) mScale.vector3Value = Vector3.one;
            }
            GUILayout.EndHorizontal();
        }
    }

      首先我们注意到ExtendTransform继承自Editor,这是我们开发这类编辑器扩展的第一个前提。其次我们注意到在该类的声明位置有这样一个标记:

    [CustomEditor(typeof(Transform),true)]

    该标记表明我们这个编辑器扩展是针对Transform组件进行扩展的,即当物体存在Tranform组件时会在编辑器中响应这个编辑器扩展程序。我们在这个编辑器扩展程序中都做了哪些事情呢?第一,我们实现了OnEnable()方法,该方法相当于一个初始化的方法;第二,我们重写了OnOnInspectorGUI()方法,该方法将覆盖默认的Inspector窗口外观。

    扩展后的Transform

    好了,现在我们点击场景中默认的相机MainCamera可以发现默认的Transform会变成具有重置功能的扩展型Transform。下面我们来介绍这段程序中较为重要的核心内容:

    Unity3D中的可序列化对象

      通常我们所说的序列化是指将一个对象的实例转化为字符串的过程,而在Unity3D中可序列化对象更像是一种智能对象,它可以将脚本中的属性显示在Inspector窗口中,当场景发生变化时这些属性值将自动被更新。例如我们可以定义这样一个简单的脚本:

    /// <summary>
    /// 定义一个可序列化类
    /// </summary>
    [System.Serializable]
    public class ExampleClass 
    {
        [SerializeField]
        public int ID;
        [SerializeField]
        public string Name;
        [SerializeField]
        public Vector3[] Points;
    
        private bool editable = false;
    }
    
    /// <summary>
    /// 定义一个简单的脚本
    /// </summary>
    public class ExampleScript : MonoBehaviour 
    {
        public ExampleClass Example;
    }

    此时如果我们给场景中的某个物体附加上该脚本,则我们在Inspector窗口可以看到Example类的实例Example将被序列化到编辑器面板中,同时我们可以注意到私有的editable字段并没有被序列化出来,这是因为在Unity3D中,公有的字段默认支持序列化,私有的字段除非显式的增加[SerializeField]标记,否则都不会被序列化,这一点希望大家注意。好了,那么我们为什么要讲这部分内容呢,这是因为它和我们下面要讲的Editor基类中的属性和方法有着十分密切的关联。

    Unity3D中的可序列化对象

    Editor基类中的属性和方法

      Editor基类中有两个重要的属性,即target和serializedObject。target表示当前受检查的物体我们可以通过它获得当前物体;而serializedObject表示当前物体的全部可序列化信息,我们可以通过它获得指定的序列化字段及其数值。Editor基类中重要的方法有:
    * OnInspectorGUI():该方法可对Inspector窗口面板进行扩展或者重写,比如我们可以通过DrawDefaultInspector()方法来绘制默认Inspector窗口面板然后在此基础上使用GUILayout或者EditorGUILayout等辅助类进行自定义的绘制。在这个示例中我们对整个面板进行了重写,值得注意的是为了让Inspector窗口面板正常工作,如果要重绘该窗口请确保对该方法进行覆盖。
    * OnSceneGUI():该方法可对场景视图进行绘制,在实际的使用中可以配合Handles类和Event类来进行网格编辑、地形绘制或高级Gizmos等方面的工作。在本文的第二个示例中,我们将利用这一特性来编写一个用于NPC寻路的路径节点编辑工具。

    对第一个示例的总结

      在第一个示例中,可以注意到我们使用了FindProperty()方法来获取一个可序列化物体的属性(字段),然后我们在EditorGUILayout.PropertyField()方法来绘制了各种属性框,这种方式可以实现属性的自动更新。注意到DrawRotate()方法与DrawPositin()及DrawScale()方法在实现方式上略有不同,这是因为Transform组件的Rotation属性是一个Quaternion即四元数的结构,四元数是利用x、y、z、w四个数值来表示物体的三维旋转,这不仅和我们平时习惯的欧拉角相违背而且更为关键的是貌似目前我还没有发现可以直接绘制四元数的API接口,如果有的话希望大家可以告诉我,所以这里我们用了变通的一种方法,即通过Transform的eulerAngles来实现,但是这种方式绘制的属性框大小和EditorGUILayout.PropertyField()方法绘制的属性框大小并不一致,同时我们需要自己去完成属性值的更新。好了,暂时先总结到这里更多的细节大家可以通过代码来了解。

    创建一个NPC寻路节点编辑工具

      创建这样一个工具的想法来自我实际的工作体验,当我Unity3D中使用的Tween动画库从iTween变成Dotween后,我在使用Dotween的过程中一直没有找到类似于iTweenPath的路径节点编辑工具。作为一个有节操的程序员,去寻找破解版的Dotween Pro这样的事情我是能不干就不干啦,因为我觉得自己有能力做这样一个类似的小工具,所以在一边准备这篇文章的时候,一边开始设计这样一个路径节点编辑工具。相信经过第一个示例的铺垫和相关知识的储备,大家都了解了这些内容,所以这里直接给出代码啦,因为实在是没有多少内容,嘿嘿:

    using UnityEngine;
    using System.Collections;
    using UnityEditor;
    
    [CustomEditor(typeof(PatrolNPC))]
    public class PatrolPathEditor : Editor 
    {
        /// <summary>
        /// 寻路节点
        /// </summary>
        private Vector3[] paths;
    
        /// <summary>
        /// 显示寻路信息的GUI
        /// </summary>
        private GUIStyle style=new GUIStyle();
    
        /// <summary>
        /// 初始化
        /// </summary>
        void OnEnable()
        {
            //获取当前NPC的寻路路径
            paths = ((PatrolNPC)target).Paths;
            //初始化GUIStyle
            style.fontStyle = FontStyle.Normal;
            style.fontSize = 15;
        }
    
    
        void OnSceneGUI()
        {
            //获取当前NPC的寻路路径
            paths = ((PatrolNPC)serializedObject.targetObject).Paths;
            //设置节点的颜色为红色
            Handles.color = Color.red;
            if(paths.Length <= 0 || paths.Length<2) return;
            //在场景中绘制每一个寻路节点
            //可以在场景中编辑节点并将更新至对应的NPC
            for (int i = 0; i < paths.Length; i++)
            {
                paths[i] = Handles.PositionHandle(paths[i], Quaternion.identity);
                Handles.SphereCap(i, paths[i], Quaternion.identity, 0.25f);
                Handles.Label(paths[i], "PathPoint" + i, style);
                if (i < paths.Length && i + 1 < paths.Length)
                {
                    Handles.DrawLine(paths[i], paths[i + 1]);
                }
            }
        }
    
    }

      这里的PatrolNPC是一个可寻路NPC类,基本和这篇文章的内容无关,大家只要知道那个Paths字段是一个Vector3[]就好啦,这样当我们在场景中编辑这些路径节点的时候,对应NPC的路径节点信息就会同步发生更新,这样我们就可以随心所欲地规划NPC的移动路径啦,哈哈。好了,今天的内容就是这样啦,写完熬到这个点真心不容易啊,大家晚安,这是这个小工具在场景编辑器中的效果,嘻嘻,感觉还是蛮不错的吧,反正我是很喜欢就对啦!

    路径节点编辑工具演示

    展开全文
  • [Unity3d]场景管理插件-SceneManager

    千次阅读 2014-03-02 18:54:51
    Unity3d中提供了场景Scene的概念,Scene就是一组相关联的...Unity3d提供了一些切换场景的规则和方法(例如在切换场景时不销毁某些GameObject,同步,异步加载场景API),但是并没有提供一个通用的场景管理的模块(想要

    Unity3d中提供了场景Scene的概念,Scene就是一组相关联的游戏对象的一个集合,通常每个集合就是一个场景,但是也有可能只是一个场景的一部分!

    场景中的游戏对象是任意的,可以是HUD的UI组件,场景地图,模型等等

    Unity3d提供了一些切换场景的规则和方法(例如在切换场景时不销毁某些GameObject,同步,异步加载场景API),但是并没有提供一个通用的场景管理的模块(想要做到“通用”是很难的)

    在实际开发中,有些开发者摒弃了Scene模块,即整个游戏只有一个Scene,然后自己实现一套“窗口”对象以及“窗口”管理模块,以达到场景管理和通信的目的,这样的好处在于更灵活的控制场景对象;同样,坏处也很明显,即工作量会很大!

    我在开发中也做了一套简单的场景管理模块,其主要功能包括:

    1.使用一个栈来保存玩家在游戏中场景的载入先后关系(方便Back功能实现以及记录当前场景ID)

    2.提供切换场景,压栈场景,出栈场景方法

    3.提供异步加载场景,并提供加载进度(用以显示Loading条)

    Unity3d将组件设计模式发挥的淋漓尽致,很多开发者都可以方便灵活的制作各种插件,如果足够抽象,便可以为其它项目很方便的使用!Scene Manager就是其中一个,官网地址


    1.功能

    Scene Manager提供了2个场景的概念:Screen和Level

    Screen:即相互之间没有关联的场景模块(例如登陆场景,主菜单场景,游戏场景之间的关系),其之间并没有严格的先后关系,更接近于Unity3d中Scene的概念

    Level:即游戏场景中的关卡模块,有一定的先后关系,并且逻辑相同,Scene Manager为Level提供了一些关卡关系的方法,包括当前关卡,上一个关卡,关卡状态,参考 SMLevelProgress 类

    这2个场景的概念在Unity3d看来都是Scene的意义,之所以这样区分是为了将Scene的概念更细化!

    其提供了下图的编辑界面,我们只需要创建一个SceneConfiguration来编辑游戏中所有Scene的类别和关系



    2.实现

    (1)SMSceneManager

    一旦Scene Configuration创建完成之后,即可以在第一个“Screen场景”中创建出单例类SMGameEnvironment实例,其

    其构造方法中完成对SMSceneManager与SMLevelProgress实例的创建:

    (注意一定要在Screen场景中实例化SMGameEnvironment,如果是Level场景,则有可能对各个Level之间的关系有错误)

    SMSceneManager提供切换场景的接口(包括加载场景,加载关卡,加载第一个关卡)

    SMLevelProgress用以保存Level之间的关系(包括当前Level,上一Level,当前Level状态)


    (2)SMTransition

    SMTransition及其子类,提供了很多方便的切换场景(包括Screen和Level)动画效果,包括 淡入淡出,闪烁,卡通等等

    (这些动画效果都作为Prefab保存在SceneManager/Resources/Transitions/下)

    SMTransition作为基类,提供了是否异步加载场景,实际调用Unity3d API切换场景方法,但主要提供了一个动画的模板方法 DoTransition(),代码如下:

    1. protected virtual IEnumerator DoTransition() {  
    2.         // 第一部分:之前场景退出动画  
    3.         state = SMTransitionState.Out;  
    4.         Prepare();  
    5.         float time = 0;  
    6.           
    7.         while(Process(time)) {  
    8.             time += Time.deltaTime;  
    9.             // wait for the next frame  
    10.             yield return 0;  
    11.         }  
    12.           
    13.         // wait another frame...  
    14.         yield return 0;  
    15.           
    16.         // 第二部分:保证SMTransition对象不被销毁(完成后续动画)  
    17.         state = SMTransitionState.Hold;  
    18.         DontDestroyOnLoad(gameObject);  
    19.   
    20.   
    21.         // wait another frame...  
    22.         yield return 0;  
    23.           
    24.         IEnumerator loadLevel = DoLoadLevel();  
    25.         while (loadLevel.MoveNext()) {  
    26.             yield return loadLevel.Current;  
    27.         }  
    28.            
    29.         // wait another frame...  
    30.         yield return 0;  
    31.   
    32.   
    33.         // 第三部分:新场景载入动画  
    34.         state = SMTransitionState.In;  
    35.         Prepare();  
    36.         time = 0;  
    37.   
    38.   
    39.         while(Process(time)) {  
    40.             time += Time.deltaTime;  
    41.             // wait for the next frame  
    42.             yield return 0;  
    43.         }  
    44.   
    45.   
    46.         // wait another frame...  
    47.         yield return 0;  
    48.           
    49.         Destroy(gameObject);  
    50.     }  

    在SMTransition的子类中,分别实现Prepare()虚方法和Process(float elapsedTime)抽象方法

    例如 SMFadeTransition 类中,通过传入参数elapsedTime与配置淡入淡出参数duration计算得到当前进度,正交化进度,得到当前遮盖的alpha值,并在OnGUI绘制,代码如下:

    1. protected override bool Process(float elapsedTime) {  
    2.         float effectTime = elapsedTime;  
    3.         // invert direction if necessary  
    4.         if (state == SMTransitionState.In) {  
    5.             effectTime = duration - effectTime;  
    6.         }  
    7.           
    8.         progress = SMTransitionUtils.SmoothProgress(0, duration, effectTime);  
    9.           
    10.         return elapsedTime < duration;  
    11.     }  
    1. public void OnGUI() {  
    2.         GUI.depth = 0;  
    3.         Color c = GUI.color;  
    4.         GUI.color = new Color(1, 1, 1, progress);  
    5.         GUI.DrawTexture(new Rect(0, 0, Screen.width, Screen.height), overlayTexture);  
    6.         GUI.color = c;  
    7.     }  

    其它SMTransition子类也通过Process(float elapsedTime)实现切换动画效果!


    PS: 在异步加载场景中,Scene Manager中并没有提供一个获取当前加载进度的接口,需要自己实现,在SMTransition类中

    1. protected virtual YieldInstruction LoadLevel() {  
    2.         if (loadAsync) {  
    3.                     AsyncOperation ao = Application.LoadLevelAsync(screenId);  
    4.                     Debug.Log("Progress: " + ao.progress);  
    5.                     return ao;  
    6.                     //return Application.LoadLevelAsync(screenId);  
    7.         } else {  
    8.             Application.LoadLevel(screenId);  
    9.             return null;  
    10.         }  
    11.     }  

    转载自:http://blog.csdn.net/onerain88/article/details/12303511



    展开全文
  • Unity3D场景管理插件Scene Manager

    千次阅读 2015-07-17 10:32:55
    Unity3d中提供了场景Scene的概念,Scene就是一组相关联的...Unity3d提供了一些切换场景的规则和方法(例如在切换场景时不销毁某些GameObject,同步,异步加载场景API),但是并没有提供一个通用的场景管理的模块(想要

    Unity3d中提供了场景Scene的概念,Scene就是一组相关联的游戏对象的一个集合,通常每个集合就是一个场景,但是也有可能只是一个场景的一部分!

    场景中的游戏对象是任意的,可以是HUD的UI组件,场景地图,模型等等

    Unity3d提供了一些切换场景的规则和方法(例如在切换场景时不销毁某些GameObject,同步,异步加载场景API),但是并没有提供一个通用的场景管理的模块(想要做到“通用”是很难的)

    在实际开发中,有些开发者摒弃了Scene模块,即整个游戏只有一个Scene,然后自己实现一套“窗口”对象以及“窗口”管理模块,以达到场景管理和通信的目的,这样的好处在于更灵活的控制场景对象;同样,坏处也很明显,即工作量会很大!

    我在开发中也做了一套简单的场景管理模块,其主要功能包括:

    1.使用一个栈来保存玩家在游戏中场景的载入先后关系(方便Back功能实现以及记录当前场景ID)

    2.提供切换场景,压栈场景,出栈场景方法

    3.提供异步加载场景,并提供加载进度(用以显示Loading条)

    Unity3d将组件设计模式发挥的淋漓尽致,很多开发者都可以方便灵活的制作各种插件,如果足够抽象,便可以为其它项目很方便的使用!Scene Manager就是其中一个,官网地址


    1.功能

    Scene Manager提供了2个场景的概念:Screen和Level

    Screen:即相互之间没有关联的场景模块(例如登陆场景,主菜单场景,游戏场景之间的关系),其之间并没有严格的先后关系,更接近于Unity3d中Scene的概念

    Level:即游戏场景中的关卡模块,有一定的先后关系,并且逻辑相同,Scene Manager为Level提供了一些关卡关系的方法,包括当前关卡,上一个关卡,关卡状态,参考 SMLevelProgress 类

    这2个场景的概念在Unity3d看来都是Scene的意义,之所以这样区分是为了将Scene的概念更细化!

    其提供了下图的编辑界面,我们只需要创建一个SceneConfiguration来编辑游戏中所有Scene的类别和关系



    2.实现

    (1)SMSceneManager

    一旦Scene Configuration创建完成之后,即可以在第一个“Screen场景”中创建出单例类SMGameEnvironment实例,其

    其构造方法中完成对SMSceneManager与SMLevelProgress实例的创建:

    (注意一定要在Screen场景中实例化SMGameEnvironment,如果是Level场景,则有可能对各个Level之间的关系有错误)

    SMSceneManager提供切换场景的接口(包括加载场景,加载关卡,加载第一个关卡)

    SMLevelProgress用以保存Level之间的关系(包括当前Level,上一Level,当前Level状态)


    (2)SMTransition

    SMTransition及其子类,提供了很多方便的切换场景(包括Screen和Level)动画效果,包括 淡入淡出,闪烁,卡通等等

    (这些动画效果都作为Prefab保存在SceneManager/Resources/Transitions/下)

    SMTransition作为基类,提供了是否异步加载场景,实际调用Unity3d API切换场景方法,但主要提供了一个动画的模板方法 DoTransition(),代码如下:

    1. protected virtual IEnumerator DoTransition() {  
    2.         // 第一部分:之前场景退出动画  
    3.         state = SMTransitionState.Out;  
    4.         Prepare();  
    5.         float time = 0;  
    6.           
    7.         while(Process(time)) {  
    8.             time += Time.deltaTime;  
    9.             // wait for the next frame  
    10.             yield return 0;  
    11.         }  
    12.           
    13.         // wait another frame...  
    14.         yield return 0;  
    15.           
    16.         // 第二部分:保证SMTransition对象不被销毁(完成后续动画)  
    17.         state = SMTransitionState.Hold;  
    18.         DontDestroyOnLoad(gameObject);  
    19.   
    20.   
    21.         // wait another frame...  
    22.         yield return 0;  
    23.           
    24.         IEnumerator loadLevel = DoLoadLevel();  
    25.         while (loadLevel.MoveNext()) {  
    26.             yield return loadLevel.Current;  
    27.         }  
    28.            
    29.         // wait another frame...  
    30.         yield return 0;  
    31.   
    32.   
    33.         // 第三部分:新场景载入动画  
    34.         state = SMTransitionState.In;  
    35.         Prepare();  
    36.         time = 0;  
    37.   
    38.   
    39.         while(Process(time)) {  
    40.             time += Time.deltaTime;  
    41.             // wait for the next frame  
    42.             yield return 0;  
    43.         }  
    44.   
    45.   
    46.         // wait another frame...  
    47.         yield return 0;  
    48.           
    49.         Destroy(gameObject);  
    50.     }  

    在SMTransition的子类中,分别实现Prepare()虚方法和Process(float elapsedTime)抽象方法

    例如 SMFadeTransition 类中,通过传入参数elapsedTime与配置淡入淡出参数duration计算得到当前进度,正交化进度,得到当前遮盖的alpha值,并在OnGUI绘制,代码如下:

    1. protected override bool Process(float elapsedTime) {  
    2.         float effectTime = elapsedTime;  
    3.         // invert direction if necessary  
    4.         if (state == SMTransitionState.In) {  
    5.             effectTime = duration - effectTime;  
    6.         }  
    7.           
    8.         progress = SMTransitionUtils.SmoothProgress(0, duration, effectTime);  
    9.           
    10.         return elapsedTime < duration;  
    11.     }  
    1. public void OnGUI() {  
    2.         GUI.depth = 0;  
    3.         Color c = GUI.color;  
    4.         GUI.color = new Color(1, 1, 1, progress);  
    5.         GUI.DrawTexture(new Rect(0, 0, Screen.width, Screen.height), overlayTexture);  
    6.         GUI.color = c;  
    7.     }  

    其它SMTransition子类也通过Process(float elapsedTime)实现切换动画效果!


    PS: 在异步加载场景中,Scene Manager中并没有提供一个获取当前加载进度的接口,需要自己实现,在SMTransition类中

    1. protected virtual YieldInstruction LoadLevel() {  
    2.         if (loadAsync) {  
    3.                     AsyncOperation ao = Application.LoadLevelAsync(screenId);  
    4.                     Debug.Log("Progress: " + ao.progress);  
    5.                     return ao;  
    6.                     //return Application.LoadLevelAsync(screenId);  
    7.         } else {  
    8.             Application.LoadLevel(screenId);  
    9.             return null;  
    10.         }  
    11.     }  



    http://blog.csdn.net/onerain88/article/details/12303511


    展开全文
  • Unity3d中提供了场景Scene的概念,Scene就是一组...Unity3d提供了一些切换场景的规则和方法(例如在切换场景时不销毁某些GameObject,同步,异步加载场景API),但是并没有提供一个通用的场景管理的模块(想要做到“通
  • Unity3D 制作场景地图 插件

    千次阅读 2017-11-08 21:59:31
    Unity3D 制作场景地图,地图轨迹 插件包。
  • Unity3D 场景摄像机控制 插件

    千次阅读 2017-11-08 21:56:35
    Unity3D 场景摄像机控制脚本组件 插件
  • Unity3d场景快速烘焙【2019】

    万次阅读 多人点赞 2019-12-26 19:09:28
    很多刚刚接触Unity3d的童鞋花了大量的时间自学,可总是把握不好Unity3d的烘焙,刚从一个坑里爬出来,又陷入另一个新的坑,每次烘焙一个场景少则几个小时,多则几十个小时,机器总是处于假死机状态,半天看不到结果,...
  • Odin puts your Unity workflow on steroids, making it easy to build powerful and advanced user-friendly editors for you and your entire team. With an effortless integration that deploys perfectly ...
  • Unity3D 场景渲染到Cubemap 插件

    千次阅读 2017-11-08 22:03:11
    Unity3D 场景渲染到Cubemap文件 插件
  • Unity3d 场景搭建 基础 学习

    千次阅读 2017-09-02 12:08:05
    第一章:Unity环境搭建 所用软件:Unity 5.4.0f3 (64-bit) assets文件夹最重要 Scene场景面板  常用快捷键 1.按下鼠标滚轮拖动场景(或者拖动小手),滑动滚轮缩放场景 2.选择十字标,选定物体,按下F:...
  • Unity3d】200个插件免费分享(所有资源已上传)

    万次阅读 多人点赞 2019-07-05 10:03:48
    接触U3D有段时间了,积累了点插件、资源、学习网站、论坛等,现在整理下,跟广大同仁们分享下! 所有资源已经上传完毕,约5G。 200个插件免费分享 【下载链接】  链接:https://pan.baidu.com/s/1smQzbDb 密码...
  • Unity3D编辑器插件开发

    千次阅读 2019-02-27 17:05:54
    Unity3D插件开发.png 一,菜单项相关操作 1.菜单项(MenuItem) 首先在Asset目录下新建一个Editor文件夹,然后在该目录下添加一个脚本MenuTest.cs 代码内容: using UnityEngine; using System.Collections; ...
  • 最近在做一个项目,了解到了一个Unity插件——HighlightingSystem HighlightingSystem 链接:https://pan.baidu.com/s/1SoOwz7c8Ai1lZE93nzDSTw 提取码:v9p6 关于插件,导入之后可能会又报错,将报错...
  • Unity3D 简易细节层次插件 Simple LOD http://www.idoubi.net/unity3d/tool/3764.html Unity3D 物体表面贴花喷漆插件 Easy Decal Easy Decal v1.6.8 http://www.idoubi.net/unity3d/tool/4060.html Unity3D 汽车底盘...
  • Unity3D调用摄像头加载到场景中-插件

    热门讨论 2020-07-30 23:30:38
    Unity3D调用摄像头加载到场景中代码
  • unity3d 白天夜晚切换插件,可以渐变改变天空盒,代码可以更改,很方便使用。
  • Unity3d 离线渲染插件

    2020-07-30 23:31:50
    Unity3d 离线渲染,Octane for Unity3dUnity3d烘焙,Unity3d VR制作
  • Unity引擎做3D游戏起家,Asset Store里也有非常多优质的3D资源。本文将介绍Asset Store里几家非常棒的3D模型开发商,Unity开发者可以选购他们的模型素材,相信会让游戏更有质感。 1)Synty Studios Synty Studios...
  • 目前收集整理了20个Unity3D着色器插件,效果都不错。 1.Unity3D 毁灭着色特效 Damage FX v1.2 http://www.idoubi.net/unity3d/shader/2543.html 2.Unity3D 水下特效 Sleepless Underwater Effects ...
1 2 3 4 5 ... 20
收藏数 6,433
精华内容 2,573
关键字:

unity3d 场景管理器插件