unity3d编辑器和插件制作(二)

2015年02月01日 11:07 0 点赞 0 评论 更新于 2025-11-21 15:55

一、VKButton类实现

以下是VKButton类的代码,该类继承自VKView,用于实现按钮相关功能:

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插件可从官网下载,各大论坛也有相关下载资源。

二、动画相关类实现

1. VkAniDuration枚举

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
};

2. VKAnimator类

using UnityEngine;
using System.Collections;
using Holoville.HOTween;

public class VKAnimator {
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;
}

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;
}
}

3. VKAniComplete类

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编辑器实现

1. 获取脚本公共方法

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;
}
}

2. VKButtonEditor类

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];
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) {
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();
}
}

四、VKLabel类实现

1. VKLabel类

using UnityEngine;
using System.Collections;

[RequireComponent(typeof(MeshRenderer))]
[ExecuteInEditMode]
public class VKLabel : MonoBehaviour {
public Font labelFont;
TextMesh labelMesh;
Material labelMat;

void Start() {
labelMesh = GetComponent<TextMesh>();
if (labelMesh == null) {
labelMesh = gameObject.AddComponent<TextMesh>();
}
labelFont = labelMesh.font;
if (labelMesh.text.Length == 0) {
labelMesh.text = "VKLabel";
}
labelMat = new Material(Shader.Find("VK/VkLabelShader"));
labelMat.mainTexture = labelMesh.font.material.mainTexture;
GetComponent<MeshRenderer>().material = labelMat;
updateTextMesh();
}

public void updateTextMesh() {
if (labelMesh != null) {
labelMesh.font = labelFont;
}
if (labelMat != null && labelFont != null) {
if (labelFont.material != null) {
labelMat.mainTexture = labelFont.material.mainTexture;
}
labelMat.color = labelMesh.color;
GetComponent<MeshRenderer>().material = labelMat;
}
}
}

2. VkLabelShader

Shader "VK/VkLabelShader" {
Properties {
_MainTex ("Font Texture", 2D) = "white" {}
_Color ("Text Color", Color) = (1,1,1,1)
}
SubShader {
Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
Lighting Off Cull Off ZWrite Off Fog { Mode Off }
Blend SrcAlpha OneMinusSrcAlpha
Pass {
Color [_Color]
SetTexture [_MainTex] {
combine primary, texture * primary
}
}
}
}

下面我们要实现一个简单的label编辑器类,使label的监视面板更美观。这里暂不详细实现,因为该编辑器未添加任何修饰内容。需要注意的是,不要使用[RequireComponent(typeof(TextMesh))]添加组件,否则TextMesh将没有任何字体。应使用Unity自带的方法添加组件,这样它会自动添加Unity内置的字体。

作者信息

feifeila

feifeila

共发布了 3994 篇文章