///预先显示动画文件路径//
- public class ClipInfo : EditorWindow
- {
- private AnimationClip clip;
- [MenuItem("Window/Clip Info")]
- static void Init()
- {
- GetWindow(typeof(ClipInfo));
- }
- public void OnGUI()
- {
- clip = EditorGUILayout.ObjectField("Clip", clip, typeof(AnimationClip), false) as AnimationClip;
- EditorGUILayout.LabelField("Curves:");
- if (clip != null)
- {
- foreach (var binding in AnimationUtility.GetCurveBindings(clip))
- {
- AnimationCurve curve = AnimationUtility.GetEditorCurve(clip, binding);
- EditorGUILayout.LabelField(binding.path + "/" + binding.propertyName + ", Keys: " + curve.keys.Length);
- for (int i = 0; i < curve.length; i++)
- {
- EditorGUILayout.LabelField("Keys" + i + ":" + curve[i].value);
- }
- }
- }
- if (GUILayout.Button("Save"))
- {
- Save();
- }
- }
- public void Save()
- {
- if (clip != null)
- {
- ObjectPosCurvesData o = new ObjectPosCurvesData();
- foreach (var binding in AnimationUtility.GetCurveBindings(clip))
- {
- AnimationCurve curve = AnimationUtility.GetEditorCurve(clip, binding);
- Debug.Log(binding.propertyName);
- if (binding.propertyName == "m_LocalPosition.x")
- {
- o.curveX = new float[curve.length];
- o.KeyLength = curve.length;
- for (int i = 0; i < curve.length; i++)
- {
- o.curveX[i] = curve[i].value;
- }
- }
- else if (binding.propertyName == "m_LocalPosition.y")
- {
- o.curveY = new float[curve.length];
- for (int i = 0; i < curve.length; i++)
- {
- o.curveY[i] = curve[i].value;
- }
- }
- else if (binding.propertyName == "m_LocalPosition.z")
- {
- o.curveZ = new float[curve.length];
- for (int i = 0; i < curve.length; i++)
- {
- o.curveZ[i] = curve[i].value;
- }
- }
- }
- //序列化并保存文件
- FileUtils.SaveFile(@"E:\AnimationData\AD.data",FileUtils.SerializeToBinary(o));
- }
- }
- }
- [Serializable]
- public class ObjectPosCurvesData
- {
- public int KeyLength;
- public float[] curveX;
- public float[] curveY;
- public float[] curveZ;
- }
///NavMeshAgent 寻路路径Game显示/
public Transform line;//就是我们刚才添加的 gameobject
private LineRenderer _lineRenderer;//储存 gameobject 的 LineRenderer 组件
void Start ()
{
_lineRenderer = line.GetComponent<LineRenderer>();
}
Vector3[] path = Nav.path.corners;//储存路径
_lineRenderer.SetVertexCount(path.Length);//设置线段数
for (int i = 0; i < path.Length; i++)
{
_lineRenderer.SetPosition(i, path[i]);//设置线段顶点坐标
}
///OpenURL//
It's well worth noting that if you just want to send a very simple one with NO dynamic text, no body, no unusual characters, just replace the spaces with %20 manually like so:
public void LinkHelpEMAIL()
{
string t =
"mailto:blah@blah.com?subject=Question%20on%20Awesome%20Game";
Application.OpenURL(t);
}
exactly like that (do not escape the at symbol). saves typing, tested on both.
/// <summary>
/// - opens the mail app on android, ios & windows (tested on windows)
/// </summary>
public class SendMailCrossPlatform
{
/// <param name="email"> myMail@something.com</param>
/// <param name="subject">my subject</param>
/// <param name="body">my body</param>
public static void SendEmail (string email,string subject,string body)
{
subject = MyEscapeURL(subject);
body = MyEscapeURL(body);
Application.OpenURL("mailto:" + email + "?subject=" + subject + "&body=" + body);
}
public static string MyEscapeURL (string url)
{
return WWW.EscapeURL(url).Replace("+","%20");
}
}
//ScriptableObjectCreateInstance
public class NPCDataInstance : UnityEngine.ScriptableObject
{
//public string data;
public List<NPCData> dataLst;
}
[System.Serializable]
public class NPCData //: ScriptableObject
{
public UnityEngine.Vector3 Position;
//public UnityEngine.Color Color;
public float Color_r;
public float Color_g;
public float Color_b;
}
[MenuItem("GameObject/GeneratePositionColor", false, 1)]/*Assets [CreateAssetMenu(fileName = "UntitledInstaller", menuName = "MyAsset/UntitledInstaller")]//添加这个特性就能在资源窗口右键创建资源*/
public static void GenerateData()
{
var npcs = Selection.gameObjects[0].transform.GetComponentsInChildren<Transform>();
var npcDataInstance = ScriptableObject.CreateInstance<NPCDataInstance>();
npcDataInstance.dataLst = new List<NPCData>();
for (int i = 1, count = npcs.Length; i < count; i++)
{
NPCData data = /*ScriptableObject.CreateInstance<NPCData>();*/new NPCData();
data.Position = npcs[i].transform.position;
SpriteRenderer sr = npcs[i].GetComponent<SpriteRenderer>();
//data.Color = sr.color;
data.Color_r = sr.color.r;
data.Color_g = sr.color.g;
data.Color_b = sr.color.b;
npcDataInstance.dataLst.Add(data);
}
//string json = JsonConvert.SerializeObject(npcDataInstance.dataLst);
AssetDatabase.CreateAsset(npcDataInstance, @"Assets\Resources\NPCData.asset"/*FileUtil.GetProjectRelativePath(AssetDatabase.GetAssetPath(MonoScript.FromScriptableObject(this)))*/);
}
LoadAssetAsync<NPCDataInstance>("NPCData.asset", (name, obj) =>
{
m_npcDataLst = (obj as NPCDataInstance).dataLst; });
//simple spire animation ///
[CreateAssetMenu(order = 1000)]
public class SpriteFrameAnimation : ScriptableObject
{
public bool loop;
public float frameDuration = 15.0f; // duration is in milliseconds
public Sprite[] frames = new Sprite[0];
}
public enum SpriteFrameAnimationResetOption
{
DontReset,
ResetIfNew,
ResetAlways
}
[AddComponentMenu("UnityToolbag/Sprite Frame Animator")]
public class SpriteFrameAnimator : MonoBehaviour
{
private SpriteFrameAnimation _currentAnimation;
private int _frame;
private float _timer;
[SerializeField]
private SpriteRenderer _spriteRenderer;
[SerializeField]
private SpriteFrameAnimation[] _animations;
[SerializeField]
private string _startAnimation = string.Empty;
[SerializeField]
private bool _playOnStart = false;
public bool isAnimationComplete
{
get
{
if (_currentAnimation == null) {
return true;
}
if (_currentAnimation.loop) {
return false;
}
return _frame == _currentAnimation.frames.Length - 1 &&
_timer == _currentAnimation.frameDuration;
}
}
public void Play(string name)
{
Play(name, SpriteFrameAnimationResetOption.ResetIfNew);
}
public void Play(string name, SpriteFrameAnimationResetOption resetOption)
{
SpriteFrameAnimation newAnimation = null;
foreach (var anim in _animations){
if (anim.name == name) {
newAnimation = anim;
break;
}
}
if (newAnimation == null) {
_currentAnimation = null;
return;
}
switch (resetOption) {
case SpriteFrameAnimationResetOption.ResetIfNew: {
if (newAnimation != _currentAnimation) {
_frame = 0;
_timer = 0;
}
break;
}
case SpriteFrameAnimationResetOption.ResetAlways: {
_frame = 0;
_timer = 0;
break;
}
default: {
break;
}
}
_currentAnimation = newAnimation;
if (_currentAnimation != null) {
UpdateWithFrameData();
}
}
public void Stop()
{
_currentAnimation = null;
}
public void Stop(int stopOnIndex)
{
if (_currentAnimation != null) {
_frame = stopOnIndex;
UpdateWithFrameData();
_currentAnimation = null;
}
}
void Awake()
{
_spriteRenderer = GetComponent<SpriteRenderer>();
}
void Start()
{
if (_playOnStart) {
Play(_startAnimation);
}
}
void Update()
{
if (_currentAnimation != null) {
if (!isAnimationComplete) {
_timer += Time.deltaTime * 1000f;
}
if (_timer >= _currentAnimation.frameDuration) {
_timer -= _currentAnimation.frameDuration;
if (!isAnimationComplete || _currentAnimation.loop) {
if (_currentAnimation.loop) {
_frame = (_frame + 1) % _currentAnimation.frames.Length;
}
else if (_frame < _currentAnimation.frames.Length) {
_frame++;
}
UpdateWithFrameData();
}
}
}
}
void UpdateWithFrameData()
{
_spriteRenderer.sprite = _currentAnimation.frames[_frame];
}
}
生成脚本
编辑器脚本可以通过
var scriptPath = AssetDatabase.GetAssetPath(MonoScript.FromScriptableObject(this));
AssetDatabase.LoadAssetAtPath<TextAsset>(assetPath);
inputText.Replace
File.WriteAllText(writePath, inputText);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
物体 transform.rotation.eulerAngles; 遇到万向锁了 transform.forward 向前则没有 ,赋值给主角朝向
设置一下Lua脚本的模板地址 : Assets/Editor/Lua/Template/lua.lua
C#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | using UnityEngine; using UnityEditor; using System; using System.IO; using System.Text; using UnityEditor.ProjectWindowCallback; using System.Text.RegularExpressions; public class Test { [MenuItem("Assets/Create/Lua Script", false, 80)] public static void CreatNewLua() { ProjectWindowUtil.StartNameEditingIfProjectWindowExists(0, ScriptableObject.CreateInstance<MyDoCreateScriptAsset>(), GetSelectedPathOrFallback() + "/New Lua.lua", null, "Assets/Editor/Lua/Template/lua.lua"); } public static string GetSelectedPathOrFallback() { string path = "Assets"; foreach (UnityEngine.Object obj in Selection.GetFiltered(typeof(UnityEngine.Object), SelectionMode.Assets)) { path = AssetDatabase.GetAssetPath(obj); if (!string.IsNullOrEmpty(path) && File.Exists(path)) { path = Path.GetDirectoryName(path); break; } } return path; } } class MyDoCreateScriptAsset : EndNameEditAction { public override void Action(int instanceId, string pathName, string resourceFile) { UnityEngine.Object o = CreateScriptAssetFromTemplate(pathName, resourceFile); ProjectWindowUtil.ShowCreatedAsset(o); } internal static UnityEngine.Object CreateScriptAssetFromTemplate(string pathName, string resourceFile) { string fullPath = Path.GetFullPath(pathName); StreamReader streamReader = new StreamReader(resourceFile); string text = streamReader.ReadToEnd(); streamReader.Close(); string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(pathName); text = Regex.Replace(text, "#NAME#", fileNameWithoutExtension); //string text2 = Regex.Replace(fileNameWithoutExtension, " ", string.Empty); //text = Regex.Replace(text, "#SCRIPTNAME#", text2); //if (char.IsUpper(text2, 0)) //{ // text2 = char.ToLower(text2[0]) + text2.Substring(1); // text = Regex.Replace(text, "#SCRIPTNAME_LOWER#", text2); //} //else //{ // text2 = "my" + char.ToUpper(text2[0]) + text2.Substring(1); // text = Regex.Replace(text, "#SCRIPTNAME_LOWER#", text2); //} bool encoderShouldEmitUTF8Identifier = true; bool throwOnInvalidBytes = false; UTF8Encoding encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier, throwOnInvalidBytes); bool append = false; StreamWriter streamWriter = new StreamWriter(fullPath, append, encoding); streamWriter.Write(text); streamWriter.Close(); AssetDatabase.ImportAsset(pathName); return AssetDatabase.LoadAssetAtPath(pathName, typeof(UnityEngine.Object)); } } |
初级资源创建
Editor文件夹下创建脚本:
using UnityEngine;
using UnityEditor;
public class CreateTest
{
[MenuItem ("Assets/Create ExampleAssets")]
static void CreateExampleAssets ()
{
var material = new Material (Shader.Find ("Standard"));
ProjectWindowUtil.CreateAsset (material, "New Material.mat");
}
}
点击Assets--Create ExampleAssets 就会发现一个材质球被创建
中级资源创建
Editor文件夹下创建脚本:
using UnityEngine;
using UnityEditor;
public class CreateMaterial
{
[MenuItem ("Assets/Create Material")]
static void CreateExampleAssets ()
{
var material = new Material (Shader.Find ("Standard"));
var instanceID = material.GetInstanceID ();
var icon = AssetPreview.GetMiniThumbnail (material);
var endNameEditAction =
ScriptableObject.CreateInstance<DoCreateMaterialAsset> ();
ProjectWindowUtil.StartNameEditingIfProjectWindowExists (instanceID,
endNameEditAction, "New Material.mat", icon, "");
}
}
点击Assets--Create Material 创建一个特定的材质球
更自由的自定义资源创建
Editor文件夹下创建脚本:
using UnityEngine;
using UnityEditor;
using UnityEditor.ProjectWindowCallback;
public class DoCreateMaterialAsset : EndNameEditAction
{
public override void Action (int instanceId, string pathName, string resourceFile)
{
var mat = (Material)EditorUtility.InstanceIDToObject (instanceId);
mat.color = Color.red;
AssetDatabase.CreateAsset (mat, pathName);
AssetDatabase.ImportAsset (pathName);
ProjectWindowUtil.ShowCreatedAsset (mat);
}
}
Editor文件夹下创建脚本:
using System.IO;
using System.Text;
using UnityEditor;
using UnityEditor.ProjectWindowCallback;
using System;
public class DoCreateScriptAsset : EndNameEditAction
{
public override void Action (int instanceId, string pathName, string resourceFile)
{
var text = File.ReadAllText (resourceFile);
var className = Path.GetFileNameWithoutExtension (pathName);
//清除空格
className = className.Replace (" ", "");
text ="//Programer: "+"porgramerName"+"\n//code date:"+DateTime.Now.Date.ToShortDateString()+"\n"
+text.Replace ("#SCRIPTNAME#", className);
text += "\n//自己添加Something!"+"\n";
//utf8
var encoding = new UTF8Encoding (true, false);
File.WriteAllText (pathName, text, encoding);
AssetDatabase.ImportAsset (pathName);
var asset = AssetDatabase.LoadAssetAtPath<MonoScript> (pathName);
ProjectWindowUtil.ShowCreatedAsset (asset);
}
}
Editor文件夹下创建脚本:
using UnityEditor;
using UnityEngine;
using System.IO;
public class CreateAssets : EditorWindow
{
[MenuItem("Window/CreatAssets")]
static void Open ()
{
GetWindow<CreateAssets> ();
}
public string scriptName,materialName;
void OnGUI()
{
var options = new []{GUILayout.Width (100), GUILayout.Height (20)};
GUILayout.Label ("CreateScripts");
EditorGUILayout.Space ();
EditorGUILayout.BeginHorizontal ();
EditorGUILayout.LabelField ("ScriptName",options);
scriptName= EditorGUILayout.TextArea (scriptName);
EditorGUILayout.EndHorizontal ();
if (GUILayout.Button ("Create")) {
CreateScript (scriptName);
}
GUILayout.Label ("CreateMaterial");
EditorGUILayout .Space ();
EditorGUILayout.BeginHorizontal ();
EditorGUILayout.LabelField ("materialName",options);
materialName= EditorGUILayout.TextArea (materialName);
EditorGUILayout.EndHorizontal ();
if (GUILayout.Button ("Create")) {
CreateMaterial (materialName);
}
}
// 新建自定义脚本
static void CreateScript (string scriptName)
{
var resourceFile = Path.Combine (EditorApplication.applicationContentsPath,
"Resources/ScriptTemplates/81-C# Script-NewBehaviourScript.cs.txt");
Debug.Log (resourceFile);
Texture2D csIcon =
EditorGUIUtility.IconContent ("cs Script Icon").image as Texture2D;
var endNameEditAction =
ScriptableObject.CreateInstance<DoCreateScriptAsset> ();
ProjectWindowUtil.StartNameEditingIfProjectWindowExists (0, endNameEditAction,
scriptName+".cs", csIcon, resourceFile);
}
//新建Material
static void CreateMaterial (string materialName)
{
var material = new Material (Shader.Find ("Standard"));
var instanceID = material.GetInstanceID ();
var icon = AssetPreview.GetMiniThumbnail (material);
var endNameEditAction =
ScriptableObject.CreateInstance<DoCreateMaterialAsset> ();
ProjectWindowUtil.StartNameEditingIfProjectWindowExists (instanceID,
endNameEditAction, materialName+".mat", icon, "");
}
}
[CustomPropertyDrawer(typeof(LabelAttribute),false)]
public class LabelDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
label.text = (attribute as LabelAttribute).label;
EditorGUI.PropertyField(position, property, label);
}
}
public class LabelAttribute : PropertyAttribute
{
public string label;
public LabelAttribute(string label)
{
this.label = label;
}
}
[Label("中文属性名")]
public int testInt;
[CustomPropertyDrawer(typeof(TabAttribute))]
public class TabDraw : PropertyDrawer
{
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return 0f;
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
GUIStyle buttonActive = new GUIStyle(GUI.skin.button) { normal = GUI.skin.button.active };
string[] tabNames = (attribute as TabAttribute).tabNames;
EditorGUILayout.BeginHorizontal();
int count = tabNames.Length;
for (int i = 0; i < count; i++)
{
if (GUILayout.Button(tabNames[i], i == property.intValue ? buttonActive : GUI.skin.button))
{
property.intValue = i;
}
}
EditorGUILayout.EndHorizontal();
}
}
public class TabAttribute: PropertyAttribute
{
public string[] tabNames;
}
//使用示例
[Tab(tabNames = new string[] { "tab1","tab2"})]
public int tabIndex;
publicTAddComponent<T>() whereT: EntityComponent,new()
{
if (_componentTypes.Contains(typeof(T)))
{
varcomp = components.Find(item=> item.GetType() == typeof(T));
returncompasT;
}
Tcomponent= newT();
components.Add(component);
_componentTypes.Add(typeof(T));
ProcessRequiredComponent(typeof(T));
component.OnAttachToEntity(this);
returncomponent;
}
privatevoidProcessRequiredComponent(Typetype)
{
if (!typeof(EntityComponent).IsAssignableFrom(type))
{
Debugger.LogErrorFormat("type {0} must inherited from EntityComponent", type.Name);
return;
}
RequireComponentattr = type.GetCustomAttribute<RequireComponent>();
if (attr == null)
return;
Type[] typeArr= newType[3] { attr.m_Type0,attr.m_Type1, attr.m_Type2};
for(inti = 0; i < 3; i++)
{
Typecomptype= typeArr[i];
if (comptype!= null && typeof(EntityComponent).IsAssignableFrom(comptype))
{
AddComponent(comptype);
}
}
}
"<color=#FFFF00>dfafd</color>" Unity打印自定义颜色log
CreateAssetMenu(fileName = "bb", menuName = "aa", order = 100)
public class TerrainData : ScriptableObject {} 会在右键Create下有个aa,并生成bb的scriptableObject文件
transform.rotation.eulerAngles transform.rotation = Quaternion.Euler(view.x, view.y, view.z);
static publicTLoadAsset<T> (stringpath)whereT: Object
{
Object obj = LoadAsset(path);
if (obj ==null)returnnull;
T val = obj asT;
if (val !=null)returnval;
if (typeof(T).IsSubclassOf(typeof(Component)))
{
if (obj.GetType() ==typeof(GameObject))
{
GameObjectgo =objas GameObject;
return go.GetComponent(typeof(T))asT;
}
}
return null;
}
public delegate void ActionClick(ActorData data);
public event ActionClick ActorDataDelegate;
public staticTCreateItemIcon<T>(ItemNumitemNum,Transformparent =null) where T : Object
{
GameObject go = ResUtil.LoadGameObject("UI/CommonIcon/ItemIconInfo");
if (parent !=null)
parent.AddChildEx(go.transform);
go.name =string.Format("Item{0}",itemNum.ItemId);
go.GetComponentOrAdd<ItemIconInfo>().Data =itemNum;
T obj = go asT;
if (obj !=null)returnobj;
if(typeof(T).IsSubclassOf(typeof(Component)))
{
//if (go.GetType() == typeof(GameObject))
{
return go.GetComponent(typeof(T))asT;
}
}
return null;
}
代码生成AnimatorController
private void CreateAnimatorController(List<AnimationClip> clipList)
{
//创建一个控制器
AnimatorController animatorController = AnimatorController.CreateAnimatorControllerAtPath("Assets/youkexueyuan.controller");
//获取控制器的layer
AnimatorControllerLayer layer = animatorController.layers[0];
//获取状态机
AnimatorStateMachine machine = layer.stateMachine;
//添加一个坐标,让状态从这个位置开始摆放,防止状态乱摆,巨丑
Vector3 dpos = new Vector3(300,0,0);
foreach(AnimationClip clip in clipList)
{
AnimatorState state = new AnimatorState(); //machine.AddState(clip.name);
state.motion = clip;
state.name = clip.name;
machine.AddState(state, dpos);
dpos += new Vector3(0,50,0);//改变下一个坐标,让状态排成一列
if(state.name.Equals("idle"))
{
machine.defaultState = state;//设置默认状态
}
}
}
代码拷贝FBX模型动画剪辑
AnimationClip dstClip = new AnimationClip();
dstClip.name = srcClip.name;
string copyPath ="Assets/xiaobao.anim";
AssetDatabase.CreateAsset(dstClip, copyPath);
//拷贝Clip的浮点数据
EditorCurveBinding[] bindings = AnimationUtility.GetCurveBindings(srcClip);
for (int i = 0; i < bindings.Length; i++)
{
AnimationUtility.SetEditorCurve(dstClip, bindings[i], AnimationUtility.GetEditorCurve(srcClip, bindings[i]));
}
dstClip.frameRate = 30.0f;
Mesh材质合并
using UnityEngine;
using System.Collections;
public class Combine_Test : MonoBehaviour {
// Use this for initialization
void Start ()
{
//---------------- 先获取材质 -------------------------
//获取自身和所有子物体中所有MeshRenderer组件
MeshRenderer[] meshRenderers = GetComponentsInChildren<MeshRenderer>();
//新建材质球数组
Material[] mats = new Material[meshRenderers.Length];
for (int i = 0; i < meshRenderers.Length; i++) {
//生成材质球数组
mats[i] = meshRenderers[i].sharedMaterial;
}
//---------------- 合并 Mesh -------------------------
//获取自身和所有子物体中所有MeshFilter组件
MeshFilter[] meshFilters = GetComponentsInChildren<MeshFilter>();
CombineInstance[] combine = new CombineInstance[meshFilters.Length];
for (int i = 0; i < meshFilters.Length; i++) {
combine[i].mesh = meshFilters[i].sharedMesh;
//矩阵(Matrix)自身空间坐标的点转换成世界空间坐标的点
combine[i].transform = meshFilters[i].transform.localToWorldMatrix;
meshFilters[i].gameObject.SetActive(false);
}
//为新的整体新建一个mesh
transform.GetComponent<MeshFilter>().mesh = new Mesh();
//合并Mesh. 第二个false参数, 表示并不合并为一个网格, 而是一个子网格列表
transform.GetComponent<MeshFilter>().mesh.CombineMeshes(combine, false);
transform.gameObject.SetActive(true);
//为合并后的新Mesh指定材质 ------------------------------
transform.GetComponent<MeshRenderer>().sharedMaterials = mats;
}
// Update is called once per frame
void Update () {
}
}
反编译游戏资源得到的都是Altas大图片变成单张图片
usingUnityEngine;
usingSystem.Collections;
usingUnityEditor;
usingSystem.IO;
publicclassSlipTexture:EditorWindow
{
publicTexture2DMainTex=null;
[MenuItem("Window/分割图集")]
publicstaticvoidCreateWindows()
{
SlipTexture sp =EditorWindow.CreateInstance<SlipTexture>();
sp.title="分割图集";
sp.Show(true);
}
voidOnGUI()
{
MainTex=EditorGUILayout.ObjectField("mainText",MainTex,typeof(Texture2D))asTexture2D;
if(MainTex!=null)
{
if(GUILayout.Button("导出成小图片"))
{
string path =AssetDatabase.GetAssetPath(MainTex);
TextureImporter importer =AssetImporter.GetAtPath(path)asTextureImporter;
if(importer.textureType!=TextureImporterType.Sprite||
importer.spriteImportMode!=SpriteImportMode.Multiple||
importer.spritesheet.Length==0
)
{
Debug.LogError("当前图片不是Sprite Multiple格式 或者没有分割");
return;
}
importer.isReadable=true;
AssetDatabase.ImportAsset(path);
AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport);
string savepath =EditorUtility.OpenFolderPanel("选择要保存的文件夹",Application.dataPath,"");
if(!string.IsNullOrEmpty(savepath))
{
foreach(SpriteMetaData metaDatain importer.spritesheet)//遍历小图集
{
Texture2D myimage =newTexture2D((int)metaData.rect.width,(int)metaData.rect.height);
for(int y=(int)metaData.rect.y; y < metaData.rect.y+ metaData.rect.height; y++)//Y轴像素
{
for(int x=(int)metaData.rect.x; x < metaData.rect.x+ metaData.rect.width; x++)
myimage.SetPixel(x-(int)metaData.rect.x, y -(int)metaData.rect.y,MainTex.GetPixel(x, y));
}
//转换纹理到EncodeToPNG兼容格式
if(myimage.format!=TextureFormat.ARGB32&& myimage.format!=TextureFormat.RGB24)
{
Texture2D newTexture =newTexture2D(myimage.width, myimage.height);
newTexture.SetPixels(myimage.GetPixels(0),0);
myimage= newTexture;
}
byte[] pngData = myimage.EncodeToPNG();
//AssetDatabase.CreateAsset(myimage, rootPath + "/" + image.name + "/" + metaData.name + ".PNG");
File.WriteAllBytes(savepath+"/"+ metaData.name+".PNG", pngData);
}
}
}
}
}
}
判断在不在摄像机裁剪范围
void Update()
{
if (renderer.IsVisibleFrom(Camera.main)) Debug.Log("Visible");
else Debug.Log("Not visible");
}
Update()
{
if (renderer.IsVisibleFrom(Camera.main)) Debug.Log("Visible");
else Debug.Log("Not visible");
}
<span style="color:#008000">
</span>
static function IsRenderedFrom(renderer : Renderer, camera : Camera) : boolean
{
var planes = GeometryUtility.CalculateFrustumPlanes(camera);
return GeometryUtility.TestPlanesAABB(planes, renderer.bounds);
}
function IsRenderedFrom(renderer : Renderer, camera : Camera) : boolean
{
var planes = GeometryUtility.CalculateFrustumPlanes(camera);
return GeometryUtility.TestPlanesAABB(planes, renderer.bounds);
}
/// 3D世界坐标转2DUI坐标并自适应的做法(血条,气泡)
UI
屏幕坐标系是从左下角为原点,Y轴向右为正,X轴向上为正。所有相关的UI的锚点都需要是设置成左下为锚点。其次,UI挂载的根节点需要做屏幕的自适应,保证和屏幕一样大。
脚本
常见的情况下有两种宽高。只要不是PC的固定界面大小,屏幕大小和设置的界面大小就会有对应的缩放情况。
第一种情况
Canvas使用固定屏幕大小。这种情况无论真机比例如何,都会按照预先设置好的大小比例进行缩放。
因为没有跟随屏幕分辨率进行缩放,所以我们在计算后需要再做多一步进行转换。根节点要做自适应。width和Height是屏幕宽高,位置是中心点(宽高/2)。
父节点的大小设置
PlaneTransform.sizeDelta = CanvanTransform.sizeDelta;
PlaneTransform.anchoredPosition = PlaneTransform.sizeDelta / 2;
UI的位置需要转化一下
Vector3 pos = Camera.main.WorldToScreenPoint(m_TragetTransform.position + m_Offect);
pos.x *= m_CanvasTransform.sizeDelta.x / Screen.width;
pos.y *= m_CanvasTransform.sizeDelta.y / Screen.height;
pos.z = 0;
m_MyTransform.anchoredPosition = pos;
第二种情况
Canvas跟随屏幕大小,这样会跟随着分辨率的改变而改变。
因为根节点已经做了转换,所以直接设置即可。
//m_TragetTransform是模型对象
Vector3 pos = Camera.main.WorldToScreenPoint(m_TragetTransform.position + m_Offect);
pos.z = 0;
m_MyTransform.anchoredPosition = pos;
//