如何使实例化出来的对象具有血条更随+unity创建对象

温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
LOFTER精选
if(myObjet&==&null)
&&&myObject&=&SpawnMyObject();
11.把人物和站立物体的支点放在底部,而不是中心。这样易于将人物和物体精准的放在地面上。同时在游戏逻辑、AI以及物理方面,这也能让3D工程像2D一样简单,当然是在某些合适的情况下。
12.&让所有的网格面向同一方向(正或负Z轴)。这适用于那些有朝向概念的人物或者事物的网格。如果所有的东西都面朝一个方向,那么许多算法都可以得到简化。
13.从一开始就确定尺寸。
14.制作二聚平面用以GUI组件和手动创建粒子。
15.制作和使用的测试技术
各种纯的颜色:白色,黑色着色试验,50%的灰,红,绿,蓝,黄,洋红,青蓝。
阴影检测梯度:黑色到白色,红色,绿色,红色,蓝色,绿色,蓝色。
平滑和崎岖的法线贴图
照明设备(如预制)快速建立测试场景
16.对于一切都可以使用预制。游戏场景中的唯一对象不应该是预制,而应该是文件夹。即使是只使用一次的特殊对象也应该是预制。这使得不改变场景也可以轻松实现转变。(这也让使用构建sprite地图时更加可靠)
17.使用不同的预制来专业化,不使用专门的实例。如果你有两个类型的敌人,他们的唯一区别是他们的财产不同,那么对财产分别作预制,然后再将其链接,这让下面两点成为可能:
在一个地方对任何类型做改变
在不改变场景的情况下做出变化
如果你有太多的敌人类型,那么就不用在编辑器重做出专业化实例了。一种代替方法是做程序,或者使用对所有的敌人使用一个核心文件/预制。一个下降动作可以用于不同的敌人,一个运算可以基于敌人位置或玩家进程。
18.将预制之间链接,实例之间不链接。当把预制拖放到场景时,预制的链接可以得到保证,而实例则不可以。链接到预制可以在任何时候减少场景的建立,也可以减少场景变化的需求。
19.尽可能在实例之间自动建立连接。如果你需要链接实例,建立编程链接。例如,玩家预制可以在GameManager启动时自己注册,或者GameManager在启动时可以找到玩家预制实例。
如果你想添加其他脚本的话,就不要把网格放在预制的根源。
用链接预制代替嵌套预制。
20.使用安全的流程来分支预制。我们以玩家预制为例来解释:
如下是一个有风险的改变玩家预制的方法:
1.&&复制玩家预制
2.&&重命名该副本&__Player_Backup
3.&&改变玩家预制
4.&&如果一切顺利,删除&__Player_Backup
不要把把副本命名为Player_New,并且改变它!
有些情况更加复杂。例如,某个改变可能涉及两个人,按照上述步骤直到Person
2完成的时候,可能会破坏掉所有人的工作场景。如果足够快的话,仍会是这样。因为变化需要的时间更长,你可以仿照下面的方法:
1.&&复制玩家预制
2.&&重命名为__Player_WithNewFeature或者__Player_ForPerson2.
3.&&在副本上修改,并且提交到Person 2
Person 2:
1.&&在新预制上做修改
2.&&复制玩家预制,命名为&__Player_Backup.
3.&&拖动__Player_WithNewFeature的实例到场景
4.&&拖动这个实例到原来的玩家预制
5.&&如果一切顺利,删除__Player_Backup&和&__Player_WithNewFeature.
拓展组件和 MonoBehaviourBase
21.拓展你自己的基本单一行为,并推导出所有它的组件。这让你实现一些通用功能,如类的安全调用和其他更复杂的调用。
22.定义调用的安全方法,StartCoroutine和实例化。定义一个委托任务,并用它来定义不依赖于字符串名称的方法,例如:
public&voidInvoke(Task&task,&float&time)
&&&Invoke(task.Method.Name,&time);
23.使用共享界面的拓展组件。有时候可以很方便的得到执行某个界面的组件,或者使用组件找到对象。下面的执行使用typeof来代替这些功能的通用版本。通用版本不能使用这些接口,但是typeof可以。请参考:
//Definedin&the&common&base&class&for&all&mono&behaviours
publicI&GetInterfaceComponent&I&()&where&I&:&class
&&&return&GetComponent(typeof(I))&as&I;
publicstatic&List&I&&FindObjectsOfInterface&I&()&where&I&:&class
&&&MonoBehaviour[]&monoBehaviours&=FindObjectsOfType&MonoBehaviour&();
&&&List&I&&list&=&new&List&I&();
&&&&foreach(MonoBehaviour&behaviour&inmonoBehaviours)
&&&&&&I&component&=behaviour.GetComponent(typeof(I))&as&I;
&&&&&&&if(component&!=&null)
&&&&&&&&&list.Add(component);
&&&&return&
24.使用拓展组件使语法更加方便,例如
public&staticclass&CSTransform
&&&public&static&voidSetX(this&Transform&transform,&float&x)
&&&&&&Vector3&newPosition&=
&&&&&&&&&new&Vector3(x,&transform.position.y,transform.position.z);
&&&&&&transform.position&=&newP
25.使用备用的GetComponent以供选择。有时候强制组件依赖关系令人头疼(通过RequiredComponent)。例如:这使得在检查器中难以改变组件(即使它们是相同的基本类型)。作为替代品,当一个组件需要输出一条没有被发现的错误信息时,下面的GameObject拓展就可以使用了。
publicstatic&T&GetSafeComponent&T&(this&GameObject&obj)&where&T&:&MonoBehaviour
&&&T&component&=&obj.GetComponent&T&();
&&&if(component&==&null)
&&&&&&Debug.LogError("Expected&to&findcomponent&of&type&"
&&&&&&&&&+&typeof(T)&+&"&but&foundnone",&obj);
&&&return&
26.避免使用不同的语法来做同一件事。许多情况下,可以有多种语法来做一件事。这时,请选择一种贯穿项目的始终,因为:
有些语法不能很好地协同工作。只使用一种语法使得设计能够朝着一个方向进行,并且不适合其他语法。
从始至终使用一种语法能让团队成员更好地了解项目进程,可以让架构和代码更容易理解,更少出错。
·协同VS.状态机。
·嵌套问题VS.相关问题VS.预制
·数据分离策略
·2D游戏状态中使用sprites的方法
·预制结构
·生产策略。
·查找对象的方法:按类型VS.名称VS.标记VS.层VS.参考(“链接”)。
·组对象的方法:类型VS.名称VS.标签VS.层VS.数组引用(“链接”)。
·寻找对象VS.自注册
·控制执行规则(使用Unity的执行规则设置VS.产生逻辑VS.清醒/启动和更新/晚更新依赖VS.手工方法VS.任何规则结构)
·选择对象/位置/用鼠标选择目标:选择管理VS.自我管理
·保持变化场景之间的数据:通过PlayerPrefs,或者加载一个新场景时不会被破坏的物体
·结合方式(混合,添加和分层)动画
28.游戏运行时,不要让产生对象弄乱你的层次。当游戏运行时,在场景对象中设置他们的父对象将使东西更容易找到。你可以使用一个空的游戏对象,甚至是单例来使访问代码更容易。将这个对象成为DynamicObjects。
数据结构设计
29.为方便起见请使用单例下述可以使任何数据自动继承单例
public class Singleton&T& : MonoBehaviourwhere T :
MonoBehaviour
&&&protectedstatic T
&&&&&&Returnsthe instance of this
singleton.
&&&publicstatic T Instance
&&&&&&&&if(instance ==
&&&&&&&&&{
&&&&&&&&&&&instance = (T)
FindObjectOfType(typeof(T));
&&&&&&&&&&&&if(instance ==
&&&&&&&&&&&&{
&&&&&&&&&&&&&&Debug.LogError("An instance
of " + typeof(T) +
&&&&&&&&&&&&&&&&&" is needed in the scene, but there is
&&&&&&&&&&&&}
&&&&&&&&&}
&&&&&&&&return
单例对管理很有用,比如粒子管理、音频管理、GUI管理
30.对于组件,绝不要公开那些不应在检查面板中调整的变量。否则,它建个可能被设计师改变,尤其是在不清楚它的用处的时候。在某些罕见的情况下,这是不可避免的。在这种情况下,请使用双下划线甚至四个下划线来作为变量的名称前缀,以警告那些想要做修改的人。
public float __aV
31.把界面从游戏逻辑中分离出来
32.分离状态和簿记簿记变量是为了高效、方便,并可从状态中恢复。通过分离这些,你可以更容易的:
·保存游戏状态
·调试游戏状态
一种方法是:为每个游戏逻辑类定义一个保存数据类
[Serializable]
PlayerSaveData
&&& //public
forserialisation, not exposed in inspector
&&&//... bookkeeping variables
&&&//Don’t expose state in inspector. State isnot
tweakable.
&&&private PlayerSaveData playerSaveD
33.独立专业化设置。考虑两个有着相同网格,但Tweakables不同(例如不同强度和不同速度)的敌人,有不同的方式来分离数据。我倾向于下述方式,特别是当对象被催生或者游戏保存的时候。(Tweakables不是状态数据,而是配置数据,所以不需要保存,当加载或催生对象的时候,Tweakables会自动分别加载)
·定义每个游戏逻辑类的模板类。例如,对敌人,我们还定义了Enemytemplate。所有的分化Tweakables都存储在Enemytemplate
·在游戏逻辑类里,定义一个变量的模板类型。
·做一个敌人的预制件,和两个模板预制weakenemytemplate和strongenemytemplate。
·加载或催生对象时,设置合适模板的模板变量。
这种方法可以变得相当复杂的(有时是不必要的,复杂的,所以要小心!)。
例如,为了更好地利用通用多态性,我们可以这样定义类:
public class BaseTemplate
public class ActorTemplate : BaseTemplate
public class Entity&EntityTemplateType&where EntityTemplateType
: BaseTemplate
&&EntityTemplateT
public class Actor : Entity&ActorTemplate&
34.字符串不要用于显示文字之外的任何事。特别是,不要使用字符串识别对象或预制等。动画是个不幸的例外,通常访问它们的字符串名称。
35.避免使用公共指数耦合阵列。例如,不要定义武器阵列,子弹阵列,和颗粒阵列,你的代码看起来像这样:
public void SelectWeapon(int index)
&&currentWeaponIndex =
&&Player.SwitchWeapon(weapons[currentWeapon]);
public void Shoot()
&&Fire(bullets[currentWeapon]);
&&FireParticles(particles[currentWeapon]);
这里的问题并不是完全在于代码,而是在检查面板中不犯错误地设置出来。
相反,定义一个类,封装三个变量,使一个数组:
[Serializable]
public class Weapon
&&&publicGameO
&&&publicParticleS
&&&publicB
这段代码看上去更整洁,最重要的是,在检查面板里建立数据时不容易出错。
36.避免使用序列以外的数组结构。例如,一个玩家可能有三种攻击类型,每个都使用当前的武器,但是产生不同的子弹和行为。你可能想把三个子弹放在一个数组中,用这种逻辑:
public void FireAttack()
&&&///behaviour
&&Fire(bullets[0]);
public void IceAttack()
&&&///behaviour
&&Fire(bullets[1]);
public void WindAttack()
&&&///behaviour
&&Fire(bullets[2]);
枚举可以让代码看起来更好…
public void WindAttack()
&&&///behaviour
&&Fire(bullets[WeaponType.Wind]);
但是不是在检查面板中。
最好使用独立的变量,名称可以有助于显示应该放入哪些内容。使用一个类来让它整洁。
[Serializable]
public class Bullets
&&&publicBullet FireB
&&public Bullet IceB
&&public Bullet WindB
PS:假设没有其他的火、冰、风等数据。
37.在序列化类中将数据分组以使事物在检查面板中看起来更整洁。一些实体可能有几十个tweakables,这就使得在检查面板中寻找正确的变量成为一场噩梦。以下步骤会让事情变简单:
·对变量组定义独立的类,使其公开并序列化。
·在主类里,为如上定义的每一类型定义公共变量
·不要在Awake 或 Start初始化这些变量,因为他们是序列化的,Unity会处理那些。
·你可以像以前一样通过定义赋值指定缺省值
·这将在检查面板中将变量按可折叠单位分组,便于管理。
[Serializable]
public class MovementProperties //Not
aMonoBehaviour!
&&public float movementS
&&public float turnSpeed = 1; //default
public class HealthProperties //Not
aMonoBehaviour!
&&public float maxH
&&public float regenerationR
public class Player : MonoBehaviour
&&public MovementProperties
&&public HealthPorperties healthP
38.如果你的故事文本很多,那么请将文本放在一个文件中。不要放在检视面板的编辑器里。要让它在不打开Unity的情况下就可以编辑,特别是在不用保存场景的情况下。
39.如果你打算本地化,把所有字符串独立到一个地方。方法很多,其一是定义每个字符串都有公共字符串字段的文本类,默认设置为英语。例如:其他语言子属于它,然后用语言赋值重新初始化字段。
更先进的技术将读取电子数据表,然后基于所选语言为选择正确的字符串提供逻辑。
测试和调试
40.执行图形记录器调试物理,动画,和AI,这可以使调试相当快。
41.执行HTML记录器。在某些情况下,记录仍然是有用的。记录可以更容易地解析(彩色编码,多个视图,记录截图),可以使日志调试更愉快。
42.执行你自己的FPS计数器。是的,没人知道Unity的FPS计数器到底测量什么,但不是帧速率。执行你自己的,这样数量就可以协调直觉和视觉检查了。
43.快捷键实现屏幕截图。许多bugs是可见的,并且通过图片可以更容易发现。
44.实施快捷方式打印玩家的世界位置。这易于发现bug的位置。
45.执行debug选项使测试更容易,例如
·解锁所有项目
·禁用敌人
·让玩家无敌
·禁用所有的游戏
46.对于足够小的团队,为每一个成员做一个有debug选项的预制。将用户标示符放在一个不被承认的文件里,并且在游戏运行时读取,原因是:
·团队成员偶尔会不承认他们的debug选项,还可能影响到别人。
·改变debug选项不改变场景
47.维持所有游戏元素的场景。例如:一个你可以与所有敌人,所有对象互动的场景等等。这可以很容易地测试功能,不用耗费太多精力。
48.为调试快捷键定义常量并保持固定的位置。
49.记录你的设置。绝大多数的文件都应该编码,但是某些东西应该记录在代码之外。让设计师通过设置找代码是在浪费时间。记录设置能提高效率(如果是最近的记录)。
按下列方式记录:
·层使用(碰撞,裁剪,和光线投射–本质,哪一层里应该有什么)
·标签使用
·GUI深度层(应该显示什么)
·场景设置
·语法偏好
·预制结构
·命名标准和文件夹结构
50.&遵循文件的命名规则和文件夹结构。统一的命名和文件夹结构更利于查找和辨认。相信你也希望创建自己的命名规则和文件夹结构。这里提供一个例子供参考。
命名的一般原则:
1.是什么就叫什么。一只鸟就应该就应该叫做“Bird”。
2.选择容易发音和记住的名字。如果你在做玛雅语的游戏,不要命名QuetzalcoatisReturn。
3.保持一致。选了一个名字就坚持到底。
4.使用Pascal案例,就像这样:&ComplicatedVerySpecificObject。不要使用空格、下划线或者连字符,但是也有一个例外(请参阅命名同一事物的不同方面)。
5.不要用版本号或者表示进程的词汇(WIP,final)。
6.不要用缩写:DVamp@W&应该是&DarkVampire@Walk。
7.在设计文件中使用术语。如果文件中把die
animation称作Die,那么请用DarkVampire@Die,而不是DarkVampire@Death.
8.把特定描述放在左边。是DarkVampire而不是VampireDark;是PauseButton而不是&ButtonPaused。
9.有些名字会形成序列。在这些名字中使用数字。例如:PathNode0,&PathNode1。要从0开始,而不是从1开始。
10.不会形成序列的名字就不要使用数字。比如Bird0,&Bird1,&Bird2应该被叫做Flamingo,&Eagle,&Swallow.
11.给临时对象命名请使用双下划线前缀__Player_Backup.
命名同一事物的不同方面
在核心名称与描述性事物之间使用下划线,例如
·GUI按钮状&EnterButton_Active, EnterButton_Inactive
·纹理&DarkVampire_Diffuse, DarkVampire_Normalmap
·天空盒&JungleSky_Top, JungleSky_North
·LOD组& DarkVampire_LOD0, DarkVampire_LOD1
不要使用本规则来区分不同类型的项目,例如rock_small,rock_large应该是smallrock,largerock。
场景、工程文件夹以及脚本文件夹的组织应当遵循类似的模式。
文件夹结构
DarkVampire
LightVampire
Structures
TestScenes
Dynamic Objects
Management
脚本文件夹结构
ThirdParty
MyGenericScripts
Extensions
MyGameScripts
怎样重新执行Inspector Drawing
1.为所有的编辑定义基类
BaseEditor&T&: Editor
where T :MonoBehaviour
&&&override public void OnInspectorGUI()
&&&&&&T data = (T)
&&&&&&GUIContent label = new
GUIContent();
&&&&&&label.text =
"Properties"; //
&&&&&&DrawDefaultInspectors(label, data);
&&&&&&if(GUI.changed)
&&&&&&{&&&&&&&
&&&&&&&&&EditorUtility.SetDirty(target);
2.使用反射和递归来绘制组件
public staticvoid DrawDefaultInspectors&T&(GUIContent label, T
&&&where T :
&&&EditorGUILayout.Separator();
&&&Type type = typeof(T);&&&&
&&&FieldInfo[] fields = type.GetFields();
&&&EditorGUI.indentLevel++;
&&&foreach(FieldInfo field in
&&&&&&if(field.IsPublic)
&&&&&&&&&if(field.FieldType ==
typeof(int))
&&&&&&&&&{
&&&&&&&&&&&&field.SetValue(target,EditorGUILayout.IntField(
&&&&&&&&&&&&MakeLabel(field),
(int)field.GetValue(target)));
&&&&&&&&&}&
&&&&&&&&&else
if(field.FieldType
==typeof(float))
&&&&&&&&&{
&&&&&&&&&&&&field.SetValue(target,EditorGUILayout.FloatField(
&&&&&&&&&&&&MakeLabel(field),
(float)field.GetValue(target)));
&&&&&&&&&}
&&&&&&&&&///etc. for other primitive types
&&&&&&&&&else
if(field.FieldType.IsClass)
&&&&&&&&&{
&&&&&&&&&&&&Type[] parmTypes = new
Type[]{field.FieldType};
&&&&&&&&&&&&string methodName
="DrawDefaultInspectors";
&&&&&&&&&&&&MethodInfo drawMethod =
&&&&&&&&&&&&&&typeof(CSEditorGUILayout).GetMethod(methodName);
&&&&&&&&&&&&if(drawMethod ==
&&&&&&&&&&&&{
&&&&&&&&&&&&&&&Debug.LogError("No
methodfound: " + methodName);
&&&&&&&&&&&&}
&&&&&&&&&&&&bool foldOut =
&&&&&&&&&&&drawMethod.MakeGenericMethod(parmTypes).Invoke(null,
&&&&&&&&&&&&&&&new object[]
&&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&MakeLabel(field),
&&&&&&&&&&&&&&&&&&field.GetValue(target)
&&&&&&&&&&&&&&&});
&&&&&&&&&}&&&&
&&&&&&&&&else
&&&&&&&&&{
&&&&&&&&&&&&Debug.LogError(
&&&&&&&&&&&&&&&"DrawDefaultInspectors doesnot support
fields of type " +
&&&&&&&&&&&&&&&field.FieldType);
&&&&&&&&&}
&&&&&&}&&&&&&&
&&&EditorGUI.indentLevel--;
上述方法使用下述帮助
private staticGUIContent MakeLabel(FieldInfo field)
&&&GUIContent guiContent = newGUIContent();&&&&
&&&guiContent.text =field.Name.SplitCamelCase();&&&&
&&&object[] descriptions =
&&&&&field.GetCustomAttributes(typeof(DescriptionAttribute),
&&&if(descriptions.Length &
&&&&&&//just use the first one.
&&&&&&guiContent.tooltip =
&&&&&&&&&(descriptions[0]
asDescriptionAttribute).D
&&&return guiC
注意:它在类代码中使用注释,来在检查面板中产生工具提示
3.定义新的自定义编辑器
不幸的是,你仍然需要定义每个MonoBehaviour类。幸运的是,这些定义可以是空的;所有的实际工作都由基类来完成。
[CustomEditor(typeof(MyClass))]
public classMyClassEditor : BaseEditor&MyClass&
理论上说这一步可以自动化,但是我还没有尝试过。
原文链接:
阅读(447)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
loftPermalink:'',
id:'fks_',
blogTitle:'【转】使用Unity的50个建议',
blogAbstract:'\n关于这些建议\n这些建议并不适用于所有的项目\n\n这些建议是基于我与3-20人的小团队项目经验总结出来的\n结构、可重复使用性、明晰度都是有价的——团队规模和项目规模决定了是否值得付这个价。\n一些建议也许公然违抗了传统的Unity开发。例如:使用专业化的组合而不是使用实例就很不像Unity的作风,价格也很高。即使看上去挺疯狂的,但我还是看到了这些建议给开发者带来了利益。\n&\n过程方面\n1.避免分支资产&对于任何资产我们应该只有一个版本。如果你非要把一个预设,场景,或网格分支开来,那么情遵循一个过程,这个过程必须清楚的表明哪一个才是正确的版本。错误的分支应该有一个显著的名字,例如,使用双下划线前缀__MainScene_Backup。预设的分支需要一个特定的过程来使其安全。(详见预设部分)\n2.持有项目副本&任何一个使用版本控制的团队成',
blogTag:'',
blogUrl:'blog/static/',
isPublished:1,
istop:false,
modifyTime:0,
publishTime:1,
permalink:'blog/static/',
commentCount:0,
mainCommentCount:0,
recommendCount:0,
bsrk:-100,
publisherId:0,
recomBlogHome:false,
currentRecomBlog:false,
attachmentsFileIds:[],
groupInfo:{},
friendstatus:'none',
followstatus:'unFollow',
pubSucc:'',
visitorProvince:'',
visitorCity:'',
visitorNewUser:false,
postAddInfo:{},
mset:'000',
remindgoodnightblog:false,
isBlackVisitor:false,
isShowYodaoAd:false,
hostIntro:'',
hmcon:'0',
selfRecomBlogCount:'0',
lofter_single:''
{list a as x}
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}提到为了传递数据,需要把作为载体的实体类序列化,好好的找了一些序列化方面的介绍。感觉下面的这个介绍比较容易介绍!
1.什么是序列化
序列化是将对象状态转换为可保持或传输的格式的过程,在序列化过程中,对象的公共字段和私有字段以及类的名称(包括包含该类的程序集)都被转换为字节流,然后写入数据流。与序列化相对的是反序列化,它将流转换为对象。这两个过程结合起来,可以轻松地存储和传输数据。
2.为什么使用序列化
a. 一个原因是将对象的状态保持在存储媒体中,以便可以在以后重新创建精确的副本。
我们经常需要将对象的字段值保存到磁盘中,并在以后检索此数据。尽管不使用序列化也能完成这项工作,但这种方法通常很繁琐而且容易出错,并且在需要跟踪 对象的层次结构时,会变得越来越复杂。可以想象一下编写包含大量对象的大型业务应用程序的情形,程序员不得不为每一个对象编写代码,以便将字段和属性保存 至磁盘以及从磁盘还原这些字段和属性。序列化提供了轻松实现这个目标的快捷方法。
b.另一个原因是通过值将对象从一个应用程序域发送到另一个应用程序域中。
例如,序列化可用于在 ASP.NET 中保存会话状态并将对象复制到 Windows 窗体的剪贴板中。远程处理还可以使用序列化通过值将对象从一个应用程序域传递到另一个应用程序域中。
公共语言运行时 (CLR) 管理对象在内存中的分布,.NET 框架则通过使用反射提供自动的序列化机制。对象序列化后,类的名称、程序集以及类实例的所有数据成员均被写入存储媒体中。对象通常用成员变量来存储对其他 实例的引用。类序列化后,序列化引擎将跟踪所有已序列化的引用对象,以确保同一对象不被序列化多次。.NET 框架所提供的序列化体系结构可以自动正确处理对象图表和循环引用。对对象图表的唯一要求是,由正在进行序列化的对象所引用的所有对象都必须标记为 Serializable(请参阅基本序列化)。否则,当序列化程序试图序列化未标记的对象时将会出现异常。
当反序列化已序列化的类时,将重新创建该类,并自动还原所有数据成员的值。
3.如何实现对象的序列化及反序列化
要实现对象的序列化,首先要保证该对象可以序列化。而且,序列化只是将对象的属性进行有效的保存,对于对象的一些方法则无法实现序列化的。
实现一个类可序列化的最简便的方法就是增加Serializable属性标记类。如:
[Serializable()]
public class MEABlock
private int m_ID;
public string C
public MEABlock()
///构造函数
即可实现该类的可序列化。注意序列化的类必须为Public,否则不能够被序列化。
要将该类的实例序列化为到文件中?.NET FrameWork提供了两种方法:
a .XML序列化
使用 XmLSerializer 类,可将下列项序列化。
公共类的公共读/写属性和字段
实现 ICollection 或 IEnumerable 的类。(注意只有集合会被序列化,而公共属性却不会。)
XmlElement 对象。
XmlNode 对象。
DataSet 对象。
要实现上述类的实例的序列化,可参照如下例子:
MEABlock myBlock = new MEABlock();
// Insert code to set properties and fields of the object.
XmlSerializer mySerializer = new XmlSerializer(typeof(MEABlock));
// To write to a file, create a StreamWriter object.
StreamWriter myWriter = new StreamWriter(&myFileName.xml&);
mySerializer.Serialize(myWriter, MEABlock);
需要注意的是XML序列化只会将public的字段保存,对于私有字段不予于保存。
生成的XML文件格式如下:
&MEABlock&
&Caption&Test&/Caption&
&/MEABlock&
对于对象的反序列化,则如下:
MEABlock myB
// Constructs an instance of the XmlSerializer with the type
// of object that is being deserialized.
XmlSerializer mySerializer = new XmlSerializer(typeof(MEABlock));
// To read the file, creates a FileStream.
FileStream myFileStream = new FileStream(&myFileName.xml&, FileMode.Open);
// Calls the Deserialize method and casts to the object type.
myBlock = (MEABlock)mySerializer.Deserialize(myFileStream)
b. 二进制序列化
与XML序列化不同的是,二进制序列化可以将类的实例中所有字段(包括私有和公有)都进行序列化操作。这就更方便、更准确的还原了对象的副本。
要实现上述类的实例的序列化,可参照如下例子:
MEABlock myBlock = new MEABlock();
// Insert code to set properties and fields of the object.
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream(&MyFile.bin&,FileMode.Create,FileAccess.Write, FileShare.None);
formatter.Serialize(stream, myBlock);
stream.Close();
对于对象的反序列化,则如下:
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream(&MyFile.bin&, FileMode.Open,FileAccess.Read, FileShare.Read);
MEABlock myBlock = (MEABlock) formatter.Deserialize(stream);
stream.Close();
4、如何变相实现自定义可视化控件的序列化、反序列化
对于WinForm中自定义控件,由于继承于System.Windows.Form类,而Form类又是从MarshalByRefObject继承的,窗体本身无法做到序列化,窗体的实现基于Win32下GUI资源,不能脱离当前上下文存在。
当然可以采用变通的方法实现控件的序列化。这里采用的是记忆类模型。
定义记忆类(其实就是一个可序列化的实体类)用于记录控件的有效属性,需要序列化控件的时候,只需要将该控件的实例Copy到记忆类,演变成序列化保存该记忆类的操作。
反序列化是一个逆过程。将数据流反序列化成为该记忆类,再根据该记忆类的属性生成控件实例。而对于控件的一些事件、方法则可以继续使用。
wwf之所以强调要把类实例化,就是因为工作流和应用程序是在不同的线程中。二者之间需要用类作为传递数据的载体的话,就需要把该类定义为public序列化为二进制传输.
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:11042次
排名:千里之外
原创:14篇
转载:17篇
(1)(2)(1)(1)(2)(2)(1)(2)(1)(7)(10)(1)}

我要回帖

更多关于 unity 血条 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信