Unity技巧2

转发,请保持地址:http://blog.csdn.net/stalendp/article/details/46707079

相关的文章:【Unity】技巧集合

1. 调试相关

[csharp]  view plain copy
  1. Debug.DrawRay(transform.position, newDir, Color.red);  

2. uGui的层级问题。(参考Canvas中的Draw Order of Elements)

uGUI的元素的渲染循序和Hierarchy中的循序一致,从上往下渲染(后面的会覆盖之前的)。在脚本中可以通过transform的SetAsFirstSibling, SetAsLastSibling, and SetSiblingIndex.函数来设置循序。比如下面的代码,把当前选择的物体置顶。

[csharp]  view plain copy
  1. curSelected.transform.SetAsLastSibling();  

3. 摄像机移动代码

[csharp]  view plain copy
  1. public class DragMap : MonoBehaviour {  
  2.       
  3.     public Vector3 speed = Vector3.zero;  
  4.     public bool isFlying = false;  
  5.     public float threshold = 0.2f;  
  6.   
  7.     Camera mainCam;  
  8.     Vector3 startPos;  
  9.     int groundLayer;  
  10.   
  11.     Vector3[] speedCache ;  
  12.     int idx = 0;  
  13.     bool isDragging = false;  
  14.   
  15.     // Use this for initialization  
  16.     void Start () {  
  17.         groundLayer = 1 << LayerMask.NameToLayer ("ground");  
  18.         mainCam = Camera.main;  
  19.         speedCache = new Vector3[5];  
  20.         isFlying = false;  
  21.     }  
  22.       
  23.     // Update is called once per frame  
  24.     void Update () {  
  25.         if (Input.GetMouseButtonDown (0)) {  
  26.             RaycastHit hit;  
  27.             if (Physics.Raycast (mainCam.ScreenPointToRay (Input.mousePosition), out hit, Mathf.Infinity, groundLayer)) {    
  28.                 startPos = hit.point;  
  29.                 speed = Vector3.zero;  
  30.                 idx = 0;  
  31.                 for(int i=0; i<speedCache.Length; i++) {  
  32.                     speedCache[i] = Vector3.zero;  
  33.                 }  
  34.                 isDragging = true;  
  35.             }  
  36.   
  37.         } else if(Input.GetMouseButtonUp(0)) {  
  38.             speed = Vector3.zero;  
  39.             foreach(Vector3 s in speedCache) {  
  40.                 speed += s;  
  41.             }  
  42.             speed /= 5;  
  43.             isFlying = speed.magnitude > threshold;  
  44.             isDragging = false;  
  45.         }  
  46.   
  47.         if (isDragging) {  
  48.             RaycastHit hit;  
  49.             if (Physics.Raycast (mainCam.ScreenPointToRay (Input.mousePosition), out hit, Mathf.Infinity, groundLayer)) {    
  50.                 Vector3 offset = hit.point - startPos;  
  51.                 mainCam.transform.position -= offset;  
  52.                 speedCache [idx++ % 5] = offset;  
  53.             }  
  54.         } else if (isFlying) {  
  55.             speed *= 0.9f;  
  56.             isFlying = speed.magnitude > threshold;  
  57.             mainCam.transform.position -= speed;  
  58.         }  
  59.     }  
  60. }  

4. 协同的用法(IEnumerator)

[csharp]  view plain copy
  1. IEnumerator Start() {  
  2.     Debug.Log ("zero: " + Time.time);  
  3.     yield return StartCoroutine (mywait (3f));  
  4.     Debug.Log ("one: " + Time.time);  
  5.     yield return StartCoroutine (mywait (2f));  
  6.     Debug.Log ("two: " + Time.time);  
  7. }  

关于Coroutines,以便能够获取更多的功能:
1)Coroutines – More than you want to know:http://twistedoakstudios.com/blog/Post83_coroutines-more-than-you-want-to-know
2)Unity coroutine (Coroutine) principle deeply again:http://www.programering.com/a/MTOzgjNwATI.html
3)Wrapping Unity C# Coroutines for Exception Handling, Value Retrieval, and Locking:http://www.zingweb.com/blog/2013/02/05/unity-coroutine-wrapper
Coroutine的实现参考:https://github.com/rozgo/Unity.Coroutine/blob/master/Coroutine.cs


