首页 > 代码库 > unity 编辑器和插件制作(四.2)
unity 编辑器和插件制作(四.2)
上次 我们讲述的是编辑器制作,怎么把图片加载到场景中,今天 我们就来讲述下,怎么 制作UIButton以及UIimage的互换。
废话不多说。进入正题。
首先我们要了解 unity的机制,button属性必须有的属性等。
首先 我们先说下 unity的机制:
unity中检测点击事件,使用NGUI的可能知道,NGUI使用的就是SendMessage的方式来进行事件的传递。没错,这也是 unity最为简便的方式,
(要注意一个问题哦,这个方式 如果 你要使用 大于 万次循环的话 会有延迟的哦,一般也不会同时发送万条事件的)。
我们知道了 事件的传送的方式,那么我们就开始制作这个规则,首先 要使用SendMessage的话我们要拿到gameobject的对象才能使用。
所以我们要想办法拿到点击的那个物体。怎么坐那,原理其实很简单,就是射线。我们都知道,unity的射线是用来探测使用的 正好,我们所有可以看到的物体都是存在camera下面,那么我们就可以使用,从camera上发射射线,来达到检测物体的作用,物体要有碰撞体哦。
先贴部分代码等这个章节完了我会贴完整的代码
Ray cameraRay; RaycastHit hit; Vector3 touchPos,pressOffSet; public static GameObject touchObj = null; public static VKCamera shareVkCamera;
void Update () { #if UNITY_EDITOR if(Input.GetMouseButtonDown(0)){ onPressDown(Input.mousePosition); }else if(Input.GetMouseButtonUp(0)){ onPressUp(Input.mousePosition); }else if(Input.GetMouseButton(0)){ onDrag(Input.mousePosition); } #endif #if UNITY_IPHONE || UNITY_ANDROID Touch touch; if(Input.touchCount==1){ touch = Input.GetTouch (0); switch(touch.phase){ case TouchPhase.Began: onPressDown(touch.position); break; case TouchPhase.Moved: onPressUp(touch.position); break; case TouchPhase.Ended: case TouchPhase.Canceled: onDrag(touch.position); break; } } #else if(Input.GetMouseButtonDown(0)){ onPressDown(Input.mousePosition); }else if(Input.GetMouseButtonUp(0)){ onPressUp(Input.mousePosition); }else if(Input.GetMouseButton(0)){ onDrag(Input.mousePosition); } #endif }
public void onPressDown(Vector2 vec){ touchPos = vec; for(int i=0 ; i<Camera.allCameras.Length;i++){ cameraRay = Camera.allCameras[i].ScreenPointToRay(touchPos); if(Physics.Raycast(cameraRay,out hit,9999,Camera.allCameras[i].cullingMask) && touchObj == null){ touchObj = hit.transform.gameObject; if(touchObj!=null && touchObj.GetComponent<VKButton>()){ touchPos = Camera.allCameras[i].ScreenToWorldPoint(touchPos); pressOffSet =touchObj.transform.position-touchPos; VKButton button = touchObj.GetComponent<VKButton>(); if(!iSNull(button.pressEventName) && button.eventObj!=null) button.eventObj.SendMessage(button.pressEventName,button); if(button.pressButtonTex!=null){ button.renderer.sharedMaterial.mainTexture = button.pressButtonTex; } if(button.isDrag && !iSNull(button.dragStartEventName)){ button.eventObj.SendMessage(button.dragStartEventName,vec); } if(button.isAni){ button.SendMessage("onPressAni"); } } } } }
public void onPressUp(Vector2 vec){ if(touchObj!=null){ VKButton button = touchObj.GetComponent<VKButton>(); if(button!=null){ if(button.buttonTex!=null){ touchObj.renderer.sharedMaterial.mainTexture = touchObj.GetComponent<VKButton>().buttonTex; } if(!iSNull(button.clickEventName) && button.eventObj!=null){ button.eventObj.SendMessage(button.clickEventName,button); } if(button.isDrag && !iSNull(button.dragEndEventName)){ button.SendMessage(button.dragEndEventName,vec); } if(button.isAni){ button.SendMessage("onClickAni"); } } touchObj = null; } }
public void onDrag(Vector2 vec){ if(touchObj!=null){ VKButton button = touchObj.GetComponent<VKButton>(); if(button!=null && button.isDrag){ for(int i= 0;i<Camera.allCameras.Length;i++){ Vector2 worldVec = Camera.allCameras[i].ScreenToWorldPoint(vec); touchObj.transform.position = new Vector3(worldVec.x+pressOffSet.x,worldVec.y+pressOffSet.y,touchObj.transform.position.z); if(!iSNull(button.dragEventName)) button.eventObj.SendMessage(button.dragEventName,worldVec); } } } }
bool iSNull(string eventName){ bool buttonIsNull = false; if(eventName== null || eventName.Equals("null")){ buttonIsNull =true; } return buttonIsNull; }
这些是camera的部分,还有一点这个 我们没有贴我的适配方案 摄像机的适配方案,这里统配是1420*800的设计方案,因为这里我估计还要改下,发现这个摄像机适配方案,超出了unity的物理引擎的范围。不建议,不过可以参考。
public void initVKCamere(){ gameObject.name = "VKCamere"; this.camera.orthographic = true; this.camera.backgroundColor = Color.black; this.camera.nearClipPlane = 0; this.camera.farClipPlane = 9999; this.camera.orthographic =true; this.camera.orthographicSize = getCameraSize (); this.transform.position = new Vector3(0,0,-1000); this.transform.rotation = Quaternion.Euler(Vector3.zero); this.transform.localScale = Vector3.one; Application.targetFrameRate=60; if(GetComponent<AudioListener>()){ //DestroyImmediate(GetComponent<AudioListener>()); } } int getCameraSize(){ int size = 384; bool isLandscape=(Camera.main.pixelWidth>Camera.main.pixelHeight); float rad = Camera.main.pixelWidth/Camera.main.pixelHeight; bool isIPad= (Mathf.Abs(rad-1.3333f)<0.001f) || (Mathf.Abs(rad-0.75f)<0.001f); if(isIPad){ if(isLandscape){ size=400; }else{ size=533; } }else{ if(isLandscape){ size=400; }else{ //iPhone 5 if(Camera.main.pixelHeight/Camera.main.pixelWidth>1.6){ size=710; }else{ size=600; } } } return size; }
camera的编辑器类
using UnityEditor; using UnityEngine; using System.Collections; [CustomEditor(typeof(VKCamera))] public class VKCameraEditor : Editor { public override void OnInspectorGUI (){ base.OnInspectorGUI(); VKCamera vkCamere = (VKCamera)target; if(GUILayout.Button("ReSetCamera")){ vkCamere.initVKCamere(); } EditorUtility.SetDirty(vkCamere); EditorUtility.UnloadUnusedAssets(); } }
好下面我们来讲述下,button的一些东西,其实就很简单了。只是在编辑器方面可能会有些麻烦。
说白了 就是button就来处理 摄像机发来的东西。虽然很简单的一句话,但我们写得东西还是有很多的。
依然,button还是继承前面的view
using UnityEngine; using System.Collections; using Holoville.HOTween; //[RequireComponent(typeof(BoxCollider))] public class VKButton : VKView { [HideInInspector] public Material buttonDefultMat; [HideInInspector] public Mesh buttonDefultMesh; [HideInInspector] public Texture buttonTex,pressButtonTex; [HideInInspector] public string pressEventName = null; [HideInInspector] public string clickEventName = null; [HideInInspector] public string dragStartEventName = null; [HideInInspector] public string dragEventName = null; [HideInInspector] public string dragEndEventName = null; [HideInInspector] public GameObject eventObj = null; [HideInInspector] public string eventScript = null; [HideInInspector] public bool isDrag = false; [HideInInspector] public float scale = 1; [HideInInspector] public string info= null; [HideInInspector] public string[] animatorType = new string[]{"null","bigger","smaller","moveLeft","moveRight"}; [HideInInspector] public int currentAnimator = 0; [HideInInspector] public bool isAni = false; void Start () { buttonDefultMat = new Material(Shader.Find("VK/VKButtonShader")); gameObject.GetComponent<MeshRenderer> ().material = buttonDefultMat; buttonDefultMesh = new Mesh (); gameObject.GetComponent<MeshFilter> ().mesh = buttonDefultMesh; if(GetComponent<BoxCollider>()== null) gameObject.AddComponent<BoxCollider>(); updateButton(); } public float setScale{ set{ scale = value; }get{ return scale; } } public void updateButton(){ if(buttonTex!=null){ if(buttonDefultMat!=null) buttonDefultMat.mainTexture = buttonTex; if(buttonDefultMesh!=null) buttonDefultMesh.vertices = InitBase.initVertice(buttonTex.width *scale,buttonTex.height*scale,ancPointx,ancPointy); if(this!=null&&gameObject.GetComponent<BoxCollider>()!=null){ gameObject.GetComponent<BoxCollider>().size = new Vector3(buttonTex.width*scale,buttonTex.height*scale,0); } }else{ if(buttonDefultMat!=null) buttonDefultMat.mainTexture = null; if(buttonDefultMesh!=null) buttonDefultMesh.vertices = InitBase.initVertice(width*scale,height*scale,ancPointx,ancPointy); gameObject.GetComponent<BoxCollider>().size = new Vector3(width,height,0); } if(buttonDefultMesh!= null){ buttonDefultMesh.triangles = InitBase.initTri (); buttonDefultMesh.normals = InitBase.initNormal(); buttonDefultMesh.uv = InitBase.initUV(); } } Vector3 pressScale= Vector3.zero; Vector3 pressPos = Vector3.zero; Tweener tw = null; void onPressAni(){ if(tw!=null && !tw.isComplete){ return; } pressScale = transform.localScale; pressPos = transform.position; switch(currentAnimator){ case 1: tw = VKAnimator.scaleBy(gameObject,0.3f,Vector3.one*0.2f,VkAniDuration.AnimationCurve,null); break; case 2: tw = VKAnimator.scaleBy(gameObject,0.3f,Vector3.one*-0.2f,VkAniDuration.AnimationCurve,null); break; case 3: tw = VKAnimator.moveBy(gameObject,0.3f,new Vector3(-10f,0,0),false,VkAniDuration.AnimationCurve,null); break; case 4: tw = VKAnimator.moveBy(gameObject,0.3f,new Vector3(10f,0,0),false,VkAniDuration.AnimationCurve,null); break; } } void onClickAni(){ if(currentAnimator == 1 || currentAnimator==2){ VKAnimator.scaleTo(gameObject,0.3f,pressScale,VkAniDuration.AnimationCurve,null); } else if(currentAnimator == 3 || currentAnimator==4){ VKAnimator.moveTo(gameObject,0.3f,pressPos,false,VkAniDuration.AnimationCurve,null); } } public void switchImageView(){ VKImageView imgView = gameObject.AddComponent<VKImageView> (); imgView.imgViewTex = buttonTex; imgView.highLightedTex = pressButtonTex; imgView.ancPointx = ancPointx; imgView.ancPointy = ancPointy; imgView.scale = scale; imgView.updateImageView (); if(GetComponent<BoxCollider>()){ DestroyImmediate(GetComponent<BoxCollider>()); } DestroyImmediate (GetComponent<VKButton>()); } }
这里有个 动画效果 我是自己使用的hotween整合的一些东西,如果你想用自己的可以自己去做。hotween插件 我就不用公布了,可以去官网进行下载,各大论坛也有下载资源。
using UnityEngine; using System.Collections; using Holoville.HOTween; public enum VkAniDuration{ AnimationCurve = EaseType.AnimationCurve, EaseInBack=EaseType.EaseInBack, EaseInBounce=EaseType.EaseInBounce, EaseInCirc=EaseType.EaseInCirc, EaseInCubic=EaseType.EaseInCubic, EaseInElastic=EaseType.EaseInElastic, EaseInExpo=EaseType.EaseInExpo, EaseInOutBack=EaseType.EaseInOutBack, EaseInOutBounce=EaseType.EaseInOutBounce, EaseInOutCirc=EaseType.EaseInOutCirc, EaseInOutCubic=EaseType.EaseInOutCubic, EaseInOutElastic=EaseType.EaseInOutElastic, EaseInOutExpo=EaseType.EaseInOutExpo, EaseInOutQuad=EaseType.EaseInOutQuad, EaseInOutQuart=EaseType.EaseInOutQuart, EaseInOutQuint=EaseType.EaseInOutQuint, EaseInOutSine=EaseType.EaseInOutSine, EaseInQuad=EaseType.EaseInQuad, EaseInQuart=EaseType.EaseInQuart, EaseInQuint=EaseType.EaseInQuint, EaseInSine=EaseType.EaseInSine, EaseOutBack=EaseType.EaseOutBack, EaseOutBounce=EaseType.EaseOutBounce, EaseOutCirc=EaseType.EaseOutCirc, EaseOutCubic=EaseType.EaseOutCubic, EaseOutElastic=EaseType.EaseOutElastic, EaseOutExpo=EaseType.EaseOutExpo, EaseOutQuad=EaseType.EaseOutQuad, EaseOutQuart=EaseType.EaseOutQuart, EaseOutQuint=EaseType.EaseOutQuint, EaseOutSine=EaseType.EaseOutSine, Linear=EaseType.Linear }; public class VKAnimator { // public static Tweener moveTo(GameObject obj,float time,Vector3 target,bool isLocal,VkAniDuration vkDurType = VkAniDuration.AnimationCurve){ // Tweener tw = null; // if(isLocal) // tw = startVkAnimote(obj,time,"localPosition",target,vkDurType,null); // // else // tw = startVkAnimote(obj,time,"position",target,vkDurType,null); // return tw; // } public static Tweener moveTo(GameObject obj,float time,Vector3 target,bool isLocal,VkAniDuration vkDurType = VkAniDuration.AnimationCurve,VKAniComplete completeObj = null){ Tweener tw = null; if(isLocal) tw =startVkAnimote(obj,time,"localPosition",target,vkDurType,completeObj); else tw = startVkAnimote(obj,time,"position",target,vkDurType,completeObj); return tw; } public static Tweener moveBy(GameObject obj,float time,Vector3 offset,bool isLocal,VkAniDuration vkDurType = VkAniDuration.AnimationCurve,VKAniComplete completeObj = null){ Tweener tw = null; if(isLocal){ Vector3 tLocalPos = obj.transform.localPosition + offset; tw = startVkAnimote(obj,time,"localPosition",tLocalPos,vkDurType,completeObj); }else{ Vector3 tPos = obj.transform.position + offset; tw = startVkAnimote(obj,time,"position",tPos,vkDurType,completeObj); } return tw; } public static Tweener scaleTo(GameObject obj,float time,Vector3 scale,VkAniDuration vkDurType = VkAniDuration.AnimationCurve,VKAniComplete completeObj = null){ Tweener tw = null; tw = startVkAnimote(obj,time,"localScale",scale,vkDurType,completeObj); return tw; } public static Tweener scaleBy(GameObject obj,float time,Vector3 offsetScale,VkAniDuration vkDurType = VkAniDuration.AnimationCurve,VKAniComplete completeObj = null){ Tweener tw = null; Vector3 targetScale = obj.transform.localScale+offsetScale; tw = startVkAnimote(obj,time,"localScale",targetScale,vkDurType,completeObj); return tw; } public static Tweener routeTo(GameObject obj,float time,Vector3 routeEulerTarget,VkAniDuration vkDurType = VkAniDuration.AnimationCurve,VKAniComplete completeObj = null){ Tweener tw = null; tw = startVkAnimote(obj,time,"localEulerAngles",routeEulerTarget,vkDurType,completeObj); return tw; } public static Tweener routeBy(GameObject obj,float time,Vector3 routeEulerOffset,VkAniDuration vkDurType = VkAniDuration.AnimationCurve,VKAniComplete completeObj = null){ Tweener tw = null; Vector3 target = obj.transform.localEulerAngles+ routeEulerOffset; tw = startVkAnimote(obj,time,"localEulerAngles",target,vkDurType,completeObj); return tw; } //localEulerAngles private static Tweener startVkAnimote(GameObject obj,float time,string key,object target,VkAniDuration vkDurType = VkAniDuration.AnimationCurve,VKAniComplete completeObj = null){ Tweener tw = null; TweenParms twp = new TweenParms(); twp.Prop(key,target); twp.Ease((EaseType)vkDurType); if(completeObj!=null){ twp.OnComplete(completeObj.sendTargetObj,completeObj.methodName,completeObj.sendobj,SendMessageOptions.DontRequireReceiver); } tw = HOTween.To(obj.transform,time,twp); return tw; } }
using UnityEngine; using System.Collections; public class VKAniComplete{ public GameObject sendTargetObj = null; public string methodName = null; public object sendobj = null; public VKAniComplete(GameObject sendTargetObj,string methodName,object sendobj){ this.sendTargetObj = sendTargetObj; this.methodName = methodName; this.sendobj = sendobj; } }
下面就是button的编辑器方面了。ok,这里可能有点麻烦。不过还是可以解决的。
首先我们要获取脚本里面的方法怎么获取那。根据c#的MSDN的描述我们可以看到。就是以下方法,这就是 为什么 NGUI 只能找到public属性的方法。
using UnityEngine; using System.Collections; using System.Reflection; public class GetPublic : MonoBehaviour { static public MethodInfo[] GetObjectMethods(string selectedObjClass){ if(selectedObjClass==null)return null; MethodInfo[] methodInfos=null; if(System.Type.GetType(selectedObjClass)==null){ return methodInfos; } methodInfos = System.Type.GetType(selectedObjClass).GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); return methodInfos; } }
这里就是button编辑器的一些属性的传递,和界面的修改哈。
using UnityEngine; using System.Collections; using UnityEditor; using System.Reflection; [CustomEditor(typeof(VKButton))] public class VKButtonEditor : Editor { public override void OnInspectorGUI () { int pressEventNum= 0; int selectScriptNum = 0; int clickEventNum = 0; int dragStartEveNum = 0; int dragEveNum = 0; int dragEndEveNum = 0; VKButton button = (VKButton)target; button.buttonTex = EditorGUILayout.ObjectField ("Texture",button.buttonTex,typeof(Texture),true)as Texture; button.pressButtonTex = EditorGUILayout.ObjectField ("PressButtonTex",button.pressButtonTex,typeof(Texture),true)as Texture; button.eventObj = EditorGUILayout.ObjectField("eventObj",button.eventObj,typeof(GameObject),true) as GameObject; button.info = EditorGUILayout.TextField("info",button.info); button.ancPointx = EditorGUILayout.Slider("AnchorX",button.ancPointx,0.0f,1.0f); button.ancPointy = EditorGUILayout.Slider("AnchorY",button.ancPointy,0.0f,1.0f); if(button.buttonTex == null){ button.width=EditorGUILayout.IntField("Width",button.width); button.height=EditorGUILayout.IntField("Height",button.height); } GUILayout.BeginHorizontal(); if(GUILayout.Button("2X")){ button.setScale = 0.5f; } if(GUILayout.Button("1X")){ button.setScale = 1f; } if(GUILayout.Button("1.5X")){ button.setScale = 0.75f; } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); if(GUILayout.Button("ChangeName")){ if(button.buttonTex!=null){ button.name = button.buttonTex.name; } } if(GUILayout.Button("Switch ImageView")){ button.switchImageView(); } GUILayout.EndHorizontal(); if(button.eventObj!=null){ MonoBehaviour[] monoScriptArry =new MonoBehaviour[button.eventObj.GetComponents<MonoBehaviour>().Length+1];// button.eventObj.GetComponents<MonoBehaviour>(); for(int i=0;i<monoScriptArry.Length;i++){ if(i<monoScriptArry.Length-1) monoScriptArry [i] = button.eventObj.GetComponents<MonoBehaviour>()[i]; if(i == monoScriptArry.Length-1){ monoScriptArry [i] = null; } } if(monoScriptArry !=null&& monoScriptArry.Length>0){ string [] scriptName = new string[monoScriptArry.Length]; for(int i=0;i<scriptName.Length;i++){ if(monoScriptArry[i]!=null){ scriptName[i] = monoScriptArry[i].GetType().ToString(); if(scriptName[i].Equals("VKCamera")){ scriptName[i] = "null"; } }else{ scriptName[i] = "null"; } if(scriptName[i].Equals(button.eventScript)){ selectScriptNum = i; } } selectScriptNum = EditorGUILayout.Popup("EventScript",selectScriptNum,scriptName); button.eventScript = scriptName[selectScriptNum]; MethodInfo[] publicMethodArry; if(button.eventScript == null || button.eventScript.Equals("null")){ publicMethodArry = new MethodInfo[1]; }else{ publicMethodArry = new MethodInfo[GetPublic.GetObjectMethods(button.eventScript).Length+1]; } for(int i = 0;i<publicMethodArry.Length;i++){ if(i<publicMethodArry.Length-1){ publicMethodArry[i] =GetPublic.GetObjectMethods(button.eventScript)[i]; }else{ publicMethodArry[i] = null; } } if(publicMethodArry!=null && publicMethodArry.Length>0){ string[] methodArry = new string[publicMethodArry.Length]; for(int i=0;i<methodArry.Length;i++){ if(publicMethodArry[i]!=null){ methodArry[i] = publicMethodArry[i].Name; }else{ methodArry[i] ="null"; } if(button.pressEventName !=null && button.pressEventName.Equals(methodArry[i])){ pressEventNum = i; } if(button.clickEventName != null && button.clickEventName.Equals(methodArry[i])){ clickEventNum = i; } if(button.isDrag){ if(button.dragStartEventName != null && button.dragStartEventName.Equals(methodArry[i])){ dragStartEveNum = i; } if(button.dragEventName != null && button.dragEventName.Equals(methodArry[i])){ dragEveNum = i; } if(button.dragEndEventName != null && button.dragEndEventName.Equals(methodArry[i])){ dragEndEveNum = i; } } } pressEventNum = EditorGUILayout.Popup("PressEvent",pressEventNum,methodArry); clickEventNum = EditorGUILayout.Popup("ClickEvent",clickEventNum,methodArry); button.pressEventName = methodArry[pressEventNum]; button.clickEventName = methodArry[clickEventNum]; button.isAni = EditorGUILayout.Toggle ("ISAimator",button.isAni); if(button.isAni){ button.currentAnimator = EditorGUILayout.Popup("ButtonAnimator",button.currentAnimator,button.animatorType); } button.isDrag = EditorGUILayout.Toggle ("ISDrag",button.isDrag); if(button.isDrag){ // EditorGUILayout.LabelField("---------------------------------------------"); dragStartEveNum = EditorGUILayout.Popup("DragStartEvent",dragStartEveNum,methodArry); dragEveNum = EditorGUILayout.Popup("DragEvent",dragEveNum,methodArry); dragEndEveNum = EditorGUILayout.Popup("DragEndEvent",dragEndEveNum,methodArry); button.dragStartEventName = methodArry[dragStartEveNum]; button.dragEventName = methodArry[dragEveNum]; button.dragEndEventName =methodArry[dragEndEveNum]; } }else{ pressEventNum = EditorGUILayout.Popup("PressEvent",pressEventNum,new string[]{"null"}); clickEventNum = EditorGUILayout.Popup("ClickEvent",clickEventNum,new string[]{"null"}); } } }else{ button.isAni =false; button.isDrag =false; } button.updateButton (); if(button!=null){ EditorUtility.SetDirty(button); } EditorUtility.UnloadUnusedAssets(); } }我这里扩展了一些功能,像移动啊,什么的。。其实还可以加一些功能的 ,这里只是学习。有兴趣的可以自己加些东西。