ScriptableObject 对象化的运用
http://www.cnblogs.com/oldman/articles/2409554.html
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 是Unity3D整个引擎的设计中,最为出彩的地方。通过他我们将数据保存,数据和编辑器的交互以及数据在runtime的使用三部分很方便的联系在一起。这是一个容易被Unity3D的初学者们容易忽略的领域。
简单的说,你可以把ScriptableObject当作Unity3D下的xml。但是其存储格式为二进制。让我们从一个实际例子出发,来理解ScriptableObject在实际项目中的整个运用。
假设我们有AbilityInfo需要设置和保存,我们可以将AbilityInfo制作成ScriptableObject,如下:
public class AbilityInfo : ScriptableObject {
public enum Type {
Unknown,
FireBall,
FireWall,
IceBall,
DarkForce,
Heal,
Poison,
}
public Type type = Type.Unknown;
public float point = 10.0f;
public float affectRange = 100.0f;
}
创建ScriptableObject
ScriptableObject 可以通过 ScriptableObject.CreateInstance<T>() 动态创建。然而将它保存为Unity3D Asset是ScriptableObject的设计本意。一般的,我们通过这个函数来完成整个创建过程:
public static class AbilityInfoUtility {
public static AbilityInfo Create ( string _path, string _name ) {
//
if ( new DirectoryInfo(_path).Exists == false ) {
Debug.LogError ( "can't create asset, path not found" );
return null;
}
if ( string.IsNullOrEmpty(_name) ) {
Debug.LogError ( "can't create asset, the name is empty" );
return null;
}
string assetPath = Path.Combine( _path, _name + ".asset" );
//
AbilityInfo newAbilityInfo = ScriptableObject.CreateInstance<AbilityInfo>();
AssetDatabase.CreateAsset(newAbilityInfo, assetPath);
Selection.activeObject = newAbilityInfo;
return newAbilityInfo;
}
}
注意1: 这是一个在Editor下使用的函数,所以这份代码需要放在项目中名为 “Editor” 的文件夹中 (目录层次无所谓),并且需要在代码开头处引入: using UnityEditor;
注意2: ScriptableObject的脚本文件名必须和他的类名一致,并且一个脚本文件只能对应一个ScriptableObject定义。
注意3: ScriptableObject只能保存为后缀名为”.asset”的文件,其他格式Unity3D将不能正确读取。
将Asset的创建方式提供给用户
对于编辑器的使用者,自然需要有UI或者方便的执行脚本方法来帮助创建数据。我们使用[MenuItem]来完成操作。以下代码会将Asset的创建加入到Project Window的右键菜单中:
class AbilityInfoUtility {
...
[MenuItem ("Assets/Create/Ability Info")]
static void Create () {
// get current selected directory
string assetName = "New AbilityInfo";
string assetPath = "Assets";
if ( Selection.activeObject ) {
assetPath = AssetDatabase.GetAssetPath(Selection.activeObject);
if ( Path.GetExtension(assetPath) != "" ) {
assetPath = Path.GetDirectoryName(assetPath);
}
}
//
bool doCreate = true;
string path = Path.Combine( assetPath, assetName + ".asset" );
FileInfo fileInfo = new FileInfo(path);
if ( fileInfo.Exists ) {
doCreate = EditorUtility.DisplayDialog( assetName + " already exists.",
"Do you want to overwrite the old one?",
"Yes", "No" );
}
if ( doCreate ) {
AbilityInfo abilityInfo = AbilityInfoUtility.Create ( assetPath, assetName );
Selection.activeObject = abilityInfo;
// EditorGUIUtility.PingObject(border);
}
}
}

自定义编辑显示
ScriptableObject 可以通过自定义编辑器的方式进行特殊编辑。编辑器方面有EditorWindow和Editor两种方式。EditorWindow更多地用在一些复杂数 据的可视化编辑。对于一些小的行为改变,我们可以通过Editor来实现。本节我们也已介绍Editor的编辑为主。设我们需要为AbilityInfo 在Inspector中加入预览图标。我们先于提供预览图标的美术工作人员约定好图标的存放位置和名称,如Editor/Icons/Ability 目录内。这里我们通过简单的硬编码来存取这些图标 (更灵活的做法是提供一些辅助的设置gui等)。我们在AbilityInfoUtility中添加如下函数:
public static class AbilityInfoUtility {
...
public static Texture2D GetTextureByType ( AbilityInfo.Type _type ) {
switch ( _type ) {
case AbilityInfo.Type.Unknown:
return AssetDatabase.LoadAssetAtPath ( "Assets/Editor/Icons/Ability/Unknown.png", typeof(Texture2D) ) as Texture2D;
case AbilityInfo.Type.FireBall:
return AssetDatabase.LoadAssetAtPath ( "Assets/Editor/Icons/Ability/FireBall.png", typeof(Texture2D) ) as Texture2D;
case AbilityInfo.Type.FireWall:
return AssetDatabase.LoadAssetAtPath ( "Assets/Editor/Icons/Ability/FireWall.png", typeof(Texture2D) ) as Texture2D;
case AbilityInfo.Type.IceBall:
return AssetDatabase.LoadAssetAtPath ( "Assets/Editor/Icons/Ability/IceBall.png", typeof(Texture2D) ) as Texture2D;
case AbilityInfo.Type.DarkForce:
return AssetDatabase.LoadAssetAtPath ( "Assets/Editor/Icons/Ability/DarkForce.png", typeof(Texture2D) ) as Texture2D;
case AbilityInfo.Type.Heal:
return AssetDatabase.LoadAssetAtPath ( "Assets/Editor/Icons/Ability/Heal.png", typeof(Texture2D) ) as Texture2D;
case AbilityInfo.Type.Poison:
return AssetDatabase.LoadAssetAtPath ( "Assets/Editor/Icons/Ability/Poison.png", typeof(Texture2D) ) as Texture2D;
}
return null;
}
}
要自定义Inspector显示,只需要通过在派生的Editor中标记上[CustomEditor(Type)]这个Attribute即可,这里给出一个简单的示例:
[CustomEditor(typeof(AbilityInfo))]
public class AbilityInfoEditor : Editor {
public override void OnInspectorGUI () {
AbilityInfo editInfo = target as AbilityInfo;
GUI.DrawTexture ( new Rect( 20, 20, 40, 40 ), AbilityInfoUtility.GetTextureByType(editInfo.type) );
GUILayoutUtility.GetRect ( 40, 40 );
GUILayout.Space (5);
base.OnInspectorGUI();
}
}
注意: 这里的base.OnInspectorGUI()实际上是比较偷懒的做法。对于需要仔细定义每个属性用途和显示的数据,请参考Unity3D的EditorGUI, EditorGUILayout文档认真编写。