5. 回调相关:UnityEventSystem.Action和System.Func; 都是delegate,相当于函数指针;前者没有返回值,后者有返回值。其中UnityEvent和System.Action基本相同,但是UnityEvent可以被序列化,最显著的优点是可以在Inspector上被编辑(比如新UI控件ScrollRect中的OnValueChanged属性),两者差异性参考这里的讨论,用法:

5a) System.Func的用法:

[csharp]  view plain copy
  1. public struct AstarWorkItem {  
  2.     //....  
  3.     public System.Func<boolbool> update;  
  4.     //....  
  5.     public AstarWorkItem (System.Func<boolbool> update) {  
  6.         this.update = update;  
  7.     }  
  8. }  
  9. //...  
  10. AddWorkItem (new AstarWorkItem (delegate (bool force) {  
  11.     InternalOnPostScan ();  
  12.     return true;  
  13. }));  

也可以简写为:

[csharp]  view plain copy
  1. public struct AstarWorkItem {  
  2.     public System.Func<boolbool> update;  
  3. }  
  4. // ...  
  5. AddWorkItem (new AstarWorkItem () {  
  6.     update = (force) => {  
  7.         InternalOnPostScan ();  
  8.         return true;  
  9.     }  
  10. });  
5b)UnityEvent的用法

[csharp]  view plain copy
  1. [Serializable]  
  2. public class ScrollRectEvent : UnityEvent<Vector2> {}  
  3.   
  4. // class members  
  5. [SerializeField]  
  6. private ScrollRectEvent m_OnValueChanged = new ScrollRectEvent();  
  7. public ScrollRectEvent onValueChanged { get { return m_OnValueChanged; } set { m_OnValueChanged = value; } }  
  8.   
  9. // invoke ...  
  10. onValueChanged.AddListener (offset => {  
  11.     Debug.Log("ScrollRect is changed, offset is : " + offset.ToString());  
  12. });  

6. 在Raycast中忽略trigger Colliders的方法:

Edit > Project Settings > Physics > Uncheck "Raycasts Hit Triggers"

7. 粒子系统操作:

[csharp]  view plain copy
  1. // stop particalSystem  
  2. waterEffect.Stop();  
  3.   
  4. // restart particalSystem  
  5. waterEffect.Simulate(0);  
  6. waterEffect.Play();  

8. C#中的特殊的操作符:https://msdn.microsoft.com/en-us/library/6a71f45d.aspx

其中NullableTypes,参考:https://msdn.microsoft.com/en-us/library/1t3y8s4s.aspx

8-1)Boxing nullable types:  int?  float?  double?      把基本类型变为object类型;其值可以为null,也可以有相关转化操作。

[csharp]  view plain copy
  1. //## Example 1: Nullable objects and their boxed counterpart can be tested for null:  
  2. bool? b = null;  
  3. object boxedB = b;  
  4. if (b == null) {  
  5.     // True.  
  6. }  
  7. if (boxedB == null) {  
  8.     // Also true.  
  9. }  
  10.   
  11.   
  12. //## Example 2: Boxed nullable types fully support the functionality of the underlying type:  
  13. double? d = 44.4;  
  14. object iBoxed = d;  
  15. // Access IConvertible interface implemented by double.  
  16. IConvertible ic = (IConvertible)iBoxed;  
  17. int i = ic.ToInt32(null);  
  18. string str = ic.ToString();  

8-2)  Null-conditional Operators:  ?.  ?[]   在访问自对象之前,先判断null,这样可以简化代码。C# 6的新特性,在Unity中好似无法使用

[csharp]  view plain copy
  1. int? length = customers?.Length; // null if customers is null   
  2. Customer first = customers?[0];  // null if customers is null  
  3. int? count = customers?[0]?.Orders?.Count();    
  4.                                   // null if customers, the first customer, or Orders is null  
