转发,请保持地址:http://blog.youkuaiyun.com/stalendp/article/details/46707079
相关的文章:【Unity】技巧集合
1. 调试相关
- Debug.DrawRay(transform.position, newDir, Color.red);
2. uGui的层级问题。(参考Canvas中的Draw Order of Elements)
uGUI的元素的渲染循序和Hierarchy中的循序一致,从上往下渲染(后面的会覆盖之前的)。在脚本中可以通过transform的SetAsFirstSibling, SetAsLastSibling, and SetSiblingIndex.函数来设置循序。比如下面的代码,把当前选择的物体置顶。
- curSelected.transform.SetAsLastSibling();
3. 摄像机移动代码
- public class DragMap : MonoBehaviour {
- public Vector3 speed = Vector3.zero;
- public bool isFlying = false;
- public float threshold = 0.2f;
- Camera mainCam;
- Vector3 startPos;
- int groundLayer;
- Vector3[] speedCache ;
- int idx = 0;
- bool isDragging = false;
- // Use this for initialization
- void Start () {
- groundLayer = 1 << LayerMask.NameToLayer ("ground");
- mainCam = Camera.main;
- speedCache = new Vector3[5];
- isFlying = false;
- }
- // Update is called once per frame
- void Update () {
- if (Input.GetMouseButtonDown (0)) {
- RaycastHit hit;
- if (Physics.Raycast (mainCam.ScreenPointToRay (Input.mousePosition), out hit, Mathf.Infinity, groundLayer)) {
- startPos = hit.point;
- speed = Vector3.zero;
- idx = 0;
- for(int i=0; i<speedCache.Length; i++) {
- speedCache[i] = Vector3.zero;
- }
- isDragging = true;
- }
- } else if(Input.GetMouseButtonUp(0)) {
- speed = Vector3.zero;
- foreach(Vector3 s in speedCache) {
- speed += s;
- }
- speed /= 5;
- isFlying = speed.magnitude > threshold;
- isDragging = false;
- }
- if (isDragging) {
- RaycastHit hit;
- if (Physics.Raycast (mainCam.ScreenPointToRay (Input.mousePosition), out hit, Mathf.Infinity, groundLayer)) {
- Vector3 offset = hit.point - startPos;
- mainCam.transform.position -= offset;
- speedCache [idx++ % 5] = offset;
- }
- } else if (isFlying) {
- speed *= 0.9f;
- isFlying = speed.magnitude > threshold;
- mainCam.transform.position -= speed;
- }
- }
- }
4. 协同的用法(IEnumerator)
- IEnumerator Start() {
- Debug.Log ("zero: " + Time.time);
- yield return StartCoroutine (mywait (3f));
- Debug.Log ("one: " + Time.time);
- yield return StartCoroutine (mywait (2f));
- Debug.Log ("two: " + Time.time);
- }
关于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. 回调相关:UnityEvent和System.Action和System.Func; 都是delegate,相当于函数指针;前者没有返回值,后者有返回值。其中UnityEvent和System.Action基本相同,但是UnityEvent可以被序列化,最显著的优点是可以在Inspector上被编辑(比如新UI控件ScrollRect中的OnValueChanged属性),两者差异性参考这里的讨论,用法:
5a) System.Func的用法:
- public struct AstarWorkItem {
- //....
- public System.Func<bool, bool> update;
- //....
- public AstarWorkItem (System.Func<bool, bool> update) {
- this.update = update;
- }
- }
- //...
- AddWorkItem (new AstarWorkItem (delegate (bool force) {
- InternalOnPostScan ();
- return true;
- }));
也可以简写为:
- public struct AstarWorkItem {
- public System.Func<bool, bool> update;
- }
- // ...
- AddWorkItem (new AstarWorkItem () {
- update = (force) => {
- InternalOnPostScan ();
- return true;
- }
- });
- [Serializable]
- public class ScrollRectEvent : UnityEvent<Vector2> {}
- // class members
- [SerializeField]
- private ScrollRectEvent m_OnValueChanged = new ScrollRectEvent();
- public ScrollRectEvent onValueChanged { get { return m_OnValueChanged; } set { m_OnValueChanged = value; } }
- // invoke ...
- onValueChanged.AddListener (offset => {
- Debug.Log("ScrollRect is changed, offset is : " + offset.ToString());
- });
6. 在Raycast中忽略trigger Colliders的方法:
Edit > Project Settings > Physics > Uncheck "Raycasts Hit Triggers"
7. 粒子系统操作:
- // stop particalSystem
- waterEffect.Stop();
- // restart particalSystem
- waterEffect.Simulate(0);
- 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,也可以有相关转化操作。
- //## Example 1: Nullable objects and their boxed counterpart can be tested for null:
- bool? b = null;
- object boxedB = b;
- if (b == null) {
- // True.
- }
- if (boxedB == null) {
- // Also true.
- }
- //## Example 2: Boxed nullable types fully support the functionality of the underlying type:
- double? d = 44.4;
- object iBoxed = d;
- // Access IConvertible interface implemented by double.
- IConvertible ic = (IConvertible)iBoxed;
- int i = ic.ToInt32(null);
- string str = ic.ToString();
8-2) Null-conditional Operators: ?. ?[] 在访问自对象之前,先判断null,这样可以简化代码。C# 6的新特性,在Unity中好似无法使用
- int? length = customers?.Length; // null if customers is null
- Customer first = customers?[0]; // null if customers is null
- int? count = customers?[0]?.Orders?.Count();
- // null if customers, the first customer, or Orders is null
- var handler = this.PropertyChanged;
- if (handler != null)
- handler(…)
- ===简化为==》
- PropertyChanged?.Invoke(e)
8-3) Null-coalescing Operator: x ?? y
- class NullCoalesce
- {
- static int? GetNullableInt()
- {
- return null;
- }
- static string GetStringValue()
- {
- return null;
- }
- static void Main()
- {
- int? x = null;
- // Set y to the value of x if x is NOT null; otherwise,
- // if x = null, set y to -1.
- int y = x ?? -1;
- // Assign i to return value of the method if the method's result
- // is NOT null; otherwise, if the result is null, set i to the
- // default value of int.
- int i = GetNullableInt() ?? default(int);
- string s = GetStringValue();
- // Display the value of s if s is NOT null; otherwise,
- // display the string "Unspecified".
- Console.WriteLine(s ?? "Unspecified");
- }
- }
- bool? b = null;
- if (b) // Error CS0266.
- {
- }
- ===改成==>>
- bool? test = null;
- // Other code that may or may not
- // give a value to test.
- if(!test.HasValue) //check for a value
- {
- // Assume that IsInitialized
- // returns either true or false.
- test = IsInitialized();
- }
- if((bool)test) //now this cast is safe
- {
- // Do something.
- }
9. Unity中“单例“的一般实现方案:
- public static EventSystem current { get; set; }
- ...
- protected void OnEnable()
- {
- if (EventSystem.current == null)
- EventSystem.current = this;
- #if UNITY_EDITOR
- else
- {
- Debug.LogWarning("Multiple EventSystems in scene... this is not supported");
- }
- #endif
- }
10. 初始化变量的一种简略方式
- PointerEventData ped = new PointerEventData (EventSystem.current);
- ped.position = Input.mousePosition;
- EventSystem.current.RaycastAll (ped, hits);
- ===简化为==>
- EventSystem.current.RaycastAll (new PointerEventData (EventSystem.current) {
- position = Input.mousePosition
- }, hits);
11. Unity中新UI的消息处理方式(借助EventSystem中的Raycast获取当前的UI,并发送消息)
具体参考文章:http://gregandaduck.blogspot.com/2015/02/using-unitys-c-message-system-unity-46.html
消息接受方,实现如下:
- using UnityEngine;
- using UnityEngine.UI;
- using UnityEngine.EventSystems;
- using System.Collections;
- // refer to http://gregandaduck.blogspot.com/2015/02/using-unitys-c-message-system-unity-46.html
- public interface IMyMouseOver : IEventSystemHandler {
- void mouseOver(string str);
- void mouseLeaving();
- }
- public class MyDisplayText : MonoBehaviour, IMyMouseOver {
- public Text text;
- public void mouseOver(string str) {
- if (!text.enabled) {
- text.text = str;
- text.enabled = true;
- }
- }
- public void mouseLeaving() {
- if (text.enabled) {
- text.enabled = false;
- }
- }
- }
消息发送方,实现如下:
- using UnityEngine;
- using UnityEngine.EventSystems;
- using System.Collections;
- using System.Collections.Generic;
- public class MyMouseOver : MonoBehaviour {
- GameObject prevObject;
- void Update () {
- GameObject target = getMouseOver ();
- if (target) {
- prevObject = target;
- ExecuteEvents.Execute<IMyMouseOver> (target, null, (handle, data) => {
- handle.mouseOver ("Mouse Over Active, frame: " + Time.frameCount);
- });
- } else {
- if(prevObject) {
- ExecuteEvents.Execute<IMyMouseOver>(prevObject, null, (handle, data) =>{
- handle.mouseLeaving();
- });
- prevObject = null;
- }
- }
- }
- private GameObject getMouseOver() {
- List<RaycastResult> hits = new List<RaycastResult>();
- EventSystem.current.RaycastAll (new PointerEventData (EventSystem.current) {
- position = Input.mousePosition
- }, hits);
- foreach (RaycastResult rr in hits) {
- GameObject go = rr.gameObject;
- if(go)
- return go;
- }
- return null;
- }
- }
12. 在C#中模拟Java中的匿名类写法(有点Javascript的味道):
- public class HpBarHandler { // 当然这里用struct会显得把delegate更加看作为数据
- public System.Action<float> changeHp;
- public System.Action hidde;
- public System.Action show;
- public System.Action destory;
- }
- public void registerHPBarEvent(HpBarHandler _hphandler) {
- hphandler = _hphandler;
- }
- fightUnit.registerHPBarEvent (new HpBarHandler () {
- changeHp = hp => {
- size.x = 200 * hp;
- if(rectTrans) {
- rectTrans.sizeDelta = size;
- if(hp<=0) {
- GameObject.Destroy (gameObject);
- }
- }
- },
- hidde = delegate{
- gameObject.SetActive(false);
- },
- show = delegate {
- gameObject.SetActive(true);
- },
- destory = delegate {
- GameObject.Destroy (gameObject);
- }
- });
13. 工作中总是遇到初始化某个单位时,依赖其他的单位还未初始化,导致了NullReferenceException。这个是因为所有的初始化都写在了Start方法中,这样由于代码初始化的前后顺序,导致了上面的问题。解决方案就是把初始化分阶段进行。能够导致NullReferenceException的,比如GetCompent,Find等操作,写在Awake或OnEnable方法中等。逻辑初始化写在Start中等。下面是Script Lifecycle的示意图,官方文档为:http://docs.unity3d.com/Manual/ExecutionOrder.html
14. 浮点数格式化
- //List<Vector3> uvList = ...;
- Debug.Log (string.Format("frame: {0:0.00}, uvs: {1}, {2}, {3}, {4}",
- 0.125f,
- uvList[0].ToString("0.000"),
- uvList[1].ToString("0.000"),
- uvList[2].ToString("0.000"),
- uvList[3].ToString("0.000")
- ));