博客
关于我
Unity2d游戏开发:UGUI 与 Spine 的完美结合
阅读量:273 次
发布时间:2019-03-01

本文共 32873 字,大约阅读时间需要 109 分钟。

孙广东   2016.3.18


spine 动画 转化为 Ugui 系统的 Graphics 元素:(Unity 5.3以上)



SkeletonGraphic.cs       代替官方的  SkeletonAnimation.cs   使用(对象/预制体上)

SkeletonGraphic.shader   代替 官方的   Spine/Skeleton  shader 使用(赋值给材质上)

/****************************************************************************** * Spine Runtimes Software License * Version 2.3 *  * Copyright (c) 2013-2015, Esoteric Software * All rights reserved. *  * You are granted a perpetual, non-exclusive, non-sublicensable and * non-transferable license to use, install, execute and perform the Spine * Runtimes Software (the "Software") and derivative works solely for personal * or internal use. Without the written permission of Esoteric Software (see * Section 2 of the Spine Software License Agreement), you may not (a) modify, * translate, adapt or otherwise create derivative works, improvements of the * Software or develop new applications using the Software or (b) remove, * delete, alter or obscure any trademarks or any copyright, trademark, patent * or other intellectual property or proprietary rights notices on or in the * Software, including any copy thereof. Redistributions in binary or source * form must include this license and terms. *  * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/using UnityEngine;using System.Collections;using System.Collections.Generic;using UnityEngine.UI;using Spine;[ExecuteInEditMode, RequireComponent(typeof(CanvasRenderer))][AddComponentMenu("Spine/SkeletonGraphic (Unity UI Canvas)")]public class SkeletonGraphic : Graphic {	#region Inspector	[Header("Skeleton Renderer")]	public SkeletonDataAsset skeletonDataAsset;	[SpineSkin(dataField:"skeletonDataAsset")]	public string initialSkinName = "default";	[Header("Skeleton Animation")]	[SerializeField]	[SpineAnimation(dataField:"skeletonDataAsset")]	private string m_AnimationName;	public float timeScale = 1;	public bool loop;	#if UNITY_EDITOR	protected override void OnValidate () {		// This handles Scene View preview.		base.OnValidate ();		this.raycastTarget = false;		if (valid) {			if (skeletonDataAsset == null) {				Clear();				m_AnimationName = "";			} else if (skeletonDataAsset.GetSkeletonData(true) != skeleton.data) {				Initialize();				m_AnimationName = "";			} else {				if (freeze) return;				skeleton.SetToSetupPose();				if (state == null) Debug.Log("state was null for some reason");				state.ClearTracks(); // Need this. Otherwise, it mixes between animations. It's hilarious.				state.SetAnimation(0, m_AnimationName, this.loop);				Update(0);				skeleton.UpdateWorldTransform();				this.material = sharedMaterials[0];				UpdateMesh();			}		} else {			if (skeletonDataAsset != null)				Initialize();		}	}	#endif	#endregion	#region Non-Inspector API	internal Skeleton skeleton;	public Skeleton Skeleton {	// TODO: Add this to official		get {			if (skeleton == null) Initialize();			return skeleton;		}	}	internal Spine.AnimationState state;	public Spine.AnimationState State {	// TODO: Add this to official		get {			if (state == null) Initialize();			return state;		}	}	#endregion	#region Advanced Settings	[Header("Advanced")]	public bool freeze = false;	public bool calculateNormals;	public bool calculateTangents;	public float zSpacing = 0;	public bool renderMeshes = true, immutableTriangles;	public bool frontFacing;	public bool logErrors = false;	#endregion	#region Internals	[System.NonSerialized]	public bool valid;	Mesh mesh1, mesh2;	bool useMesh1;	float[] tempVertices = new float[8];	Vector3[] vertices;	Color32[] colors;	Vector2[] uvs;	Material[] sharedMaterials = new Material[0];	readonly ExposedList<Material> submeshMaterials = new ExposedList<Material>();	readonly ExposedList<Submesh> submeshes = new ExposedList<Submesh>();	LastState lastState = new LastState();	#endregion	#region SkeletonAnimation	public delegate void SkeletonGraphicDelegate (SkeletonGraphic skeletonGraphic);	protected event SkeletonGraphicDelegate m_UpdateLocal;	protected event SkeletonGraphicDelegate m_UpdateWorld;	protected event SkeletonGraphicDelegate m_UpdateComplete;	public event SkeletonGraphicDelegate UpdateLocal { add { m_UpdateLocal += value; } remove { m_UpdateLocal -= value; }	}	public event SkeletonGraphicDelegate UpdateWorld { add { m_UpdateWorld += value; } remove { m_UpdateWorld -= value; }	}	public event SkeletonGraphicDelegate UpdateComplete { add { m_UpdateComplete += value; } remove { m_UpdateComplete -= value; } }	public string AnimationName {		get {			if (state == null) return null;			TrackEntry entry = state.GetCurrent(0);			return entry == null ? null : entry.Animation.Name;		}		set {			if (m_AnimationName == value) return;			m_AnimationName = value;			if ( string.IsNullOrEmpty(value) )				state.ClearTrack (0);			else				state.SetAnimation(0, value, loop);		}	}	public virtual void Update () {		if (freeze) return;		Update(Time.deltaTime);	}	public virtual void Update (float deltaTime) {		if (!valid) return;		deltaTime *= timeScale;		skeleton.Update(deltaTime);		state.Update(deltaTime);		state.Apply(skeleton);		if (m_UpdateLocal != null) m_UpdateLocal(this);		skeleton.UpdateWorldTransform();		if (m_UpdateWorld != null) { 			m_UpdateWorld(this);			skeleton.UpdateWorldTransform();		}		if (m_UpdateComplete != null) m_UpdateComplete(this);	}	#endregion	#region UI.Graphic	protected override void Awake () {		base.Awake ();		//Debug.Log("Awake");		if (!valid) {			Initialize();			Rebuild(CanvasUpdate.PreRender);		}	}	public override void Rebuild (CanvasUpdate update) {		if (canvasRenderer.cull) return;		//Debug.Log("Rebuild");		#if UNITY_EDITOR		if (Application.isEditor) Skeleton.UpdateWorldTransform();		#endif		if (update == CanvasUpdate.PreRender) UpdateMesh();	}	void LateUpdate () {		if (freeze) return;		UpdateMesh();	}	protected override void OnDestroy () {		base.OnDestroy ();		DestroyWorkingMeshes();	}	#endregion	#region SkeletonRenderer	void DestroyWorkingMeshes () {		//Debug.Log("Destroy Meshes.");		if (mesh1 != null) {			if (Application.isPlaying)				Destroy(mesh1);			else				DestroyImmediate(mesh1);		}		if (mesh2 != null) {			if (Application.isPlaying)				Destroy(mesh2);			else				DestroyImmediate(mesh2);		}		mesh1 = null;		mesh2 = null;	}	void Clear () {		//Debug.Log("Clear");		DestroyWorkingMeshes();		canvasRenderer.Clear();		lastState = new LastState();		useMesh1 = false;		vertices = null;		colors = null;		uvs = null;		sharedMaterials = new Material[0];		submeshMaterials.Clear();		submeshes.Clear();		// TODO: Check fix with a known repro case.		//lastState.forceUpdateMesh1 = true;		//lastState.forceUpdateMesh2 = true;		skeleton = null;		state = null; // SkeletonAnimation		valid = false;	}	protected override void Reset () {		//Debug.Log("Reset");		base.Reset ();		Initialize();	}	public virtual void Initialize () {		//Debug.Log("Initialize");		Clear();		if (!skeletonDataAsset) { if (logErrors) Debug.LogError("Missing SkeletonData asset.", this); return; }		SkeletonData skeletonData = skeletonDataAsset.GetSkeletonData(false); if (skeletonData == null) return;		valid = true;		mesh1 = NewMesh();		mesh2 = NewMesh();		vertices = new Vector3[0];		skeleton = new Skeleton(skeletonData);		if (!string.IsNullOrEmpty(initialSkinName) && initialSkinName != "default")			skeleton.SetSkin(initialSkinName);		UpdateMesh();		// SkeletonAnimation		state = new Spine.AnimationState(skeletonDataAsset.GetAnimationStateData());		if ( !string.IsNullOrEmpty(m_AnimationName) ) {			state.SetAnimation(0, m_AnimationName, loop);			Update (0);		}	}	protected static Mesh NewMesh () {		var mesh = new Mesh();		mesh.name = "Skeleton Mesh";		mesh.hideFlags = HideFlags.HideAndDontSave;		mesh.MarkDynamic();		return mesh;	}	public void UpdateMesh () {		//Debug.Log("UpdateMesh");		if (!valid) return;		float scale = canvas.referencePixelsPerUnit;		// Count vertices and submesh triangles.		int vertexCount = 0;		int submeshTriangleCount = 0, submeshFirstVertex = 0, submeshStartSlotIndex = 0;		Material lastMaterial = null;		ExposedList<Slot> drawOrder = skeleton.drawOrder;		int drawOrderCount = drawOrder.Count;		bool renderMeshes = this.renderMeshes;		// Clear last state of attachments and submeshes		ExposedList<int> attachmentsTriangleCountTemp = lastState.attachmentsTriangleCountTemp;		attachmentsTriangleCountTemp.GrowIfNeeded(drawOrderCount);		attachmentsTriangleCountTemp.Count = drawOrderCount;		ExposedList<bool> attachmentsFlipStateTemp = lastState.attachmentsFlipStateTemp;		attachmentsFlipStateTemp.GrowIfNeeded(drawOrderCount);		attachmentsFlipStateTemp.Count = drawOrderCount;		ExposedList<LastState.AddSubmeshArguments> addSubmeshArgumentsTemp = lastState.addSubmeshArgumentsTemp;		addSubmeshArgumentsTemp.Clear(false);		for (int i = 0; i < drawOrderCount; i++) {			Slot slot = drawOrder.Items[i];			Bone bone = slot.bone;			Attachment attachment = slot.attachment;			object rendererObject;			int attachmentVertexCount, attachmentTriangleCount;			bool worldScaleXIsPositive = bone.worldScaleX >= 0f;			bool worldScaleYIsPositive = bone.worldScaleY >= 0f;			bool worldScaleIsSameSigns = (worldScaleXIsPositive && worldScaleYIsPositive) || 				(!worldScaleXIsPositive && !worldScaleYIsPositive);			bool flip = frontFacing && ((bone.worldFlipX != bone.worldFlipY) == worldScaleIsSameSigns);			attachmentsFlipStateTemp.Items[i] = flip;			attachmentsTriangleCountTemp.Items[i] = -1;			var regionAttachment = attachment as RegionAttachment;			if (regionAttachment != null) {				rendererObject = regionAttachment.RendererObject;				attachmentVertexCount = 4;				attachmentTriangleCount = 6;			} else {				if (!renderMeshes)					continue;				var meshAttachment = attachment as MeshAttachment;				if (meshAttachment != null) {					rendererObject = meshAttachment.RendererObject;					attachmentVertexCount = meshAttachment.vertices.Length >> 1;					attachmentTriangleCount = meshAttachment.triangles.Length;				} else {					var skinnedMeshAttachment = attachment as SkinnedMeshAttachment;					if (skinnedMeshAttachment != null) {						rendererObject = skinnedMeshAttachment.RendererObject;						attachmentVertexCount = skinnedMeshAttachment.uvs.Length >> 1;						attachmentTriangleCount = skinnedMeshAttachment.triangles.Length;					} else						continue;				}			}			// Populate submesh when material changes.			#if !SPINE_TK2D			var currentMaterial = (Material)((AtlasRegion)rendererObject).page.rendererObject;			#else			var currentMaterial = (rendererObject.GetType() == typeof(Material)) ? (Material)rendererObject : (Material)((AtlasRegion)rendererObject).page.rendererObject;			#endif			if ((lastMaterial != null && lastMaterial.GetInstanceID() != currentMaterial.GetInstanceID()) ) {				addSubmeshArgumentsTemp.Add(					new LastState.AddSubmeshArguments(lastMaterial, submeshStartSlotIndex, i, submeshTriangleCount, submeshFirstVertex, false)				);				submeshTriangleCount = 0;				submeshFirstVertex = vertexCount;				submeshStartSlotIndex = i;			}			lastMaterial = currentMaterial;			submeshTriangleCount += attachmentTriangleCount;			vertexCount += attachmentVertexCount;			attachmentsTriangleCountTemp.Items[i] = attachmentTriangleCount;		}		addSubmeshArgumentsTemp.Add(			new LastState.AddSubmeshArguments(lastMaterial, submeshStartSlotIndex, drawOrderCount, submeshTriangleCount, submeshFirstVertex, true)		);		bool mustUpdateMeshStructure = CheckIfMustUpdateMeshStructure(attachmentsTriangleCountTemp, attachmentsFlipStateTemp, addSubmeshArgumentsTemp);		if (mustUpdateMeshStructure) {			submeshMaterials.Clear();			for (int i = 0, n = addSubmeshArgumentsTemp.Count; i < n; i++) {				LastState.AddSubmeshArguments arguments = addSubmeshArgumentsTemp.Items[i];				AddSubmesh(					arguments.material,					arguments.startSlot,					arguments.endSlot,					arguments.triangleCount,					arguments.firstVertex,					arguments.lastSubmesh,					attachmentsFlipStateTemp				);			}			// Set materials.			if (submeshMaterials.Count == sharedMaterials.Length)				submeshMaterials.CopyTo(sharedMaterials);			else				sharedMaterials = submeshMaterials.ToArray();			//meshRenderer.sharedMaterials = sharedMaterials;			this.material = sharedMaterials[0];			canvasRenderer.SetMaterial(sharedMaterials[0], (Texture)null);		}		// Ensure mesh data is the right size.		Vector3[] vertices = this.vertices;		bool newTriangles = vertexCount > vertices.Length;		if (newTriangles) {			// Not enough vertices, increase size.			this.vertices = vertices = new Vector3[vertexCount];			this.colors = new Color32[vertexCount];			this.uvs = new Vector2[vertexCount];			mesh1.Clear();			mesh2.Clear();		} else {			// Too many vertices, zero the extra.			Vector3 zero = Vector3.zero;			for (int i = vertexCount, n = lastState.vertexCount ; i < n; i++)				vertices[i] = zero;		}		lastState.vertexCount = vertexCount;		// Setup mesh.		float zSpacing = this.zSpacing;		float[] tempVertices = this.tempVertices;		Vector2[] uvs = this.uvs;		Color32[] colors = this.colors;		int vertexIndex = 0;		Color32 vertColor;		Color graphicColor = base.color;		float a = skeleton.a * 255, r = skeleton.r, g = skeleton.g, b = skeleton.b;		// Mesh bounds		Vector3 meshBoundsMin;		meshBoundsMin.x = float.MaxValue;		meshBoundsMin.y = float.MaxValue;		meshBoundsMin.z = zSpacing > 0f ? 0f : zSpacing * (drawOrderCount - 1);		Vector3 meshBoundsMax;		meshBoundsMax.x = float.MinValue;		meshBoundsMax.y = float.MinValue;		meshBoundsMax.z = zSpacing < 0f ? 0f : zSpacing * (drawOrderCount - 1);		for (int i = 0; i < drawOrderCount; i++) {			Slot slot = drawOrder.Items[i];			Attachment attachment = slot.attachment;			var regionAttachment = attachment as RegionAttachment;			if (regionAttachment != null) {				regionAttachment.ComputeWorldVertices(slot.bone, tempVertices);				float z = i * zSpacing;				vertices[vertexIndex].x = tempVertices[RegionAttachment.X1] * scale;				vertices[vertexIndex].y = tempVertices[RegionAttachment.Y1] * scale;				vertices[vertexIndex].z = z;				vertices[vertexIndex + 1].x = tempVertices[RegionAttachment.X4] * scale;				vertices[vertexIndex + 1].y = tempVertices[RegionAttachment.Y4] * scale;				vertices[vertexIndex + 1].z = z;				vertices[vertexIndex + 2].x = tempVertices[RegionAttachment.X2] * scale;				vertices[vertexIndex + 2].y = tempVertices[RegionAttachment.Y2] * scale;				vertices[vertexIndex + 2].z = z;				vertices[vertexIndex + 3].x = tempVertices[RegionAttachment.X3] * scale;				vertices[vertexIndex + 3].y = tempVertices[RegionAttachment.Y3] * scale;				vertices[vertexIndex + 3].z = z;				vertColor.a = (byte)(a * slot.a * regionAttachment.a * graphicColor.a);				vertColor.r = (byte)(r * slot.r * regionAttachment.r * graphicColor.r * vertColor.a);				vertColor.g = (byte)(g * slot.g * regionAttachment.g * graphicColor.g * vertColor.a);				vertColor.b = (byte)(b * slot.b * regionAttachment.b * graphicColor.b * vertColor.a);				if (slot.data.blendMode == BlendMode.additive) vertColor.a = 0;				colors[vertexIndex] = vertColor;				colors[vertexIndex + 1] = vertColor;				colors[vertexIndex + 2] = vertColor;				colors[vertexIndex + 3] = vertColor;				float[] regionUVs = regionAttachment.uvs;				uvs[vertexIndex].x = regionUVs[RegionAttachment.X1];				uvs[vertexIndex].y = regionUVs[RegionAttachment.Y1];				uvs[vertexIndex + 1].x = regionUVs[RegionAttachment.X4];				uvs[vertexIndex + 1].y = regionUVs[RegionAttachment.Y4];				uvs[vertexIndex + 2].x = regionUVs[RegionAttachment.X2];				uvs[vertexIndex + 2].y = regionUVs[RegionAttachment.Y2];				uvs[vertexIndex + 3].x = regionUVs[RegionAttachment.X3];				uvs[vertexIndex + 3].y = regionUVs[RegionAttachment.Y3];				// Calculate Bounds min/max X				if (tempVertices[RegionAttachment.X1] < meshBoundsMin.x)					meshBoundsMin.x = tempVertices[RegionAttachment.X1];				else if (tempVertices[RegionAttachment.X1] > meshBoundsMax.x)					meshBoundsMax.x = tempVertices[RegionAttachment.X1];				if (tempVertices[RegionAttachment.X2] < meshBoundsMin.x)					meshBoundsMin.x = tempVertices[RegionAttachment.X2];				else if (tempVertices[RegionAttachment.X2] > meshBoundsMax.x)					meshBoundsMax.x = tempVertices[RegionAttachment.X2];				if (tempVertices[RegionAttachment.X3] < meshBoundsMin.x)					meshBoundsMin.x = tempVertices[RegionAttachment.X3];				else if (tempVertices[RegionAttachment.X3] > meshBoundsMax.x)					meshBoundsMax.x = tempVertices[RegionAttachment.X3];				if (tempVertices[RegionAttachment.X4] < meshBoundsMin.x)					meshBoundsMin.x = tempVertices[RegionAttachment.X4];				else if (tempVertices[RegionAttachment.X4] > meshBoundsMax.x)					meshBoundsMax.x = tempVertices[RegionAttachment.X4];				// Calculate Bounds min/max Y				if (tempVertices[RegionAttachment.Y1] < meshBoundsMin.y)					meshBoundsMin.y = tempVertices[RegionAttachment.Y1];				else if (tempVertices[RegionAttachment.Y1] > meshBoundsMax.y)					meshBoundsMax.y = tempVertices[RegionAttachment.Y1];				if (tempVertices[RegionAttachment.Y2] < meshBoundsMin.y)					meshBoundsMin.y = tempVertices[RegionAttachment.Y2];				else if (tempVertices[RegionAttachment.Y2] > meshBoundsMax.y)					meshBoundsMax.y = tempVertices[RegionAttachment.Y2];				if (tempVertices[RegionAttachment.Y3] < meshBoundsMin.y)					meshBoundsMin.y = tempVertices[RegionAttachment.Y3];				else if (tempVertices[RegionAttachment.Y3] > meshBoundsMax.y)					meshBoundsMax.y = tempVertices[RegionAttachment.Y3];				if (tempVertices[RegionAttachment.Y4] < meshBoundsMin.y)					meshBoundsMin.y = tempVertices[RegionAttachment.Y4];				else if (tempVertices[RegionAttachment.Y4] > meshBoundsMax.y)					meshBoundsMax.y = tempVertices[RegionAttachment.Y4];				vertexIndex += 4;			} else {				if (!renderMeshes)					continue;				var meshAttachment = attachment as MeshAttachment;				if (meshAttachment != null) {					int meshVertexCount = meshAttachment.vertices.Length;					if (tempVertices.Length < meshVertexCount)						this.tempVertices = tempVertices = new float[meshVertexCount];					meshAttachment.ComputeWorldVertices(slot, tempVertices);					vertColor.a = (byte)(a * slot.a * meshAttachment.a * graphicColor.a);					vertColor.r = (byte)(r * slot.r * meshAttachment.r * graphicColor.r * vertColor.a);					vertColor.g = (byte)(g * slot.g * meshAttachment.g * graphicColor.g * vertColor.a);					vertColor.b = (byte)(b * slot.b * meshAttachment.b * graphicColor.b * vertColor.a);					if (slot.data.blendMode == BlendMode.additive) vertColor.a = 0;					float[] meshUVs = meshAttachment.uvs;					float z = i * zSpacing;					for (int ii = 0; ii < meshVertexCount; ii += 2, vertexIndex++) {						vertices[vertexIndex].x = tempVertices[ii] * scale;						vertices[vertexIndex].y = tempVertices[ii + 1]  * scale;						vertices[vertexIndex].z = z;						colors[vertexIndex] = vertColor;						uvs[vertexIndex].x = meshUVs[ii];						uvs[vertexIndex].y = meshUVs[ii + 1];						// Calculate Bounds						if (tempVertices[ii] < meshBoundsMin.x)							meshBoundsMin.x = tempVertices[ii];						else if (tempVertices[ii] > meshBoundsMax.x)							meshBoundsMax.x = tempVertices[ii];						if (tempVertices[ii + 1]< meshBoundsMin.y)							meshBoundsMin.y = tempVertices[ii + 1];						else if (tempVertices[ii + 1] > meshBoundsMax.y)							meshBoundsMax.y = tempVertices[ii + 1];					}				} else {					var skinnedMeshAttachment = attachment as SkinnedMeshAttachment;					if (skinnedMeshAttachment != null) {						int meshVertexCount = skinnedMeshAttachment.uvs.Length;						if (tempVertices.Length < meshVertexCount)							this.tempVertices = tempVertices = new float[meshVertexCount];						skinnedMeshAttachment.ComputeWorldVertices(slot, tempVertices);						vertColor.a = (byte)(a * slot.a * skinnedMeshAttachment.a * graphicColor.a);						vertColor.r = (byte)(r * slot.r * skinnedMeshAttachment.r * graphicColor.r * vertColor.a);						vertColor.g = (byte)(g * slot.g * skinnedMeshAttachment.g * graphicColor.g * vertColor.a);						vertColor.b = (byte)(b * slot.b * skinnedMeshAttachment.b * graphicColor.b * vertColor.a);						if (slot.data.blendMode == BlendMode.additive) vertColor.a = 0;						float[] meshUVs = skinnedMeshAttachment.uvs;						float z = i * zSpacing;						for (int ii = 0; ii < meshVertexCount; ii += 2, vertexIndex++) {							vertices[vertexIndex].x = tempVertices[ii] * scale;							vertices[vertexIndex].y = tempVertices[ii + 1] * scale;							vertices[vertexIndex].z = z;							colors[vertexIndex] = vertColor;							uvs[vertexIndex].x = meshUVs[ii];							uvs[vertexIndex].y = meshUVs[ii + 1];							// Calculate Bounds							if (tempVertices[ii] < meshBoundsMin.x)								meshBoundsMin.x = tempVertices[ii];							else if (tempVertices[ii] > meshBoundsMax.x)								meshBoundsMax.x = tempVertices[ii];							if (tempVertices[ii + 1]< meshBoundsMin.y)								meshBoundsMin.y = tempVertices[ii + 1];							else if (tempVertices[ii + 1] > meshBoundsMax.y)								meshBoundsMax.y = tempVertices[ii + 1];						}					}				}			}		}		// Double buffer mesh.		Mesh mesh = useMesh1 ? mesh1 : mesh2;		// Push data from buffers.		mesh.vertices = vertices;		mesh.colors32 = colors;		mesh.uv = uvs;		// Set Mesh bounds.		Vector3 meshBoundsExtents = (meshBoundsMax - meshBoundsMin) * scale;	// scaled		Vector3 meshBoundsCenter = meshBoundsMin + meshBoundsExtents * 0.5f;		mesh.bounds = new Bounds(meshBoundsCenter, meshBoundsExtents);		//mesh.RecalculateBounds();		canvasRenderer.SetMesh(mesh);		//this.SetVerticesDirty();		if (mustUpdateMeshStructure) {			int submeshCount = submeshMaterials.Count;			mesh.subMeshCount = submeshCount;			for (int i = 0; i < submeshCount; ++i)				mesh.SetTriangles(submeshes.Items[i].triangles, i);			/*			 * TODO: Check fix with a known repro case.			if (useMesh1)				lastState.forceUpdateMesh1 = false;			else				lastState.forceUpdateMesh2 = false;			*/		}		if (newTriangles && calculateNormals) {			var normals = new Vector3[vertexCount];			var normal = new Vector3(0, 0, -1);			for (int i = 0; i < vertexCount; i++)				normals[i] = normal;			(useMesh1 ? mesh2 : mesh1).vertices = vertices; // Set other mesh vertices.			mesh1.normals = normals;			mesh2.normals = normals;			if (calculateTangents) {				var tangents = new Vector4[vertexCount];				var tangent = new Vector3(0, 0, 1);				for (int i = 0; i < vertexCount; i++)					tangents[i] = tangent;				mesh1.tangents = tangents;				mesh2.tangents = tangents;			}		}		// Update previous state		ExposedList<int> attachmentsTriangleCountCurrentMesh;		ExposedList<bool> attachmentsFlipStateCurrentMesh;		ExposedList<LastState.AddSubmeshArguments> addSubmeshArgumentsCurrentMesh;		if (useMesh1) {			attachmentsTriangleCountCurrentMesh = lastState.attachmentsTriangleCountMesh1;			addSubmeshArgumentsCurrentMesh = lastState.addSubmeshArgumentsMesh1;			attachmentsFlipStateCurrentMesh = lastState.attachmentsFlipStateMesh1;			lastState.immutableTrianglesMesh1 = immutableTriangles;		} else {			attachmentsTriangleCountCurrentMesh = lastState.attachmentsTriangleCountMesh2;			addSubmeshArgumentsCurrentMesh = lastState.addSubmeshArgumentsMesh2;			attachmentsFlipStateCurrentMesh = lastState.attachmentsFlipStateMesh2;			lastState.immutableTrianglesMesh2 = immutableTriangles;		}		attachmentsTriangleCountCurrentMesh.GrowIfNeeded(attachmentsTriangleCountTemp.Capacity);		attachmentsTriangleCountCurrentMesh.Count = attachmentsTriangleCountTemp.Count;		attachmentsTriangleCountTemp.CopyTo(attachmentsTriangleCountCurrentMesh.Items, 0);		attachmentsFlipStateCurrentMesh.GrowIfNeeded(attachmentsFlipStateTemp.Capacity);		attachmentsFlipStateCurrentMesh.Count = attachmentsFlipStateTemp.Count;		attachmentsFlipStateTemp.CopyTo(attachmentsFlipStateCurrentMesh.Items, 0);		addSubmeshArgumentsCurrentMesh.GrowIfNeeded(addSubmeshArgumentsTemp.Count);		addSubmeshArgumentsCurrentMesh.Count = addSubmeshArgumentsTemp.Count;		addSubmeshArgumentsTemp.CopyTo(addSubmeshArgumentsCurrentMesh.Items);		useMesh1 = !useMesh1;	}	protected bool CheckIfMustUpdateMeshStructure(ExposedList<int> attachmentsTriangleCountTemp, ExposedList<bool> attachmentsFlipStateTemp, ExposedList<LastState.AddSubmeshArguments> addSubmeshArgumentsTemp) {		// Check if any mesh settings were changed		bool mustUpdateMeshStructure =			immutableTriangles != (useMesh1 ? lastState.immutableTrianglesMesh1 : lastState.immutableTrianglesMesh2);		#if UNITY_EDITOR		mustUpdateMeshStructure |= !Application.isPlaying;		#endif		// TODO: Check fix with a known repro case.		//mustUpdateMeshStructure |= (useMesh1 ? lastState.forceUpdateMesh1 : lastState.forceUpdateMesh2);		if (mustUpdateMeshStructure)			return true;		// Check if any attachments were enabled/disabled		// or submesh structures has changed		ExposedList<int> attachmentsTriangleCountCurrentMesh;		ExposedList<bool> attachmentsFlipStateCurrentMesh;		ExposedList<LastState.AddSubmeshArguments> addSubmeshArgumentsCurrentMesh;		if (useMesh1) {			attachmentsTriangleCountCurrentMesh = lastState.attachmentsTriangleCountMesh1;			addSubmeshArgumentsCurrentMesh = lastState.addSubmeshArgumentsMesh1;			attachmentsFlipStateCurrentMesh = lastState.attachmentsFlipStateMesh1;		} else {			attachmentsTriangleCountCurrentMesh = lastState.attachmentsTriangleCountMesh2;			addSubmeshArgumentsCurrentMesh = lastState.addSubmeshArgumentsMesh2;			attachmentsFlipStateCurrentMesh = lastState.attachmentsFlipStateMesh2;		}		// Check attachments		int attachmentCount = attachmentsTriangleCountTemp.Count;		if (attachmentsTriangleCountCurrentMesh.Count != attachmentCount)			return true;		for (int i = 0; i < attachmentCount; i++) {			if (attachmentsTriangleCountCurrentMesh.Items[i] != attachmentsTriangleCountTemp.Items[i])				return true;		}		// Check flip state		for (int i = 0; i < attachmentCount; i++) {			if (attachmentsFlipStateCurrentMesh.Items[i] != attachmentsFlipStateTemp.Items[i])				return true;		}		// Check submeshes		int submeshCount = addSubmeshArgumentsTemp.Count;		if (addSubmeshArgumentsCurrentMesh.Count != submeshCount)			return true;		for (int i = 0; i < submeshCount; i++) {			if (!addSubmeshArgumentsCurrentMesh.Items[i].Equals(ref addSubmeshArgumentsTemp.Items[i]))				return true;		}		return false;	}	/** Stores vertices and triangles for a single material. */	void AddSubmesh (Material submeshMaterial, int startSlot, int endSlot, int triangleCount, int firstVertex, bool lastSubmesh, ExposedList<bool> flipStates) {		int submeshIndex = submeshMaterials.Count;		submeshMaterials.Add(submeshMaterial);		if (submeshes.Count <= submeshIndex)			submeshes.Add(new Submesh());		else if (immutableTriangles)			return;		Submesh submesh = submeshes.Items[submeshIndex];		int[] triangles = submesh.triangles;		int trianglesCapacity = triangles.Length;		if (lastSubmesh && trianglesCapacity > triangleCount) {			// Last submesh may have more triangles than required, so zero triangles to the end.			for (int i = triangleCount; i < trianglesCapacity; i++)				triangles[i] = 0;			submesh.triangleCount = triangleCount;		} else if (trianglesCapacity != triangleCount) {			// Reallocate triangles when not the exact size needed.			submesh.triangles = triangles = new int[triangleCount];			submesh.triangleCount = 0;		}		if (!renderMeshes && !frontFacing) {			// Use stored triangles if possible.			if (submesh.firstVertex != firstVertex || submesh.triangleCount < triangleCount) {				submesh.triangleCount = triangleCount;				submesh.firstVertex = firstVertex;				int drawOrderIndex = 0;				for (int i = 0; i < triangleCount; i += 6, firstVertex += 4, drawOrderIndex++) {					triangles[i] = firstVertex;					triangles[i + 1] = firstVertex + 2;					triangles[i + 2] = firstVertex + 1;					triangles[i + 3] = firstVertex + 2;					triangles[i + 4] = firstVertex + 3;					triangles[i + 5] = firstVertex + 1;				}			}			return;		}		// Store triangles.		ExposedList<Slot> drawOrder = skeleton.DrawOrder;		for (int i = startSlot, triangleIndex = 0; i < endSlot; i++) {			Slot slot = drawOrder.Items[i];			Attachment attachment = slot.attachment;			bool flip = flipStates.Items[i];			if (attachment is RegionAttachment) {				if (!flip) {					triangles[triangleIndex] = firstVertex;					triangles[triangleIndex + 1] = firstVertex + 2;					triangles[triangleIndex + 2] = firstVertex + 1;					triangles[triangleIndex + 3] = firstVertex + 2;					triangles[triangleIndex + 4] = firstVertex + 3;					triangles[triangleIndex + 5] = firstVertex + 1;				} else {					triangles[triangleIndex] = firstVertex + 1;					triangles[triangleIndex + 1] = firstVertex + 2;					triangles[triangleIndex + 2] = firstVertex;					triangles[triangleIndex + 3] = firstVertex + 1;					triangles[triangleIndex + 4] = firstVertex + 3;					triangles[triangleIndex + 5] = firstVertex + 2;				}				triangleIndex += 6;				firstVertex += 4;				continue;			}			int[] attachmentTriangles;			int attachmentVertexCount;			var meshAttachment = attachment as MeshAttachment;			if (meshAttachment != null) {				attachmentVertexCount = meshAttachment.vertices.Length >> 1;				attachmentTriangles = meshAttachment.triangles;			} else {				var skinnedMeshAttachment = attachment as SkinnedMeshAttachment;				if (skinnedMeshAttachment != null) {					attachmentVertexCount = skinnedMeshAttachment.uvs.Length >> 1;					attachmentTriangles = skinnedMeshAttachment.triangles;				} else					continue;			}			if (flip) {				for (int ii = 0, nn = attachmentTriangles.Length; ii < nn; ii += 3, triangleIndex += 3) {					triangles[triangleIndex + 2] = firstVertex + attachmentTriangles[ii];					triangles[triangleIndex + 1] = firstVertex + attachmentTriangles[ii + 1];					triangles[triangleIndex] = firstVertex + attachmentTriangles[ii + 2];				}			} else {				for (int ii = 0, nn = attachmentTriangles.Length; ii < nn; ii++, triangleIndex++) {					triangles[triangleIndex] = firstVertex + attachmentTriangles[ii];				}			}			firstVertex += attachmentVertexCount;		}	}	public class LastState {		public bool immutableTrianglesMesh1;		public bool immutableTrianglesMesh2;		//public bool forceUpdateMesh1, forceUpdateMesh2; // TODO: Check fix with a known repro case.		public int vertexCount;		public readonly ExposedList<bool> attachmentsFlipStateTemp = new ExposedList<bool>();		public readonly ExposedList<bool> attachmentsFlipStateMesh1 = new ExposedList<bool>();		public readonly ExposedList<bool> attachmentsFlipStateMesh2 = new ExposedList<bool>();		public readonly ExposedList<int> attachmentsTriangleCountTemp = new ExposedList<int>();		public readonly ExposedList<int> attachmentsTriangleCountMesh1 = new ExposedList<int>();		public readonly ExposedList<int> attachmentsTriangleCountMesh2 = new ExposedList<int>();		public readonly ExposedList<AddSubmeshArguments> addSubmeshArgumentsTemp = new ExposedList<AddSubmeshArguments>();		public readonly ExposedList<AddSubmeshArguments> addSubmeshArgumentsMesh1 = new ExposedList<AddSubmeshArguments>();		public readonly ExposedList<AddSubmeshArguments> addSubmeshArgumentsMesh2 = new ExposedList<AddSubmeshArguments>();		public struct AddSubmeshArguments {			public Material material;			public int startSlot;			public int endSlot;			public int triangleCount;			public int firstVertex;			public bool lastSubmesh;			public AddSubmeshArguments(Material material, int startSlot, int endSlot, int triangleCount, int firstVertex, bool lastSubmesh) {				this.material = material;				this.startSlot = startSlot;				this.endSlot = endSlot;				this.triangleCount = triangleCount;				this.firstVertex = firstVertex;				this.lastSubmesh = lastSubmesh;			}			public bool Equals (ref AddSubmeshArguments other) {				return					!ReferenceEquals(material, null) &&					!ReferenceEquals(other.material, null) &&					material.GetInstanceID() == other.material.GetInstanceID() &&					startSlot == other.startSlot && 					endSlot == other.endSlot && 					triangleCount == other.triangleCount && 					firstVertex == other.firstVertex;			}		}	}	#endregion}


Shader "Spine/SkeletonGraphic" {	Properties {		_MainTex ("Main Texture", 2D) = "black" {}	}		SubShader {		Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }		LOD 100		Cull Off		ZWrite Off		Blend One OneMinusSrcAlpha		Lighting Off		Stencil {			Ref 1			Comp Equal		}		Pass {			ColorMaterial AmbientAndDiffuse			SetTexture [_MainTex] {				Combine texture * primary			}		}	}}