[csharp]  view plain copy
  1. var handler = this.PropertyChanged;  
  2. if (handler != null)  
  3.     handler(…)  
  4.   
  5. ===简化为==》  
  6.   
  7. PropertyChanged?.Invoke(e)  

8-3)  Null-coalescing Operator:  x ?? y

[csharp]  view plain copy
  1. class NullCoalesce  
  2. {  
  3.     static int? GetNullableInt()  
  4.     {  
  5.         return null;  
  6.     }  
  7.   
  8.     static string GetStringValue()  
  9.     {  
  10.         return null;  
  11.     }  
  12.   
  13.     static void Main()  
  14.     {  
  15.         int? x = null;  
  16.   
  17.         // Set y to the value of x if x is NOT null; otherwise,   
  18.         // if x = null, set y to -1.   
  19.         int y = x ?? -1;  
  20.   
  21.         // Assign i to return value of the method if the method's result   
  22.         // is NOT null; otherwise, if the result is null, set i to the   
  23.         // default value of int.   
  24.         int i = GetNullableInt() ?? default(int);  
  25.   
  26.         string s = GetStringValue();  
  27.         // Display the value of s if s is NOT null; otherwise,    
  28.         // display the string "Unspecified".  
  29.         Console.WriteLine(s ?? "Unspecified");  
  30.     }  
  31. }  
8-4) How to: Safely Cast from bool? to bool

[csharp]  view plain copy
  1. bool? b = null;  
  2. if (b) // Error CS0266.  
  3. {  
  4. }  
  5.   
  6. ===改成==>>  
  7.   
  8. bool? test = null;  
  9. // Other code that may or may not  
  10. // give a value to test.  
  11. if(!test.HasValue) //check for a value  
  12. {  
  13.     // Assume that IsInitialized  
  14.     // returns either true or false.  
  15.     test = IsInitialized();  
  16. }  
  17. if((bool)test) //now this cast is safe  
  18. {  
  19.    // Do something.  
  20. }  

9. Unity中“单例“的一般实现方案:

[csharp]  view plain copy
  1. public static EventSystem current { getset; }  
  2. ...  
  3. protected void OnEnable()  
  4. {  
  5.     if (EventSystem.current == null)  
  6.         EventSystem.current = this;  
  7. #if UNITY_EDITOR  
  8.     else  
  9.     {  
  10.         Debug.LogWarning("Multiple EventSystems in scene... this is not supported");  
  11.     }  
  12. #endif  
  13. }  

10. 初始化变量的一种简略方式

[csharp]  view plain copy
  1. PointerEventData ped = new PointerEventData (EventSystem.current);  
  2. ped.position = Input.mousePosition;  
  3. EventSystem.current.RaycastAll (ped, hits);  
  4.   
  5. ===简化为==>  
  6.   
  7. EventSystem.current.RaycastAll (new PointerEventData (EventSystem.current) {  
  8.     position = Input.mousePosition  
  9. }, hits);  

11. Unity中新UI的消息处理方式(借助EventSystem中的Raycast获取当前的UI,并发送消息)

具体参考文章:http://gregandaduck.blogspot.com/2015/02/using-unitys-c-message-system-unity-46.html

消息接受方,实现如下:

[csharp]  view plain copy
  1. using UnityEngine;  
  2. using UnityEngine.UI;  
  3. using UnityEngine.EventSystems;  
  4. using System.Collections;  
  5.   
  6. // refer to http://gregandaduck.blogspot.com/2015/02/using-unitys-c-message-system-unity-46.html  
  7. public interface IMyMouseOver : IEventSystemHandler {  
  8.     void mouseOver(string str);  
  9.     void mouseLeaving();  
  10. }  
  11.   
  12. public class MyDisplayText : MonoBehaviour, IMyMouseOver {  
  13.     public Text text;  
  14.     public void mouseOver(string str) {  
  15.         if (!text.enabled) {  
  16.             text.text = str;  
  17.             text.enabled = true;  
  18.         }  
  19.     }  
  20.     public void mouseLeaving() {  
  21.         if (text.enabled) {  
  22.             text.enabled = false;  
  23.         }  
  24.     }  
  25. }  

