unity delegate event可以继承吗

Unity3D(28)
转发,请保持地址:
这篇文章将收集unity的相关技巧,会不断地更新内容。
1)保存运行中的状态
unity在运行状态时是不能够保存的。但在运行时编辑的时候,有时会发现比较好的效果想保存。这时可以在 “Hierarchy”中复制相关对象树,暂停游戏后替换原来的,就可以了。(其实这个拷贝过程是序列化过程,这种方法是序列化到内存中;另外一种方法就是序列化到磁盘上,即把内容拖动到文件夹中变成prefab,效果也是一样的)
2)Layer的用法
LayerMask.NameToLayer(&Ground&);
&// 通过名字获取layer
<span style="color:#D Raycast
RaycastHit&&&if(Physics.Raycast(cam3d.ScreenPointToRay(Input.mousePosition),&out&hit,&Mathf.Infinity,&(1&&LayerMask.NameToLayer(&Ground&))))&{&&...&&}&&
2D Raycast
Collider2D&h&=&Physics2D.OverlapPoint(cam2d.ScreenToWorldPoint(Input.mousePosition),&(1&&LayerMask.NameToLayer(&xxx&)));&&if(h)&{&&...&&}&&
3)物理摄像头取色(WebCamTexture)
Texture2D&exactCamData()&{&&&&&&&&&&&&Texture2D&snap&=&new&Texture2D((int)detectSize.x,&(int)detectSize.y);&&&&&&snap.SetPixels(webcamTexture.GetPixels((int)detectStart.x,&(int)detectStart.y,&(int)detectSize.x,&(int)detectSize.y));&&&&&&snap.Apply();&&&&&&return&&&}&&
保存截图:
System.IO.File.WriteAllBytes(Application.dataPath&&#43;&&/test.png&,&exactCamData().EncodeToPNG());&&
4) 操作componenent
CircleCollider2D&cld&=&(CircleCollider2D)colorYuan[i].AddComponent(typeof(CircleCollider2D));&&cld.radius&=&1;&&
Destroy(transform.gameObject.GetComponent&SpriteRenderer&());&&
5)动画相关
状态Init到状态fsShake的的条件为:参数shake==true;代码中的写法:
触发fsShake:
void&Awake()&{&&&&&&anims&=&new&Animator[(int)FColorType.ColorNum];&&}&&....&&if(needShake)&{&&&&&&curAnim.SetTrigger(&shake&);&&}&&
关闭fsShake
void&Update()&{&&....&&if(curAnim)&{&&&&&&AnimatorStateInfo&stateInfo&=&curAnim.GetCurrentAnimatorStateInfo(0);&&&&&&if(stateInfo.nameHash&==&Animator.StringToHash(&Base&Layer.fsShake&))&{&&&&&&&&&&curAnim.SetBool(&shake&,&false);&&&&&&&&&&curAnim&=&null;&&&&&&&&&&print&(&======&&&&&&stop&shake!!!!&);&&&&&&}&&}&&....&&}&&
关于Animator.StringToHash函数的说明:
animator的setBool,setTrigger等函数都有两种参数形式,一个接收string,一个接收hash;其实Animator内部是使用hash来记录相应信息的,所以接收string类型的函数内部会帮你调用StringToHash这个函数;所以如果要经常调用setTrigger等,请把参数名称hash化保持以便反复使用,从而提高性能。
在状态机animator中获取animation state 和animation clip的方法(参考):
public&static&AnimationClip&getAnimationClip(Animator&anim,&string&clipName)&{&&&&&&UnityEditorInternal.State&state&=&getAnimationState(anim,&clipName);&&&&&&return&state!=null&?&state.GetMotion()&as&AnimationClip&:&null;&&}&&&&public&static&UnityEditorInternal.State&getAnimationState(Animator&anim,&string&clipName)&{&&&&&&UnityEditorInternal.State&state&=&null;&&&&&&if(anim&!=&null)&{&&&&&&&&&&UnityEditorInternal.AnimatorController&ac&=&anim.runtimeAnimatorController&as&UnityEditorInternal.AnimatorC&&&&&&&&&&UnityEditorInternal.StateMachine&sm&=&ac.GetLayer(0).stateM&&&&&&&&&&&&&&&&&&&&for(int&i&=&0;&i&&&sm.stateC&i&#43;&#43;)&{&&&&&&&&&&&&&&UnityEditorInternal.State&_state&=&sm.GetState(i);&&&&&&&&&&&&&&if(state.uniqueName.EndsWith(&.&&&#43;&clipName))&{&&&&&&&&&&&&&&&&&&state&=&_&&&&&&&&&&&&&&}&&&&&&&&&&}&&&&&&}&&&&&&return&&&}&&
6)scene的切换
同步方式:
Application.LoadLevel(currentName);&&
异步方式:
Application.LoadLevelAsync(&ARScene&);&&
7)加载资源
Resources.Load&Texture&(string.Format(&{0}{1:D2}&,&mPrefix,&5));&&
8)Tag VS. Layer
& & &-& Tag用来查询对象
& & &-& Layer用来确定哪些物体可以被raycast,还有用在camera render中
transform.eulerAngles 可以访问 rotate的 xyz
transform.RotateAround(pivotTransVector,&Vector3.up,&-0.5f&*&(tmp-preX)&*&speed);&&
10)保存数据
PlayerPrefs.SetInt(&isInit_&&&#43;&Application.loadedLevelName,&1);&&
11)动画编码
/lopezycj/archive//Unity3d_AnimationEvent.html
/Components/animeditor-AnimationEvents.html
/questions/8172/how-to-add-new-curves-or-animation-events-to-an-im.html
12) 遍历子对象
Transform[]&transforms&=&target.GetComponentsInChildren&Transform&();&&for&(int&i&=&0,&imax&=&transforms.L&i&&&&&#43;&#43;i)&{&&&&&&Transform&t&=&transforms[i];&&&&&&t.gameObject.SendMessage(functionName,&gameObject,&SendMessageOptions.DontRequireReceiver);&&}&&
13)音效的播放
&先添加Auido Source, 设置Audio Clip, 也可以在代码中加入。然后在代码中调用audio.Play(), 参考如下代码:
public&AudioClip&aC&&...&&void&Start&()&{&&&&&&&...&&&&&&audio.clip&=&aC&&&&&&audio.Play();&&&&&&...&&}&&
另外,如果是3d音效的话,需要调整audio Souce中的panLevel才能听到声音,不清楚原因。
14)调试技巧(Debug)
可以在OnDrawGizmos函数来进行矩形区域等,达到调试的目的,请参考NGUI中的UIDraggablePanel.cs文件中的那个函数实现。
#if&UNITY_EDITOR&&&&&&&&&&&&&&&&&&&&&&&&void&OnDrawGizmos&()&&&&&&{&&&&&&&&&&if&(mPanel&!=&null)&&&&&&&&&&{&&&&&&&&&&&&&&Bounds&b&=&&&&&&&&&&&&&&&Gizmos.matrix&=&transform.localToWorldM&&&&&&&&&&&&&&Gizmos.color&=&new&Color(1f,&0.4f,&0f);&&&&&&&&&&&&&&Gizmos.DrawWireCube(new&Vector3(b.center.x,&b.center.y,&b.min.z),&new&Vector3(b.size.x,&b.size.y,&0f));&&&&&&&&&&}&&&&&&}&&#endif&&
15)延时相关( StartCoroutine)
StartCoroutine(DestoryPlayer());&&...&&IEnumerator&DestoryPlayer()&{&&&&&&Instantiate(explosionPrefab,&transform.position,&transform.rotation);&&&&&&gameObject.renderer.enabled&=&false;&&&&&&yield&return&new&WaitForSeconds(1.5f);&&&&&&gameObject.renderer.enabled&=&true;&&}&&
16)Random做种子
Random.seed&=&System.Environment.TickC&&&或者&&Random.seed&=&System.DateTime.Today.M&&
17) 调试技巧(debug),可以把&#20540;方便地在界面上打印出来
void&OnGUI()&{&&&&&&GUI.contentColor&=&Color.&&&&&&GUILayout.Label(&deltaTime&is:&&&&#43;&Time.deltaTime);&&}&&
18)分发消息
sendMessage,&BroadcastMessage等
19) 游戏暂停(对timeScale进行设置)
Time.timeScale&=&0;&&
20) 实例化一个prefab
Rigidbody2D&propInstance&=&Instantiate(backgroundProp,&spawnPos,&Quaternion.identity)&as&Rigidbody2D;&&
21)Lerp函数的使用场景
&&healthBar.material.color&=&Color.Lerp(Color.green,&Color.red,&1&-&health&*&0.01f);&&
22)在特定位置播放声音
&&AudioSource.PlayClipAtPoint(bombsAway,transform.position);&&
23) 浮点数相等的判断(由于浮点数有误差, 所以判断的时候最好不要用等号,尤其是计算出来的结果)
if&(Mathf.Approximately(1.0,&10.0/10.0))&&&&&&print&(&same&);&&
24)通过脚本修改shader中uniform的&#20540;
&&Properties&{&&&&&&...&&&&&&disHeight&(&threshold&distance&,&Float)&=&3&&}&&&&&SubShader&{&&&&&&Pass&{&&&&&&&&&&CGPROGRAM&&&&&&&&&&#pragma&vertex&vert&&&&&&&&&&&&#pragma&fragment&frag&&&&&&&&&&&...&&&&&&&&&&uniform&float&disH&&&&&&&&&&...&&&&&&&gameObject.renderer.sharedMaterial.SetFloat(&disHeight&,&height);&&
25) 获取当前level的名称
Application.loadedLevelName&&
26)双击事件
void&OnGUI()&{&&&&&&Event&Mouse&=&Event.&&&&&&if&(&Mouse.isMouse&&&&Mouse.type&==&EventType.MouseDown&&&&Mouse.clickCount&==&2)&{&&&&&&&&&&print(&Double&Click&);&&&&&&}&&}&&
27) 日期:
System.DateTime&dd&=&System.DateTime.N&&GUILayout.Label(dd.ToString(&M/d/yyyy&));&&
28) &RootAnimation中移动的脚本处理
class&RootControl&:&MonoBehaviour&{&&&&&&void&OnAnimatorMove()&{&&&&&&&&&&Animator&anim&=&GetComponent&Animator&();&&&&&&&&&&if(anim)&{&&&&&&&&&&&&&&Vector3&newPos&=&transform.&&&&&&&&&&&&&&newPos.z&&#43;=&anim.GetFloat(&Runspeed&)&*&Time.deltaT&&&&&&&&&&&&&&transform.position&=&newP&&&&&&&&&&}&&&&&&}&&}&&
29) BillBoard效果(广告牌效果,或者向日葵效果,使得对象重视面向摄像机)
public&class&BillBoard&:&MonoBehaviour&{&&&&&&&&&&&&void&Update&()&{&&&&&&&&&&transform.LookAt(Camera.main.transform.position,&-Vector3.up);&&&&&&}&&}&&
30)script中的属性编辑器(Property Drawers),还可以自定义属性编辑器
其中Popup好像无效,但是enum类型的变量,能够达到Popup的效果
public&class&Example&:&MonoBehaviour&{&&&&&&public&string&playerName&=&&Unnamed&;&&&&&&&&[Multiline]&&&&&&public&string&playerBiography&=&&Please&enter&your&biography&;&&&&&&&&[Popup&(&Warrior&,&&Mage&,&&Archer&,&&Ninja&)]&&&&&&public&string&@class&=&&Warrior&;&&&&&&&&[Popup&(&Human/Local&,&&Human/Network&,&&AI/Easy&,&&AI/Normal&,&&AI/Hard&)]&&&&&&public&string&&&&&&&&&[Range&(0,&100)]&&&&&&public&float&health&=&100;&&&&&&&&[Regex&(@&^(?:\d{1,3}\.){3}\d{1,3}$&,&&Invalid&IP&address!\nExample:&'127.0.0.1'&)]&&&&&&public&string&serverAddress&=&&192.168.0.1&;&&&&&&&&[Compact]&&&&&&public&Vector3&forward&=&Vector3.&&&&&&&&[Compact]&&&&&&public&Vector3&target&=&new&Vector3&(100,&200,&300);&&&&&&&&public&ScaledCurve&&&&&&&public&ScaledCurve&&&&&&&&&[Angle]&&&&&&public&float&turnRate&=&(Mathf.PI&/&3)&*&2;&&}&&
31)Mobile下面使用lightmapping问题的解决方案
在mobile模式下,lightmapping可能没有反应,可以尝试使用mobile下的shader,可以解决问题。更多请参考:
32) Unity下画线的功能(用于debug)
Debug.DrawLine&(Vector3.zero,&new&Vector3&(10,&0,&0),&Color.red);&&
33)Shader中代码的复用(CGINCLUDE的使用)
Shader&&Self-Illumin/AngryBots/InterlacePatternAdditive&&{&&&&&&Properties&{&&&&&&&&&&_MainTex&(&Base&,&2D)&=&&white&&{}&&&&&&&&&&&&&&&&}&&&&&&&&&&&&CGINCLUDE&&&&&&&&&&&&#include&&UnityCG.cginc&&&&&&&&&&&&&sampler2D&_MainT&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&struct&v2f&{&&&&&&&&&&&&&&half4&pos&:&SV_POSITION;&&&&&&&&&&&&&&half2&uv&:&TEXCOORD0;&&&&&&&&&&&&&&half2&uv2&:&TEXCOORD1;&&&&&&&&&&};&&&&&&&&&&&&v2f&vert(appdata_full&v)&{&&&&&&&&&&&&&&v2f&o;&&&&&&&&&&&&&&&&&&&&&&&&&&&&return&o;&&&&&&&&&&&}&&&&&&&&&&&&&&&&&&&&fixed4&frag(&v2f&i&)&:&COLOR&{&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&return&colorT&&&&&&&&&&}&&&&&&&&&&&&ENDCG&&&&&&&&&&&&SubShader&{&&&&&&&&&&Tags&{&RenderType&&=&&Transparent&&&Queue&&=&&Transparent&&&Reflection&&=&&RenderReflectionTransparentAdd&&}&&&&&&&&&&Cull&Off&&&&&&&&&&ZWrite&Off&&&&&&&&&&Blend&One&One&&&&&&&&&&&&&&&&Pass&{&&&&&&&&&&&&&&&&CGPROGRAM&&&&&&&&&&&&&&&&&&&&#pragma&vertex&vert&&&&&&&&&&#pragma&fragment&frag&&&&&&&&&&#pragma&fragmentoption&ARB_precision_hint_fastest&&&&&&&&&&&&&&&&&&&&&ENDCG&&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&&&&&&&&}&&&&&&&FallBack&Off&&}&&
34)获取AnimationCurve的时长
_curve.keys[_curve.length-1].&&
35)C#中string转变成byte[]:
byte[]&b1&=&System.Text.Encoding.UTF8.GetBytes&(myString);&&byte[]&b2&=&System.Text.Encoding.ASCII.GetBytes&(myString);&&System.Text.Encoding.Default.GetBytes(sPara)&&new&ASCIIEncoding().GetBytes(cpara);&&char[]&cpara=new&char[bpara.length];&&for(int&i=0;i&&bpara.i&&#43;&#43;){char[i]=system.convert.tochar(bpara[i]);}&&&&&
list.Sort(delegate(Object&a,&Object&b)&{&return&pareTo(b.name);&});&&
37) NGUI的相关类关系:
38)使得脚本能够在editor中实时反映:
在脚本前加上:[ExecuteInEditMode], 参考UISprite。
39)隐藏相关属性
属性前加上 [HideInInspector],在shader中也适用;
public&class&ResourceLoad&:&MonoBehaviour&{&&&&&&[HideInInspector]&public&string&ressName&=&&Sphere&;&&&&&&public&string&baseUrl&=&&http://192.168.56.101/ResUpdate/{0}.assetbundle&;&&
Shader&&stalendp/imageShine&&{&&&&&&Properties&{&&&&&&&&&&[HideInInspector]&_image&(&image&,&2D)&=&&white&&{}&&&&&&&&&&_percent&(&_percent&,&Range(-5,&5))&=&1&&&&&&&&&&_angle(&_angle&,&Range(0,&1))&=&0&&&&&&}&&
40)属性的序列化
可被序列化的属性,可以显示在Inspector面板上(可以使用HideInInspector来隐藏);public属性默认是可被序列化的,private默认是不可序列化的。使得private属性可被序列化,可以使用[SerializeField]来修饰。如下:
[SerializeField]&private&string&ressName&=&&Sphere&;&&
41)Shader编译的多样化()
shader通常如下的写法:
#pragma multi_compile FANCY_STUFF_OFF FANCY_STUFF_ON
这样可以把Shader编译成多个版本。使用的时候,局部设置Material.EnableKeyword, DisableKeyword;或则 全局设置Shader.EnableKeyword and DisableKeyword进行设置。
42)多个scene共享内容
[csharp] &void&Awake()&{&&&&&&DontDestroyOnLoad(transform.gameObject);&&}&&43) 使用Animation播放unity制作的AnimationClip:
首先需要设置AnimationType的类型为1 (需要在animationClip的Debug模式的属性中进行设置,如下图。另外,如果需要在animator中播放动画,需要类型为2);
代码如下:
[csharp] string&clipName&=&&currentClip&;&&AnimationClip&clip&=&...;&&&&if&(anim&==&null)&{&&&&&&anim&=&gameObject.AddComponent&Animation&();&&}&&anim.AddClip(clip,&clipName);&&anim[clipName].speed&=&_speedS&&&&float&duration&=&anim[clipName].&&duration&/=&_speedS&&&&anim.Play(clipName);&&yield&return&new&WaitForSeconds(duration&&#43;&0.1f);&&&&anim.Stop();&&anim.RemoveClip(clipName);&&
44) RenderTexture的全屏效果
[csharp] MeshFilter&mesh&=&quard.GetComponent&MeshFilter&&();&&&&RenderTexture&rTex&=&new&RenderTexture&((int)cam.pixelWidth,&(int)cam.pixelHeight,&16);&&cam.targetTexture&=&rT&&mesh.renderer.material.mainTexture&=&rT&&shader端:
[csharp] #include&&UnityCG.cginc&&&&&&&&&&&&&&sampler2D&_MainT&&sampler2D&_NoiseT&&&&&&&&struct&v2f&{&&&&&&&&&&half4&pos:SV_POSITION;&&&&&&&&&&half2&uv&:&TEXCOORD0;&&&&&&&float4&srcPos:&TEXCOORD1;&&&&};&&&&&&v2f&vert(appdata_full&v)&{&&&&&&&&v2f&o;&&&&&&&&o.pos&=&mul&(UNITY_MATRIX_MVP,&v.vertex);&&&&&&&&o.uv&=&v.texcoord.&&&&&&o.srcPos&=&ComputeScreenPos(o.pos);&&&&&&return&o;&&&&}&&&&&&fixed4&frag(v2f&i)&:&COLOR0&{&&&&&&float&tmp&=&saturate(1-(length(i.uv-float2(0.5,0.5)))*2)*0.04;&&&&&&&&&&&&&&&&float2&wcoord&=&(i.srcPos.xy/i.srcPos.w)&&#43;&tex2D(_NoiseTex,&i.uv)&*&tmp&-&tmp/2;&&&&&&return&tex2D(_MainTex,&wcoord);&&}&&&&
45)使用RenderTexture制作屏幕特效:
[csharp] [ExecuteInEditMode]&&public&class&MyScreenEffect&:&MonoBehaviour&{&&&&&&...&&&&&&void&OnRenderImage(RenderTexture&source,&RenderTexture&dest)&{&&&&&&&&&&Graphics.Blit(source,&dest,&material);&&&&&&}&&}&&如果需要多次渲染,需要使用RenderTexture.GetTemporary生成临时的RenderTexture,这个方法会从unity维护的池中获取,所以在使用完RenderTexture后,尽快调用RenderTexture.ReleaseTemporary使之返回池中。 RenderTexture存在于GPU的DRAM中,具体实现可以参考Cocos2dx中的写法来理解(CCRenderTexture.cpp中有具体实现)。GPU的架构请参考:
46) 特定条件下暂停unity
在调试战斗的时候,需要在特定条件下暂停unity,以便查看一些对象的设置。可以使用Debug.Break();来达到目的。这是需要处于debug模式,才能够达到效果。
47)在特定exception发生时暂停执行;
默认情况下,unity在遇到异常时,是不会停止执行的。但是如果要在nullReferenceException等exception发生时,进行调试。可以在MonoDevelop的菜单中选择Run/Exceptions..., 做相关设置:
48)NGUI性能建议
相关知识:1)在NGUI中,一个Panel对应一个DrawCall(当然一个panel里面的UISprite来自多个图集,就会有多个drawCall);2)当一个UISprite等UIWidget控件的active改变时,DrawCall会重新计算一遍;3)DrawCall的计算比较耗时,首先会收集DrawCall下所有UIWidget的verts,norms,trans,uvs,cols等信息,还要向GPU传输数据,相对比较耗时。
问题:当在一个Panel中有大量的UIWidget,有一部分是经常改变active的,有些部分则不怎么变。这样就会导致频繁地计算DrawCall。
性能提升方案:把经常改变active的控件单独到一个panel中。把不怎么变动的部分独立到另外的panel中。
49)NGUI中设置自定义的Shader,并改变properties的&#20540;。
使用UITexture,可以设置自定义的Material。需要注意的是,改变properties的&#20540;,需要使用UITexture中的drawCall的dynamicMaterial,如下:
[cpp] UITexture&tex=....;&&tex.drawCall.dynamicMaterial.SetFloat(&_percent&,&du/DU);&&
50) 鉴别unity中的InputTouch的类型:
[csharp] public&enum&OperateStatus&{&&&&&&OS_Idle=0,&&&&&&OS_Draging=1,&&&&&&OS_Scaling=2&&}&&.....&&&&void&Update&()&{&&&&&......&&&&&&&&&TouchPhase&tp&=&Input.GetTouch(0).&&&&&&if(tp==TouchPhase.Ended&||&tp==TouchPhase.Canceled)&{&&&&&&&&&&oStatus&=&OperateStatus.OS_I&&&&&&}&else&{&&&&&&&&&&oStatus&=&Input.touchCount&1&?&OperateStatus.OS_Scaling&:&OperateStatus.OS_D&&&&&&}&&.....&&}&&51) 物理系统的性能提示:
Unity中涉及物理模拟的有静态碰撞(static collider)和动态碰撞(dynamic collider)。其中,静态碰撞物体是指具有collider属性但没有rigidbody的物体,动态碰撞物体是指具有collider和rigidbody属性的物体。
Unity引擎期待静态物体是静止,会把场景中的所有静态物体统一计算成一个叫static collider cache的东西来加速物理模拟。但是如果其中某个静态物体进行了移动,系统就要重新计算static collider cache;而这个代价是很大的。所以如果一个物体是要经常移动的,应该设计成动态物体,即添加rigidbody成分;至于使rigidbody不响应重力等作用力的影响,请参考rigidbody中的&Use Gravity&和“Is Kinematic”属性。
如果rigidbody是kinematic的,它不响应force,可以用来制作飞行障碍物等效果。如果不是kinematic的,就会响应foce。
参考如下官方教程最后的性能分析:
52) unity中四种Collider的对比:
类型能否移动是否接收Trigger消息是否受碰撞影响是否受物理影响Static代价大NoNoNoKinematic
RigidbodyYesYesNoNoCharacter ControllerYes未知YesNoRigidbodyYesYesYesYes
仔细观察上面的表&#26684;,发现越往下,特性越多。官方在介绍collision的时候,没有加入讨论Character Controller,这个是我自己添加比较的。
另外,如果一个物体能够受碰撞影响,当然就能够接收Collition消息了。
关于接收Collision消息和Trigger消息的官方的详细表,请参考 的文末的表&#26684;。53) 使一个物体依附在一个表面上,保持物体的up方向和表面的法线方向一致(物体记为obj,表面记为suf):方法1:[csharp] obj.transform.rotation&=&Quaternion.FromToRotation(obj.transform.up,&suf.transform.up)*&obj.transform.&&方法2:[csharp] Vector3&axis&=&Vector3.Cross(obj.transform.up,&suf.transform.up);&&float&angle&=&Vector3.Angle(obj.transform.up,&suf.transform.up);&&obj.transform.Rotate(axis,&angle,&Space.World);&&54)AngryBots中的showFPS代码:
[javascript] @script&ExecuteInEditMode&&&&private&var&gui&:&GUIT&&&&private&var&updateInterval&=&1.0;&&private&var&lastInterval&:&double;&&&private&var&frames&=&0;&&&&&function&Start()&&{&&&&&&lastInterval&=&Time.realtimeSinceS&&&&&&frames&=&0;&&}&&&&function&OnDisable&()&&{&&&&&&if&(gui)&&&&&&&&&&DestroyImmediate&(gui.gameObject);&&}&&&&function&Update()&&{&&#if&!UNITY_FLASH&&&&&&&#43;&#43;&&&&&&var&timeNow&=&Time.realtimeSinceS&&&&&&if&(timeNow&&&lastInterval&&#43;&updateInterval)&&&&&&{&&&&&&&&&&if&(!gui)&&&&&&&&&&{&&&&&&&&&&&&&&var&go&:&GameObject&=&new&GameObject(&FPS&Display&,&GUIText);&&&&&&&&&&&&&&go.hideFlags&=&HideFlags.HideAndDontS&&&&&&&&&&&&&&go.transform.position&=&Vector3(0,0,0);&&&&&&&&&&&&&&gui&=&go.guiT&&&&&&&&&&&&&&gui.pixelOffset&=&Vector2(5,55);&&&&&&&&&&}&&&&&&&&&&var&fps&:&float&=&frames&/&(timeNow&-&lastInterval);&&&&&&&&&&var&ms&:&float&=&1000.0f&/&Mathf.Max&(fps,&0.00001);&&&&&&&&&&gui.text&=&ms.ToString(&f1&)&&#43;&&ms&&&&#43;&fps.ToString(&f2&)&&#43;&&FPS&;&&&&&&&&&&frames&=&0;&&&&&&&&&&lastInterval&=&timeN&&&&&&}&&#endif&&}&&55)关于Hierarchy中按名称的字母排序功能:
[csharp] public&class&AlphaNumericSort&:&BaseHierarchySort&&{&&&&&&public&override&int&Compare(GameObject&lhs,&GameObject&rhs)&&&&&&{&&&&&&&&&&if&(lhs&==&rhs)&return&0;&&&&&&&&&&if&(lhs&==&null)&return&-1;&&&&&&&&&&if&(rhs&==&null)&return&1;&&&&&&&&&&&&return&EditorUtility.NaturalCompare(lhs.name,&rhs.name);&&&&&&}&&}&&
把上面的代码放到工程中之后,在Hierarchy中就会出现排序的按钮,如下:
BaseHierarchySort的官方地址:
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:93489次
积分:1378
积分:1378
排名:千里之外
原创:44篇
转载:29篇
评论:15条
(2)(2)(1)(1)(5)(5)(4)(2)(1)(3)(5)(1)(9)(1)(3)(2)(9)(17)5484人阅读
你知道C#有一个内置的事件机制吗?这个东东在Unity3D里也非常好用。下面举一个例子。&
为了响应一个GameObject的事件分发,你通常要建立一个脚本继承MonoBehaviour并且实现你需要的方法。比如你想对鼠标悬停作出反应,就要创建OnMouseOver方法。通常代码会像这个样子:&
void&OnMouseOver&()&{&&
&&renderer.material.color&=&Color.&&
这样工作没问题。但如果你想通知另外一个对象响应这个事件(OnMouseOver事件)怎么办?&
第一种方式是保持另外对象的脚本引用,然后在你的OnMouseOver方法中调用它:&
public&MyScript&myS&&
void&OnMouseOver&()&{&&
&&myScript.NotifyMouseOver();&&
这样做没问题,但是不够好。因为你需要一直保持另外一个对象的引用,如果想通知多个对象要保持多个引用。代码会变得很乱。&
Messages 消息&
另一个办法是用SendMessage或SendMessageUpwards方法。看上去这是解决问题的最好办法,但是这些方法存在严重的缺陷,以我的观点,你应该尽量不去使用它们。&
这些方法的语法并不灵活,你需要传递一个方法名字的字符串,这样做很容易出错。另外这些方法只能用在同一个对象的附属关系中。换句话说你只能在下面几种情况中调用SendMessage或SendMessageUpwards方法,这些方法的脚本被关联到同一个GameObject中,或者被关联到这个GameObject的祖先关系对象中。&
Events 事件&
幸运的是有一个更好的解决办法,这就是C#内置的事件机制。我不在这里过多的描述机制是如何工作的,你如果有兴趣可以学习相关的知识,访问。(译者推荐另外一篇文章,)&
现在让我们看看如何在Unity3D中使用事件机制。&
using&UnityE&&
public&class&EventDispatcher&:&MonoBehaviour&{&&
&&public&delegate&void&EventHandler(GameObject&e);&&
&&public&event&EventHandler&MouseO&&
&&void&OnMouseOver&()&{&&
&&&&if&(MouseOver&!=&null)&&
&&&&&&&&MouseOver&(this.gameObject);&&
如果你不知道这段代码到底干什么,先不要着急。重要的是一旦你把这段代码关联到一个GameObject,只要在整个项目的任何一个脚本中保持这个对象,你就可以像下面这样处理事件:&
private&GameObject&s;&&
s.GetComponent&EventDispatcher&().MouseOver&&#43;=&L&&
void&Listener(GameObject&g)&{&&
这种方式比用消息更灵活,因为它可以被用在任何一个脚本中,而不仅仅在同一个对象附属关系中。如果在整个应用中保持一个单例模式的对象,你就可以监听任何从这个对象分发出来的事件。
另外一个重要特点,同一个监听方法可以响应不同对象的事件。通过传递事件源对象的引用作为参数,你总会知道哪个对象分发了事件,就像我的代码展示的那样。(对于这句话可以这样理解,假如游戏中扔一颗导弹炸死了一个小兵并导致坦克减血,小兵死亡和坦克减血这两个事件都触发了同一个监听方法-玩家得分,通过传递进来的事件源对象,就能知道小兵还是坦克触发了玩家得分这个监听方法。)&
References, controllers and MVC&
现在让我们比较一下第一和第三种方式。在最开始的例子中(第一种方式保持另外对象的脚本引用),你需要在事件分发代码中保持监听者的对象引用,我说了这不是一个好主意。在用内置事件机制,改进的版本中(第三种方式),你需要在监听者代码中保持事件分发者的引用。你也许会问,为什么后者更好?&
首先,分发者不需要知道自己事件的监听者是谁,不需要知道有多少监听者。它只负责事件的发送。在最开始的例子中(第一种方式),如果要告诉分发者停止通知监听者,你能想象这种程序判断有多么笨重吗?&
事件机制中,是由监听者自己决定监听什么事件,什么时候开始监听,什么时候停止监听。像这样的对象通常用于管理程序的状态或者执行某些游戏逻辑。这个就叫做控制器,借用MVC设计模式的概念。这样我们的代码会更清晰,不易出错。(译者认为观察者设计模式更符合)&
最后一点,我喜欢重载“&#43;=”操作符去添加监听方法。现在你也许能够猜到,如果想结束监听某个事件,可以这么写:&
s.GetComponent&EventDispatcher&().MouseOver&-=&L&&
当然你可以创建一个通用的EventDispatcher类,实现所有GameObject能够分发的事件。可以参看下面的代码。另外在实现OnGUI事件时要特别小心,如果想知道为什么,参考这篇文章:。
using&UnityE&&
using&System.C&&
public&class&EventDispatcher&:&MonoBehaviour&&
&&&&public&delegate&void&EventHandler&(GameObject&e);&&
&&&&public&delegate&void&CollisionHandler&(GameObject&e,&Collision&c);&&
&&&&public&event&EventHandler&MouseO&&
&&&&void&OnMouseOver&()&&
&&&&&&&&if&(MouseOver&!=&null)&&
&&&&&&&&&&&&MouseOver&(this.gameObject);&&
&&&&public&event&EventHandler&MouseD&&
&&&&void&OnMouseDown&()&&
&&&&&&&&if&(MouseDown&!=&null)&&
&&&&&&&&&&&&MouseDown&(this.gameObject);&&
&&&&public&event&EventHandler&MouseE&&
&&&&void&OnMouseEnter&()&&
&&&&&&&&if&(MouseEnter&!=&null)&&
&&&&&&&&&&&&MouseEnter&(this.gameObject);&&
&&&&public&event&EventHandler&MouseE&&
&&&&void&OnMouseExit&()&&
&&&&&&&&if&(MouseExit&!=&null)&&
&&&&&&&&&&&&MouseExit&(this.gameObject);&&
&&&&public&event&EventHandler&BecameV&&
&&&&void&OnBecameVisible&()&&
&&&&&&&&if&(BecameVisible&!=&null)&&
&&&&&&&&&&&&BecameVisible&(this.gameObject);&&
&&&&public&event&EventHandler&BecameI&&
&&&&void&OnBecameInvisible&()&&
&&&&&&&&if&(BecameInvisible&!=&null)&&
&&&&&&&&&&&&BecameInvisible&(this.gameObject);&&
&&&&public&event&CollisionHandler&CollisionE&&
&&&&void&OnCollisionEnter&(Collision&c)&&
&&&&&&&&if&(CollisionEnter&!=&null)&&
&&&&&&&&&&&&CollisionEnter&(this.gameObject,&c);&&
&&&&public&event&CollisionHandler&CollisionE&&
&&&&void&OnCollisionExit&(Collision&c)&&
&&&&&&&&if&(CollisionExit&!=&null)&&
&&&&&&&&&&&&CollisionExit&(this.gameObject,&c);&&
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:69875次
排名:千里之外
原创:29篇
转载:21篇
评论:12条
(3)(1)(1)(4)(6)(1)(10)(1)(5)(18)}

我要回帖

更多关于 unity多层继承注入 的文章

更多推荐

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

点击添加站长微信