• 专业版Unity技巧分享:使用定制资源配置文件


    http://unity3d.9tech.cn/news/2014/0116/39639.html

    通常,在游戏的开发过程中,最终会建立起一些组件,通过某种形式的配置文件接收一些数据。这些可能是程序级别生成系统的一些参数,或许是手势识别系统的手势集,或任何其他东西。如果你是在Unity内部开发,很可能以创建一个可序列化的类来开始这项任务,这个类被设计成简单的容器,存储你所需要的所有配置数据。

    但是那又怎样?现实中你是怎样把数据放到那个类里的?你是创建一堆XML 或 JSON文件,当游戏启动时加载它们吗?或在需要数据的类里有数据类的公共实例,并且你是通过Inspector设置所有东西,然后创建很多预制,每个配置有一个。

    在这篇文章中我将阐述一种简单的方法,把那些可序列化的数据容器类放入自定义资源文件中。这与使用XML或者其他一些外部文件格式相比有很多好处。例如,通常,文件大小会更小,并且Unity将会掌控所有的序列化和反序列化。

    我觉得这种方法最好通过举例来解释。所以我假设我们在尝试建立一个JRPG类型的对话系统,就像《火焰之纹章》或者《牧场物语》或者其他的JRPG那样。这个类型有着很大的文本泡,从底部向上滑,然后左边或右边有个扁平的角色在说话。

    好了,现在开始为每个单独的对话语言元素创建简单的可序列化数据容器,如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    [System.Serializable]
    public class DialogueElement
    {
       public enum Characters{ David, Megan};
       public enum AvatarPos{ left, right};
       public Characters Character;
       public AvatarPos CharacterPosition;
       public Texture2D CharacterPic;
       public string DialogueText;
       public GUIStyle DialogueTextStyle;
       public float TextPlayBackSpeed;
       public AudioClip PlayBackSoundFile;
    }

    上面有几个枚举来描述哪些角色和屏幕位置是有效地,展示角色的纹理,角色在对话气泡中究竟说了什么的字符串,GUIStyle为字符串设计样式,或许还有个浮点用来控制文本的消失速度,一个声音片段来为每个对话气泡加点背景声。

    记住这仅仅是个例子,所以你应该学会举一反三,通过这个例子学会将技术应用于任何类型的数据容器。

    接下来创建一个用于所有对话的类,它将含有那些DialogueElement对象的列表。我们不把它做成一个普通的序列化类,而是让它从ScriptableObject继承。ScriptableObject类可以把对话类转变成我们自己的自定义资源文件。

    1
    2
    3
    4
    public class Dialogue: ScriptableObject
    {
       public List<DialogueElement> DialogItems;
    }

    现在可以从那个对话类里做出自定义对话资源了,首先要把CustomAssetUtility类保存在工程文件夹的某个位置。

    CustomAssetUtility类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    using UnityEngine;
    using UnityEditor;
    using System.IO;
     
    public static class CustomAssetUtility
    {
        public static void CreateAsset<T> () where T : ScriptableObject
        {
            T asset = ScriptableObject.CreateInstance<T> ();
             
            string path = AssetDatabase.GetAssetPath (Selection.activeObject);
            if (path == "")
            {
                path = "Assets";
            }
            else if (Path.GetExtension (path) != "")
            {
                path = path.Replace (Path.GetFileName (AssetDatabase.GetAssetPath (Selection.activeObject)), "");
            }
             
            string assetPathAndName = AssetDatabase.GenerateUniqueAssetPath (path + "/New " + typeof(T).ToString() + ".asset");
             
            AssetDatabase.CreateAsset (asset, assetPathAndName);
             
            AssetDatabase.SaveAssets ();
            EditorUtility.FocusProjectWindow ();
            Selection.activeObject = asset;
        }
    }

    在项目中安装了这个之后,只需要几行就可以把对话类,或者任何从ScriptableObject继承的类转变成自定义资源。

    制作一个新的类/文件,命名为DialogueAsset.cs,并保证它是在Editor文件夹内的。然后在该类中为新资源创建一个新的菜单项,从已下载的工具类调用CreateAsset:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    using UnityEngine;
    using UnityEditor;
    using System;
     
    public class DialogueAsest
    {
        [MenuItem("Assets/Create/Dialogue")]
        public static void CreateAsset ()
        {
            ScriptableObjectUtility.CreateAsset<Dialogue> ();
        }
    }

    现在当你从menu选择Assets -> Create,或者在project视图中点击创建按钮的时候,就能看到创建新对话的选项。

     

    当点击新创建的资源文件的时候,Inspector视图将会出现DialogueElements的列表以及它们的所有公共变量。和实例化的DialogueElements不同,由于这些是在它们自己的资源文件夹中的,你对它们所做的任何改变都将会贯彻到底,无论是在编辑器状态还是运行状态。所以如果游戏运行时在preview模式下,你对值做了改变,即使停止运行游戏还会保留。这种技术本质上是GUISkin和Unity的其他内置资产的工作原理。

     

    为了从另一个类中访问数据,假设你正在写的类实际上在对话屏幕上显示,就做一个对话的公共实例吧。

    1
    2
    3
    4
    5
    6
    public class DialogWindow : MonoBehaviour
    {
       public Dialogue DialogueFile;
     
       //The rest of your awesome code to playback
       //your dialogues or use your customs assets

    接下来只要通过Inspector指定它。通过单击小圆,从列表中选择它,或者在开口槽(open slot)中拖放一个新建的资源文件。

     

    如果你雄心勃勃,或者仅仅想采取额外的步骤,写一个自定义的Inspector类,来配置资源在Inspector中如何展示。如果是这样,创建一个新的类/文件,命名为DialogueEditor.cs之类的,确保在Editor文件夹下。然后开始写那个类,像是这个样子:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    using UnityEngine;
    using UnityEditor;
     
    [CustomEditor(typeof(Dialogue))]
    public class DialogueEditor : Editor
    {
       private Dialogue D; //Make an easy shortcut to the Dialogue your editing
       void Awake()
       {
          D=(Dialogue)target;
       }
     
       public override void OnInspectorGUI()
       {
     
       //The rest of your awesome code to allow custom editing
       // of your dialogues or other customs assets you make
       .
       .
       .

    然后用代码填充OnInspectorGUI功能,来显示编辑资源的选项。这将非常有利于清理和简化Inspector视图所显示的东西,或者隐藏你不想编辑的选项。对于团队来说也很有用。对于技术不是很娴熟的团队成员来说,例如写脚本的人,说“你看,这个的确很简单,只要点击创建对话并填好一切即可”。下面的截图说明了本项目创建自定义Inspector的用途。

     

    但是,还有一个小小的告诫。如果你为编辑资源文件写了一个自定义Inspector类,或者在另一个MonoBehavior运行时修改自定义资源的值,就需要在你改变的对象上调用Unity的SetDirty方法,如下:

    1
    EditorUtility.SetDirty(yourInstanceOfACustomAsset);

    之所以这样做是因为Unity将会知道对象的内容被修改了,需要重新序列化并保存到磁盘上。

    现在,你应该了解如何制作属于你自己的自定义资源,并把它们作为配置文件使用。

    原文链接:Unity Pro Tip: Use custom made assets as configuration files

  • 相关阅读:
    带你走进Ajax
    基础
    基础
    基础-文字
    C++ part6.5
    操作系统 part4
    操作系统 part3
    计算机网络 part3 HTTP&HTTPS
    计算机网络 part2
    计算机网络 part1 TCP
  • 原文地址:https://www.cnblogs.com/123ing/p/4106481.html
Copyright © 2020-2023  润新知