using System.Collections; using System.Collections.Generic; using UnityEngine; /// /// 可交互脚本 /// public class HighLight_VR : MonoBehaviour { [ContextMenu("Highlight")] public void Highlight() { Init(); wasHovering = isHovering; isHovering = true; if (highlightOnHover == true && wasHovering == false) { CreateHighlightRenderers(); UpdateHighlightRenderers(); } } [ContextMenu("ShutDownHighlight")] public void ShutDownHighlight() { wasHovering = isHovering; isHovering = false; if (highlightOnHover && highlightHolder != null) Destroy(highlightHolder); } public void OnMouseEnter() { wasHovering = isHovering; isHovering = true; if (highlightOnHover == true && wasHovering == false) { CreateHighlightRenderers(); UpdateHighlightRenderers(); } } public void OnMouseExit() { wasHovering = isHovering; isHovering = false; if (highlightOnHover && highlightHolder != null) Destroy(highlightHolder); } public bool highlightOnHover = true; protected MeshRenderer[] highlightRenderers; protected MeshRenderer[] existingRenderers; protected GameObject highlightHolder; protected SkinnedMeshRenderer[] highlightSkinnedRenderers; protected SkinnedMeshRenderer[] existingSkinnedRenderers; protected static Material highlightMat; public GameObject[] hideHighlight; public bool isDestroying { get; protected set; } public bool isHovering { get; protected set; } public bool wasHovering { get; protected set; } protected virtual bool ShouldIgnoreHighlight(Component component) { return ShouldIgnore(component.gameObject); } protected virtual bool ShouldIgnore(GameObject check) { if (hideHighlight == null) return false; for (int ignoreIndex = 0; ignoreIndex < hideHighlight.Length; ignoreIndex++) { if (hideHighlight != null && check == hideHighlight[ignoreIndex]) return true; } return false; } bool inited = false; private void Init() { if (!inited) { inited = true; highlightMat = (Material)Resources.Load("SteamVR_HoverHighlight", typeof(Material)); if (highlightMat == null) Debug.LogError("[SteamVR Interaction] Hover Highlight Material is missing. Please create a material named 'SteamVR_HoverHighlight' and place it in a Resources folder", this); } } protected virtual void Start() { Init(); } protected virtual void CreateHighlightRenderers() { existingSkinnedRenderers = this.GetComponentsInChildren(true); highlightHolder = new GameObject("Highlighter"); highlightSkinnedRenderers = new SkinnedMeshRenderer[existingSkinnedRenderers.Length]; for (int skinnedIndex = 0; skinnedIndex < existingSkinnedRenderers.Length; skinnedIndex++) { SkinnedMeshRenderer existingSkinned = existingSkinnedRenderers[skinnedIndex]; if (ShouldIgnoreHighlight(existingSkinned)) continue; GameObject newSkinnedHolder = new GameObject("SkinnedHolder"); newSkinnedHolder.transform.parent = highlightHolder.transform; SkinnedMeshRenderer newSkinned = newSkinnedHolder.AddComponent(); Material[] materials = new Material[existingSkinned.sharedMaterials.Length]; for (int materialIndex = 0; materialIndex < materials.Length; materialIndex++) { materials[materialIndex] = highlightMat; } newSkinned.sharedMaterials = materials; newSkinned.sharedMesh = existingSkinned.sharedMesh; newSkinned.rootBone = existingSkinned.rootBone; newSkinned.updateWhenOffscreen = existingSkinned.updateWhenOffscreen; newSkinned.bones = existingSkinned.bones; highlightSkinnedRenderers[skinnedIndex] = newSkinned; } MeshFilter[] existingFilters = this.GetComponentsInChildren(true); existingRenderers = new MeshRenderer[existingFilters.Length]; highlightRenderers = new MeshRenderer[existingFilters.Length]; for (int filterIndex = 0; filterIndex < existingFilters.Length; filterIndex++) { MeshFilter existingFilter = existingFilters[filterIndex]; MeshRenderer existingRenderer = existingFilter.GetComponent(); if (existingFilter == null || existingRenderer == null || ShouldIgnoreHighlight(existingFilter)) continue; GameObject newFilterHolder = new GameObject("FilterHolder"); newFilterHolder.transform.parent = highlightHolder.transform; MeshFilter newFilter = newFilterHolder.AddComponent(); newFilter.sharedMesh = existingFilter.sharedMesh; MeshRenderer newRenderer = newFilterHolder.AddComponent(); Material[] materials = new Material[existingRenderer.sharedMaterials.Length]; for (int materialIndex = 0; materialIndex < materials.Length; materialIndex++) { materials[materialIndex] = highlightMat; } newRenderer.sharedMaterials = materials; highlightRenderers[filterIndex] = newRenderer; existingRenderers[filterIndex] = existingRenderer; } } protected virtual void UpdateHighlightRenderers() { if (highlightHolder == null) return; for (int skinnedIndex = 0; skinnedIndex < existingSkinnedRenderers.Length; skinnedIndex++) { SkinnedMeshRenderer existingSkinned = existingSkinnedRenderers[skinnedIndex]; SkinnedMeshRenderer highlightSkinned = highlightSkinnedRenderers[skinnedIndex]; if (existingSkinned != null && highlightSkinned != null /*&& attachedToHand == false*/) { highlightSkinned.transform.position = existingSkinned.transform.position; highlightSkinned.transform.rotation = existingSkinned.transform.rotation; highlightSkinned.transform.localScale = existingSkinned.transform.lossyScale; highlightSkinned.localBounds = existingSkinned.localBounds; highlightSkinned.enabled = isHovering && existingSkinned.enabled && existingSkinned.gameObject.activeInHierarchy; int blendShapeCount = existingSkinned.sharedMesh.blendShapeCount; for (int blendShapeIndex = 0; blendShapeIndex < blendShapeCount; blendShapeIndex++) { highlightSkinned.SetBlendShapeWeight(blendShapeIndex, existingSkinned.GetBlendShapeWeight(blendShapeIndex)); } } else if (highlightSkinned != null) highlightSkinned.enabled = false; } for (int rendererIndex = 0; rendererIndex < highlightRenderers.Length; rendererIndex++) { MeshRenderer existingRenderer = existingRenderers[rendererIndex]; MeshRenderer highlightRenderer = highlightRenderers[rendererIndex]; if (existingRenderer != null && highlightRenderer != null /*&& attachedToHand == false*/) { highlightRenderer.transform.position = existingRenderer.transform.position; highlightRenderer.transform.rotation = existingRenderer.transform.rotation; highlightRenderer.transform.localScale = existingRenderer.transform.lossyScale; highlightRenderer.enabled = isHovering && existingRenderer.enabled && existingRenderer.gameObject.activeInHierarchy; } else if (highlightRenderer != null) highlightRenderer.enabled = false; } } }