消息发送方,实现如下:

[csharp]  view plain copy
  1. using UnityEngine;  
  2. using UnityEngine.EventSystems;  
  3. using System.Collections;  
  4. using System.Collections.Generic;  
  5.   
  6. public class MyMouseOver : MonoBehaviour {  
  7.     GameObject prevObject;  
  8.     void Update () {  
  9.         GameObject target = getMouseOver ();  
  10.         if (target) {  
  11.             prevObject = target;  
  12.             ExecuteEvents.Execute<IMyMouseOver> (target, null, (handle, data) => {  
  13.                 handle.mouseOver ("Mouse Over Active, frame: " + Time.frameCount);  
  14.             });  
  15.         } else {  
  16.             if(prevObject) {  
  17.                 ExecuteEvents.Execute<IMyMouseOver>(prevObject, null, (handle, data) =>{  
  18.                     handle.mouseLeaving();  
  19.                 });  
  20.                 prevObject = null;  
  21.             }  
  22.         }  
  23.     }  
  24.   
  25.     private GameObject getMouseOver() {  
  26.         List<RaycastResult> hits = new List<RaycastResult>();  
  27.         EventSystem.current.RaycastAll (new PointerEventData (EventSystem.current) {  
  28.             position = Input.mousePosition  
  29.         }, hits);  
  30.         foreach (RaycastResult rr in hits) {  
  31.             GameObject go = rr.gameObject;  
  32.             if(go)  
  33.                 return go;  
  34.         }  
  35.         return null;  
  36.     }  
  37. }  

12. 在C#中模拟Java中的匿名类写法(有点Javascript的味道):

[csharp]  view plain copy
  1. public class HpBarHandler {  // 当然这里用struct会显得把delegate更加看作为数据  
  2.     public System.Action<float> changeHp;  
  3.     public System.Action hidde;  
  4.     public System.Action show;  
  5.     public System.Action destory;  
  6. }  
  7.   
  8. public void registerHPBarEvent(HpBarHandler _hphandler) {  
  9.     hphandler = _hphandler;  
  10. }  
  11.   
  12. fightUnit.registerHPBarEvent (new HpBarHandler () {  
  13.     changeHp = hp => {  
  14.         size.x = 200 * hp;  
  15.         if(rectTrans) {  
  16.             rectTrans.sizeDelta = size;  
  17.             if(hp<=0) {  
  18.                 GameObject.Destroy (gameObject);  
  19.             }  
  20.         }  
  21.     },  
  22.     hidde = delegate{  
  23.         gameObject.SetActive(false);  
  24.     },  
  25.     show = delegate {  
  26.         gameObject.SetActive(true);  
  27.     },  
  28.     destory = delegate {  
  29.         GameObject.Destroy (gameObject);  
  30.     }  
  31. });  

13. 工作中总是遇到初始化某个单位时,依赖其他的单位还未初始化,导致了NullReferenceException。这个是因为所有的初始化都写在了Start方法中,这样由于代码初始化的前后顺序,导致了上面的问题。解决方案就是把初始化分阶段进行。能够导致NullReferenceException的,比如GetCompent,Find等操作,写在Awake或OnEnable方法中等。逻辑初始化写在Start中等。下面是Script Lifecycle的示意图,官方文档为:http://docs.unity3d.com/Manual/ExecutionOrder.html


14. 浮点数格式化

[csharp]  view plain copy
  1. //List<Vector3> uvList = ...;  
  2. Debug.Log (string.Format("frame: {0:0.00}, uvs: {1}, {2}, {3}, {4}",  
  3.                          0.125f,  
  4.                          uvList[0].ToString("0.000"),   
  5.                          uvList[1].ToString("0.000"),   
  6.                          uvList[2].ToString("0.000"),   
  7.                          uvList[3].ToString("0.000")   
  8.                          ));  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值