a做片手机免费网站,设计网站页面出现问题,泉山网站开发,做设计什么兼职网站建设推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址我的个人博客 大家好#xff0c;我是佛系工程师☆恬静的小魔龙☆#xff0c;不定时更新Unity开发技巧#xff0c;觉得有用记得一键三连哦。
一、前言
在开发中#xff0c;常常会遇到频繁复制粘贴物体的坐标、旋转… 推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址我的个人博客 大家好我是佛系工程师☆恬静的小魔龙☆不定时更新Unity开发技巧觉得有用记得一键三连哦。
一、前言
在开发中常常会遇到频繁复制粘贴物体的坐标、旋转、缩放的操作。
使用Unity自带的组件复制粘贴比较麻烦 复制 粘贴 还有一些需要复制位置、旋转、缩放的值到到代码中如果一个一个复制粘贴非常麻烦还要一些需要复制添加自定义文本也很不方便。
所以就开发了一个小工具来提升开发效率。
二、正文
2-1、实现快速复制/粘贴位置/旋转/缩放功能
效果图 在Editor文件夹中新建脚本随便命名然后编辑代码
using UnityEngine;
using UnityEditor;
using System.Text;
using static UnityEditor.IMGUI.Controls.PrimitiveBoundsHandle;
using static UnityEngine.UI.Image;[CanEditMultipleObjects]
[CustomEditor(typeof(Transform), true)]
public class TransformEditor : Editor
{static public TransformEditor instance;//当前的本地坐标SerializedProperty mPos;//当前的本地旋转SerializedProperty mRot;//当前的本地缩放SerializedProperty mScale;void OnEnable(){instance this;if (this){try{var so serializedObject;mPos so.FindProperty(m_LocalPosition);mRot so.FindProperty(m_LocalRotation);mScale so.FindProperty(m_LocalScale);}catch { }}}void OnDestroy() { instance null; }/// summary/// Draw the inspector widget.绘制inspector小部件。/// /summarypublic override void OnInspectorGUI(){//设置label的宽度EditorGUIUtility.labelWidth 15f;serializedObject.Update();DrawPosition();DrawRotation();DrawScale();DrawCopyAndPaste();serializedObject.ApplyModifiedProperties();}void DrawCopyAndPaste(){GUILayout.BeginHorizontal();bool reset GUILayout.Button(Copy);bool reset2 GUILayout.Button(Paste);GUILayout.EndHorizontal();if (reset){//把数值打印出来var select Selection.activeGameObject;if (select null)return;//Debug.Log(select.name( mPos.vector3Value.x.ToString() , mPos.vector3Value.y.ToString() , mPos.vector3Value.z.ToString() ));//Debug.Log(select.name mRot.quaternionValue);//Debug.Log(select.name ( mScale.vector3Value.x.ToString() , mScale.vector3Value.y.ToString() , mScale.vector3Value.z.ToString() ));StringBuilder s new StringBuilder();s.Append(TransformInspector_ ( mPos.vector3Value.x.ToString() , mPos.vector3Value.y.ToString() , mPos.vector3Value.z.ToString() ) _);s.Append(mRot.quaternionValue _);s.Append(( mScale.vector3Value.x.ToString() , mScale.vector3Value.y.ToString() , mScale.vector3Value.z.ToString() ));//添加到剪贴板UnityEngine.GUIUtility.systemCopyBuffer s.ToString();}if (reset2){//把数值打印出来//Debug.Log(UnityEngine.GUIUtility.systemCopyBuffer);string s UnityEngine.GUIUtility.systemCopyBuffer;string[] sArr s.Split(_);if (sArr[0] ! TransformInspector){Debug.LogError(未复制Transform组件内容Transform component content not copied!);return;}//Debug.Log(Pos: sArr[1]);//Debug.Log(Rot: sArr[2]);//Debug.Log(Scale: sArr[3]);try{mPos.vector3Value ParseV3(sArr[1]);mRot.quaternionValue new Quaternion() { x ParseV4(sArr[2]).x, y ParseV4(sArr[2]).y, z ParseV4(sArr[2]).z, w ParseV4(sArr[2]).w };mScale.vector3Value ParseV3(sArr[3]);}catch (System.Exception ex){Debug.LogError(ex);return;}}}/// summary/// String To Vector3/// /summary/// param namestrVector3/param/// returns/returnsVector3 ParseV3(string strVector3){strVector3 strVector3.Replace((, ).Replace(), );string[] s strVector3.Split(,);return new Vector3(float.Parse(s[0]), float.Parse(s[1]), float.Parse(s[2]));}/// summary/// String To Vector4/// /summary/// param namestrVector4/param/// returns/returnsVector4 ParseV4(string strVector4){strVector4 strVector4.Replace((, ).Replace(), );string[] s strVector4.Split(,);return new Vector4(float.Parse(s[0]), float.Parse(s[1]), float.Parse(s[2]), float.Parse(s[3]));}#region Position 位置void DrawPosition(){GUILayout.BeginHorizontal();EditorGUILayout.PropertyField(mPos.FindPropertyRelative(x));EditorGUILayout.PropertyField(mPos.FindPropertyRelative(y));EditorGUILayout.PropertyField(mPos.FindPropertyRelative(z));bool reset GUILayout.Button(P, GUILayout.Width(20f));GUILayout.EndHorizontal();if (reset) mPos.vector3Value Vector3.zero;}#endregion#region Scale 缩放void DrawScale(){GUILayout.BeginHorizontal();{EditorGUILayout.PropertyField(mScale.FindPropertyRelative(x));EditorGUILayout.PropertyField(mScale.FindPropertyRelative(y));EditorGUILayout.PropertyField(mScale.FindPropertyRelative(z));bool reset GUILayout.Button(S, GUILayout.Width(20f));if (reset) mScale.vector3Value Vector3.one;}GUILayout.EndHorizontal();}#endregion#region Rotation is ugly as hell... since there is no native support for quaternion property drawing 旋转是丑陋的地狱。。。因为四元数属性绘图没有本地支持enum Axes : int{None 0,X 1,Y 2,Z 4,All 7,}Axes CheckDifference(Transform t, Vector3 original){Vector3 next t.localEulerAngles;Axes axes Axes.None;if (Differs(next.x, original.x)) axes | Axes.X;if (Differs(next.y, original.y)) axes | Axes.Y;if (Differs(next.z, original.z)) axes | Axes.Z;return axes;}Axes CheckDifference(SerializedProperty property){Axes axes Axes.None;if (property.hasMultipleDifferentValues){Vector3 original property.quaternionValue.eulerAngles;foreach (Object obj in serializedObject.targetObjects){axes | CheckDifference(obj as Transform, original);if (axes Axes.All) break;}}return axes;}/// summary/// Draw an editable float field. 绘制可编辑的浮动字段。/// /summary/// param namehiddenWhether to replace the value with a dash 是否将值替换为破折号/param/// param namegreyedOutWhether the value should be greyed out or not 值是否应灰显/paramstatic bool FloatField(string name, ref float value, bool hidden, GUILayoutOption opt){float newValue value;GUI.changed false;if (!hidden){newValue EditorGUILayout.FloatField(name, newValue, opt);}else{float.TryParse(EditorGUILayout.TextField(name, --, opt), out newValue);}if (GUI.changed Differs(newValue, value)){value newValue;return true;}return false;}/// summary/// Because Mathf.Approximately is too sensitive.因为数学近似值太敏感了。/// /summarystatic bool Differs(float a, float b) { return Mathf.Abs(a - b) 0.0001f; }/// summary/// 注册Undo/// /summary/// param namename/param/// param nameobjects/paramstatic public void RegisterUndo(string name, params Object[] objects){if (objects ! null objects.Length 0){UnityEditor.Undo.RecordObjects(objects, name);foreach (Object obj in objects){if (obj null) continue;EditorUtility.SetDirty(obj);}}}/// summary/// 角度处理/// /summary/// param nameangle/param/// returns/returnsstatic public float WrapAngle(float angle){while (angle 180f) angle - 360f;while (angle -180f) angle 360f;return angle;}void DrawRotation(){GUILayout.BeginHorizontal();{Vector3 visible (serializedObject.targetObject as Transform).localEulerAngles;visible.x WrapAngle(visible.x);visible.y WrapAngle(visible.y);visible.z WrapAngle(visible.z);Axes changed CheckDifference(mRot);Axes altered Axes.None;GUILayoutOption opt GUILayout.MinWidth(30f);if (FloatField(X, ref visible.x, (changed Axes.X) ! 0, opt)) altered | Axes.X;if (FloatField(Y, ref visible.y, (changed Axes.Y) ! 0, opt)) altered | Axes.Y;if (FloatField(Z, ref visible.z, (changed Axes.Z) ! 0, opt)) altered | Axes.Z;bool reset GUILayout.Button(R, GUILayout.Width(20f));if (reset){mRot.quaternionValue Quaternion.identity;}else if (altered ! Axes.None){RegisterUndo(Change Rotation, serializedObject.targetObjects);foreach (Object obj in serializedObject.targetObjects){Transform t obj as Transform;Vector3 v t.localEulerAngles;if ((altered Axes.X) ! 0) v.x visible.x;if ((altered Axes.Y) ! 0) v.y visible.y;if ((altered Axes.Z) ! 0) v.z visible.z;t.localEulerAngles v;}}}GUILayout.EndHorizontal();}#endregion
}运行结果 这样就实现了基本的快速复制/粘贴位置/旋转/缩放功能。
接下来就实现单独的位置、旋转、缩放的复制和粘贴吧。
2-2、单独的位置、旋转、缩放的赋值粘贴功能
效果图 示例代码
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using UnityEditor;
using UnityEngine;public class ButtonHandler
{public string showDescription;public Action onClickCallBack;public ButtonHandler(string showDescription, Action onClickCallBack){this.showDescription showDescription;this.onClickCallBack onClickCallBack;}
}
[CanEditMultipleObjects]
[CustomEditor(typeof(Transform))]
public class TransformEditor2 : Editor
{static public Editor instance;private bool extensionBool;ButtonHandler[] buttonHandlerArray;//当前的本地坐标SerializedProperty mPos;//当前的本地旋转SerializedProperty mRot;//当前的本地缩放SerializedProperty mScale;private void OnEnable(){instance this;var editorType Assembly.GetAssembly(typeof(Editor)).GetTypes().FirstOrDefault(m m.Name TransformInspector);instance CreateEditor(targets, editorType);if (this){try{var so serializedObject;mPos so.FindProperty(m_LocalPosition);mRot so.FindProperty(m_LocalRotation);mScale so.FindProperty(m_LocalScale);}catch { }}extensionBool EditorPrefs.GetBool(extensionBool);buttonHandlerArray new ButtonHandler[9];buttonHandlerArray[0] new ButtonHandler(Position Copy, () {var select Selection.activeGameObject;if (select null)return;StringBuilder s new StringBuilder();// x,y,zs.Append(mPos.vector3Value.x.ToString() , mPos.vector3Value.y.ToString() , mPos.vector3Value.z.ToString());//添加到剪贴板UnityEngine.GUIUtility.systemCopyBuffer s.ToString();});buttonHandlerArray[1] new ButtonHandler(Position Paste, () {//把数值打印出来string s UnityEngine.GUIUtility.systemCopyBuffer;try{mPos.vector3Value ParseV3(s);}catch (System.Exception ex){Debug.LogError(ex);return;}});buttonHandlerArray[2] new ButtonHandler(Position Reset, () {mPos.vector3Value Vector3.zero;});buttonHandlerArray[3] new ButtonHandler(Rotation Copy, () {//把数值打印出来var select Selection.activeGameObject;if (select null)return;StringBuilder s new StringBuilder();s.Append(mRot.quaternionValue.eulerAngles.x , mRot.quaternionValue.eulerAngles.y , mRot.quaternionValue.eulerAngles.z);//添加到剪贴板UnityEngine.GUIUtility.systemCopyBuffer s.ToString();});buttonHandlerArray[4] new ButtonHandler(Rotation Paste, () {//把数值打印出来Debug.Log(UnityEngine.GUIUtility.systemCopyBuffer);string s UnityEngine.GUIUtility.systemCopyBuffer;try{mRot.quaternionValue Quaternion.Euler(ParseV3(s));}catch (System.Exception ex){Debug.LogError(ex);return;}});buttonHandlerArray[5] new ButtonHandler(Rotation Reset, () {mRot.quaternionValue Quaternion.identity;});buttonHandlerArray[6] new ButtonHandler(Scale Copy, () {//把数值打印出来var select Selection.activeGameObject;if (select null)return;StringBuilder s new StringBuilder();s.Append(mScale.vector3Value.x.ToString() , mScale.vector3Value.y.ToString() , mScale.vector3Value.z.ToString());//添加到剪贴板UnityEngine.GUIUtility.systemCopyBuffer s.ToString();});buttonHandlerArray[7] new ButtonHandler(Scale Paste, () {//把数值打印出来Debug.Log(UnityEngine.GUIUtility.systemCopyBuffer);string s UnityEngine.GUIUtility.systemCopyBuffer;try{mScale.vector3Value ParseV3(s);}catch (System.Exception ex){Debug.LogError(ex);return;}});buttonHandlerArray[8] new ButtonHandler(Scale Reset, () {mScale.vector3Value Vector3.one;});}private void OnDisable(){EditorPrefs.SetBool(extensionBool, extensionBool);}public override void OnInspectorGUI(){instance.OnInspectorGUI();GUI.color Color.cyan;extensionBool EditorGUILayout.Foldout(extensionBool, 拓展功能);if (extensionBool){EditorGUILayout.BeginHorizontal();for (int i 0; i buttonHandlerArray.Length; i){ButtonHandler temporaryButtonHandler buttonHandlerArray[i];if (GUILayout.Button(temporaryButtonHandler.showDescription, toolbarbutton))//, GUILayout.MaxWidth(150){temporaryButtonHandler.onClickCallBack();}GUILayout.Space(5);if ((i 1) % 3 0 || i 1 buttonHandlerArray.Length){EditorGUILayout.EndHorizontal();if (i 1 buttonHandlerArray.Length){GUILayout.Space(5);EditorGUILayout.BeginHorizontal();}}}}GUI.color Color.white;serializedObject.ApplyModifiedProperties();}Vector3 ParseV3(string strVector3){string[] s strVector3.Split(,);return new Vector3(float.Parse(s[0]), float.Parse(s[1]), float.Parse(s[2]));}
}演示 这样就实现了单独的位置/旋转/缩放复制/粘贴功能。
接下来就实现单独的位置/旋转/缩放复制/粘贴功能以及位置/旋转/缩放一起复制和粘贴功能。
以及自定义文本拼接的功能。
2-3、自定义文本拼接的功能
效果图
参考代码
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using UnityEditor;
using UnityEditor.AnimatedValues;
using UnityEngine;
using static UnityEditor.IMGUI.Controls.PrimitiveBoundsHandle;
using static UnityEngine.GraphicsBuffer;
using static UnityEngine.UI.Image;[CanEditMultipleObjects]
[CustomEditor(typeof(Transform))]
public class TransformEditor : Editor
{static public Editor instance;Transform m_Transform;private bool extensionBool;string axisName Local;bool isAxis false;bool isDefined false;string row1;string row2;string row3;string row4;//当前的本地坐标SerializedProperty mPos;//当前的本地旋转SerializedProperty mRot;//当前的本地缩放SerializedProperty mScale;private void OnEnable(){instance this;var editorType Assembly.GetAssembly(typeof(Editor)).GetTypes().FirstOrDefault(m m.Name TransformInspector);instance CreateEditor(targets, editorType);isAxis EditorPrefs.GetBool(isAxis);isDefined EditorPrefs.GetBool(isDefined);m_Transform this.target as Transform;if (this){try{var so serializedObject;mPos so.FindProperty(m_LocalPosition);mRot so.FindProperty(m_LocalRotation);mScale so.FindProperty(m_LocalScale);}catch { }}}private void OnDisable(){EditorPrefs.SetBool(extensionBool, extensionBool);EditorPrefs.SetBool(isDefined, isDefined);}public override void OnInspectorGUI(){instance.OnInspectorGUI();extensionBool EditorPrefs.GetBool(extensionBool);extensionBool EditorGUILayout.Foldout(extensionBool, 拓展功能);if (extensionBool){OnTopGUI();OnTransformGUI();OnPositionGUI();OnRotationGUI();OnScaleGUI();OnDefindGUI();}}void OnTopGUI(){EditorGUILayout.BeginHorizontal();GUILayout.Label(Name);if (GUILayout.Button(Local/Global)){isAxis !isAxis;EditorPrefs.SetBool(isAxis, isAxis);}axisName isAxis ? Local : Global;GUILayout.Label(当前坐标轴 axisName);EditorGUILayout.EndHorizontal();}void OnTransformGUI(){EditorGUILayout.BeginHorizontal();GUILayout.Label(Transform);if (GUILayout.Button(Copy)){var select Selection.activeGameObject;if (select null)return;StringBuilder s new StringBuilder();s.Append(Transform_);if (isAxis){s.Append(FormatVe3(m_Transform.localPosition) _);s.Append(FormatVe3(m_Transform.localRotation.eulerAngles) _);s.Append(FormatVe3(m_Transform.localScale));}else{s.Append(FormatVe3(m_Transform.position) _);s.Append(FormatVe3(m_Transform.rotation.eulerAngles) _);s.Append(FormatVe3(m_Transform.localScale));}UnityEngine.GUIUtility.systemCopyBuffer s.ToString();}if (GUILayout.Button(Paste)){if (isDefined){Debug.LogError(不支持自定义文本);UnityEngine.GUIUtility.systemCopyBuffer ;return;}string s UnityEngine.GUIUtility.systemCopyBuffer;string[] sArr s.Split(_);if (sArr[0] ! Transform || s ){Debug.LogError(未复制Transform组件内容);return;}try{m_Transform.position ParseV3(sArr[1]);m_Transform.rotation Quaternion.Euler(ParseV3(sArr[2]));m_Transform.localScale ParseV3(sArr[3]);}catch (System.Exception ex){Debug.LogError(ex);return;}}if (GUILayout.Button(Reset)){m_Transform.position Vector3.zero;m_Transform.rotation Quaternion.identity;m_Transform.localScale Vector3.one;}EditorGUILayout.EndHorizontal();}void OnPositionGUI(){EditorGUILayout.BeginHorizontal();GUILayout.Label(Position);if (GUILayout.Button(Copy)){var select Selection.activeGameObject;if (select null)return;StringBuilder s new StringBuilder();if (isAxis){s.Append(FormatVe3(m_Transform.localPosition));}else{s.Append(FormatVe3(m_Transform.position));}UnityEngine.GUIUtility.systemCopyBuffer s.ToString();Debug.Log(s);}if (GUILayout.Button(Paste)){if (isDefined){Debug.LogError(不支持自定义文本);UnityEngine.GUIUtility.systemCopyBuffer ;return;}string s UnityEngine.GUIUtility.systemCopyBuffer;if (s ){Debug.LogError(未复制Position内容);return;}try{m_Transform.position ParseV3(s);}catch (System.Exception ex){Debug.LogError(ex);return;}}if (GUILayout.Button(Reset)){m_Transform.position Vector3.zero;}EditorGUILayout.EndHorizontal();}void OnRotationGUI(){EditorGUILayout.BeginHorizontal();GUILayout.Label(Rotation);if (GUILayout.Button(Copy)){var select Selection.activeGameObject;if (select null)return;StringBuilder s new StringBuilder();if (isAxis){s.Append(FormatVe3(m_Transform.localRotation.eulerAngles));}else{s.Append(FormatVe3(m_Transform.rotation.eulerAngles));}UnityEngine.GUIUtility.systemCopyBuffer s.ToString();}if (GUILayout.Button(Paste)){if (isDefined){Debug.LogError(不支持自定义文本);UnityEngine.GUIUtility.systemCopyBuffer ;return;}string s UnityEngine.GUIUtility.systemCopyBuffer;if (s ){Debug.LogError(未复制Rotation内容);return;}try{m_Transform.rotation Quaternion.Euler(ParseV3(s));}catch (System.Exception ex){Debug.LogError(ex);return;}}if (GUILayout.Button(Reset)){m_Transform.rotation Quaternion.identity;}EditorGUILayout.EndHorizontal();}void OnScaleGUI(){EditorGUILayout.BeginHorizontal();GUILayout.Label(Scale);if (GUILayout.Button(Copy)){var select Selection.activeGameObject;if (select null)return;StringBuilder s new StringBuilder();s.Append(FormatVe3(m_Transform.localScale));UnityEngine.GUIUtility.systemCopyBuffer s.ToString();}if (GUILayout.Button(Paste)){if (isDefined){Debug.LogError(不支持自定义文本);UnityEngine.GUIUtility.systemCopyBuffer ;return;}string s UnityEngine.GUIUtility.systemCopyBuffer;if (s ){Debug.LogError(未复制Scale内容);return;}try{m_Transform.localScale ParseV3(s);}catch (System.Exception ex){Debug.LogError(ex);return;}}if (GUILayout.Button(Reset)){m_Transform.localScale Vector3.one;}EditorGUILayout.EndHorizontal();}void OnDefindGUI(){GUILayout.BeginVertical();isDefined GUILayout.Toggle(isDefined, 启用自定义文本拼接);if (isDefined){GUILayout.BeginHorizontal();row1 GUILayout.TextField(row1);GUILayout.Label(X);row2 GUILayout.TextField(row2);GUILayout.Label(Y);row3 GUILayout.TextField(row3);GUILayout.Label(Z);row4 GUILayout.TextField(row4);GUILayout.EndHorizontal();}GUILayout.EndVertical();}// x,y,zVector3 ParseV3(string strVector3){string[] s strVector3.Split(,);return new Vector3(float.Parse(s[0]), float.Parse(s[1]), float.Parse(s[2]));}// x,y,zstring FormatVe3(Vector3 ve3){string str;if (!isDefined){str ve3.x , ve3.y , ve3.z;}else{str row1 ve3.x row2 ve3.y row3 ve3.z row4;}return str;}
}三、后记
如果觉得本篇文章有用别忘了点个关注关注不迷路持续分享更多Unity干货文章。 你的点赞就是对博主的支持有问题记得留言
博主主页有联系方式。
博主还有跟多宝藏文章等待你的发掘哦
专栏方向简介Unity3D开发小游戏小游戏开发教程分享一些使用Unity3D引擎开发的小游戏分享一些制作小游戏的教程。Unity3D从入门到进阶入门从自学Unity中获取灵感总结从零开始学习Unity的路线有C#和Unity的知识。Unity3D之UGUIUGUIUnity的UI系统UGUI全解析从UGUI的基础控件开始讲起然后将UGUI的原理UGUI的使用全面教学。Unity3D之读取数据文件读取使用Unity3D读取txt文档、json文档、xml文档、csv文档、Excel文档。Unity3D之数据集合数据集合数组集合数组、List、字典、堆栈、链表等数据集合知识分享。Unity3D之VR/AR虚拟仿真开发虚拟仿真总结博主工作常见的虚拟仿真需求进行案例讲解。Unity3D之插件插件主要分享在Unity开发中用到的一些插件使用方法插件介绍等Unity3D之日常开发日常记录主要是博主日常开发中用到的用到的方法技巧开发思路代码分享等Unity3D之日常BUG日常记录记录在使用Unity3D编辑器开发项目过程中遇到的BUG和坑让后来人可以有些参考。