完全跟 UI 元素一样, UIMask 是起到作用的等

使用:World Space

计算机生成了可选文字:ıe•ğ


Screen Space -Camera

计算机生成了可选文字:


Screen Space -OVerlay

计算机生成了可选文字:




转载地址:http://egoa.baihongyu.com/

你可能感兴趣的文章
MySQL 用户权限管理:授权、撤销、密码更新和用户删除(图文解析)
查看>>
mysql 用户管理和权限设置
查看>>
MySQL 的 varchar 水真的太深了!
查看>>
mysql 的GROUP_CONCAT函数的使用(group_by 如何显示分组之前的数据)
查看>>
MySQL 的instr函数
查看>>
MySQL 的mysql_secure_installation安全脚本执行过程介绍
查看>>
MySQL 的Rename Table语句
查看>>
MySQL 的全局锁、表锁和行锁
查看>>
mysql 的存储引擎介绍
查看>>
MySQL 的存储引擎有哪些?为什么常用InnoDB?
查看>>
Mysql 知识回顾总结-索引
查看>>
Mysql 笔记
查看>>
MySQL 精选 60 道面试题(含答案)
查看>>
mysql 索引
查看>>
MySQL 索引失效的 15 种场景!
查看>>
MySQL 索引深入解析及优化策略
查看>>
MySQL 索引的面试题总结
查看>>
mysql 索引类型以及创建
查看>>
MySQL 索引连环问题,你能答对几个?
查看>>
Mysql 索引问题集锦
查看>>