在MonoBehavior中引用数据
现在我们只需要在MonoBehavior中引用这份数据,在读取场景的时候,就会自动帮助我们完成数据的序列化操作。
public class MyBehavior : MonoBehavior {
public AbilityInfo normalSkill1;
public AbilityInfo normalSkill2;
public AbilityInfo specialSkill;
}
ScriptableObject 对象化的运用的更多相关文章
- ScriptableObject本地序列化后重启Unity后报The associated script can not be loaded.Please fix any compile errors and assign a valid script的坑
踩坑 做编辑器一些设置序列化存在本地的时候,继承自ScriptableObject的类通过 创建的asset文件. 在重启Unity后查看这个asset发现上面的所有序列化属性丢失,报的错就是 在不存 ...
- unity, 由scriptableObject创建.asset
由继承自scriptableObject的类X创建.asset文件. 假设类X的定义为: [System.Serializable] public class X : ScriptableObject ...
- [cb]ScriptableObject 序列化
ScriptableObject ScriptableObject是一个类,它允许你存储大量用于共享的数据独立脚本实例,不要迷惑这个类同样可以叫做 SerializableObject,可以理解成是一 ...
- Unity ScriptableObject的使用
ScriptableObject主要实现对象序列化的保存,因为是Unity自己的序列化,所以比xml,json序列化方便很多,但相对可控性也比较差 1.Editor下写入和读取测试: using Un ...
- EditorWindow edit ScriptableObject
using UnityEngine; [System.Serializable] public class Weapon { //[SerializeField] public string weap ...
- Unity3D之ScriptableObject学习笔记
不同与C#提供的Serializable序列化功能,ScriptableObject是Unity3D提供的一个数据存储类,我们接下来学习一下这个类的功能. 官方文档 http://docs.unity ...
- C语言对象化编程
以下为一个引子: C中struct的函数实现,只能用函数指针成员. C结构体内不能有函数的代码,但可以有函数的指针. C/C code Code highlighting produced by Ac ...
- 用DELPHI的RTTI实现数据集的简单对象化
在<强大的DELPHI RTTI--兼谈需要了解多种开发语言>一文中,我说了一下我用DELPHI的RTTI实现了数据集的简单对象化.本文将详细介绍一下我的实现方法. 首先从一个简单 ...
- 自定义ScriptableObject属性显示
自定义ScriptableObject属性显示的三种方式 1. 继承Editor,重写OnInspectorGUI方法 Editor官方文档 需求 将TestClass中intData属性和strin ...
随机推荐
- 【51Nod 1238】最小公倍数之和 V3
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1238 设\(A(n)=\sum\limits_{i=1}^n\frac{ ...
- 【2-SAT】HDU3622-Bomb Game
[题目大意] 给n对炸弹可以放置的位置(每个位置为一个二维平面上的点),每次放置炸弹是时只能选择这一对中的其中一个点,每个炸弹爆炸的范围半径都一样,控制爆炸的半径使得所有的爆炸范围都不相交(可以相切) ...
- 【动态规划/多重背包问题】POJ2392-Space Elevator
方法同POJ1014-Dividing,唯一不同点在于每一种block有最大限定高度a,故要以a为关键字进行排序,使得最大高度小的在前,否则最大高度小的再后可能放不上去. #include<io ...
- 在Ubuntu下编译hadoop2.5.x
在Ubuntu下编译hadoop2.5.x 参考博客:http://www.aboutyun.com/thread-8130-1-1.html 1 下载hadoop源码: (1) http://www ...
- 将mnist数据集存储到本地文件
参考文章: http://www.csuldw.com/2016/02/25/2016-02-25-machine-learning-MNIST-dataset/ import numpy as np ...
- Android/Java 中的 String, StringBuffer, StringBuilder的区别和使用
Android 中的 String, StringBuffer 和 StringBuilder 是移动手机开发中经常使用到的字符串类.做为基础知识是必须要理解的,这里做一些总结. A.区别 可以从以下 ...
- MyISAM重启之后的一次血泪教训
最近经历了一次MyISAM重启的血泪教训,小小的故障历经3个小时才全部解决完毕,特此铭记一下,以后坚决防止在同一个地方跌倒两次. 事情的过程: 某日早7点接到几条主库报警,给值班组打电话后得到的消息是 ...
- Dual-voltage regulator meets USB-power needs
This Design Idea stems from the limited availability of IC voltage regulators that can meet key USB- ...
- JAVA EE 博客实例
http://www.cnblogs.com/hoojo/category/276244.html
- 自己定义AlertDialog对话框布局
自己定义对话框中的信息body布局 LayoutInflater inflater =getLayoutInflater(); View layout = inflater.inflate(R.lay ...