实现物体自发光特效

实现物体自发光特效


一、如何实现物体自发光特效

导入HightLightingSystem插件,将HightLightingEffect脚本挂到场景摄像机上上,将HightLightableObject脚本挂到需要发光的物体上,新建一个脚本,代码引用发光特效。

二、使用步骤

1.HightLightingEffect

using UnityEngine;

// Delegate for the highlighting event
public delegate void HighlightingEventHandler(bool state, bool zWrite);

[RequireComponent(typeof(Camera))]
public class HighlightingEffect : MonoBehaviour
{
    // Event used to notify highlightable objects to change their materials before rendering to the highlighting buffer begins
    public static event HighlightingEventHandler highlightingEvent;

    #region Inspector Fields
    // Stencil (highlighting) buffer depth
    public int stencilZBufferDepth = 0;

    // Stencil (highlighting) buffer size downsample factor
    public int _downsampleFactor = 4;

    // Blur iterations
    public int iterations = 2;

    // Blur minimal spread
    public float blurMinSpread = 0.65f;

    // Blur spread per iteration
    public float blurSpread = 0.25f;

    // Blurring intensity for the blur material
    public float _blurIntensity = 0.3f;

    // These properties available only in Editor - we don't need them in standalone build
#if UNITY_EDITOR
    // Z-buffer writing state getter/setter
    public bool stencilZBufferEnabled
    {
        get
        {
            return (stencilZBufferDepth > 0);
        }
        set
        {
            if (stencilZBufferEnabled != value)
            {
                stencilZBufferDepth = value ? 16 : 0;
            }
        }
    }

    // Downsampling factor getter/setter
    public int downsampleFactor
    {
        get
        {
            if (_downsampleFactor == 1)
            {
                return 0;
            }
            if (_downsampleFactor == 2)
            {
                return 1;
            }
            return 2;
        }
        set
        {
            if (value == 0)
            {
                _downsampleFactor = 1;
            }
            if (value == 1)
            {
                _downsampleFactor = 2;
            }
            if (value == 2)
            {
                _downsampleFactor = 4;
            }
        }
    }

    // Blur alpha intensity getter/setter
    public float blurIntensity
    {
        get
        {
            return _blurIntensity;
        }
        set
        {
            if (_blurIntensity != value)
            {
                _blurIntensity = value;
                if (Application.isPlaying)
                {
                    blurMaterial.SetFloat("_Intensity", _blurIntensity);
                }
            }
        }
    }
#endif
    #endregion

    #region Private Fields
    // Highlighting camera layers culling mask
    private int layerMask = (1 << HighlightableObject.highlightingLayer);

    // This GameObject reference
    private GameObject go = null;

    // Camera for rendering stencil buffer GameObject
    private GameObject shaderCameraGO = null;

    // Camera for rendering stencil buffer
    private Camera shaderCamera = null;

    // RenderTexture with stencil buffer
    private RenderTexture stencilBuffer = null;

    // Camera reference
    private Camera refCam = null;

    // Blur Shader
    private static Shader _blurShader;
    private static Shader blurShader
    {
        get
        {
            if (_blurShader == null)
            {
                _blurShader = Shader.Find("Hidden/Highlighted/Blur");
            }
            return _blurShader;
        }
    }

    // Compositing Shader
    private static Shader _compShader;
    private static Shader compShader
    {
        get
        {
            if (_compShader == null)
            {
                _compShader = Shader.Find("Hidden/Highlighted/Composite");
            }
            return _compShader;
        }
    }

    // Blur Material
    private static Material _blurMaterial = null;
    private static Material blurMaterial
    {
        get
        {
            if (_blurMaterial == null)
            {
                _blurMaterial = new Material(blurShader);
                _blurMaterial.hideFlags = HideFlags.HideAndDontSave;
            }
            return _blurMaterial;
        }
    }

    // Compositing Material
    private static Material _compMaterial = null;
    private static Material compMaterial
    {
        get
        {
            if (_compMaterial == null)
            {
                _compMaterial = new Material(compShader);
                _compMaterial.hideFlags = HideFlags.HideAndDontSave;
            }
            return _compMaterial;
        }
    }
    #endregion


    void Awake()
    {
        go = gameObject;
        refCam = GetComponent<Camera>();
    }

    void OnDisable()
    {
        if (shaderCameraGO != null)
        {
            DestroyImmediate(shaderCameraGO);
        }

        if (_blurShader)
        {
            _blurShader = null;
        }

        if (_compShader)
        {
            _compShader = null;
        }

        if (_blurMaterial)
        {
            DestroyImmediate(_blurMaterial);
        }

        if (_compMaterial)
        {
            DestroyImmediate(_compMaterial);
        }

        if (stencilBuffer != null)
        {
            RenderTexture.ReleaseTemporary(stencilBuffer);
            stencilBuffer = null;
        }
    }

    void Start()
    {
        // Disable if Image Effects is not supported
        if (!SystemInfo.supportsImageEffects)
        {
            Debug.LogWarning("HighlightingSystem : Image effects is not supported on this platform! Disabling.");
            this.enabled = false;
            return;
        }

        // Disable if Render Textures is not supported
        if (!SystemInfo.supportsRenderTextures)
        {
            Debug.LogWarning("HighlightingSystem : RenderTextures is not supported on this platform! Disabling.");
            this.enabled = false;
            return;
        }

        // Disable if required Render Texture Format is not supported
        if (!SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGB32))
        {
            Debug.LogWarning("HighlightingSystem : RenderTextureFormat.ARGB32 is not supported on this platform! Disabling.");
            this.enabled = false;
            return;
        }

        // Disable if HighlightingStencilOpaque shader is not supported
        if (!Shader.Find("Hidden/Highlighted/StencilOpaque").isSupported)
        {
            Debug.LogWarning("HighlightingSystem : HighlightingStencilOpaque shader is not supported on this platform! Disabling.");
            this.enabled = false;
            return;
        }

        // Disable if HighlightingStencilTransparent shader is not supported
        if (!Shader.Find("Hidden/Highlighted/StencilTransparent").isSupported)
        {
            Debug.LogWarning("HighlightingSystem : HighlightingStencilTransparent shader is not supported on this platform! Disabling.");
            this.enabled = false;
            return;
        }

        // Disable if HighlightingStencilOpaqueZ shader is not supported
        if (!Shader.Find("Hidden/Highlighted/StencilOpaqueZ").isSupported)
        {
            Debug.LogWarning("HighlightingSystem : HighlightingStencilOpaqueZ shader is not supported on this platform! Disabling.");
            this.enabled = false;
            return;
        }

        // Disable if HighlightingStencilTransparentZ shader is not supported
        if (!Shader.Find("Hidden/Highlighted/StencilTransparentZ").isSupported)
        {
            Debug.LogWarning("HighlightingSystem : HighlightingStencilTransparentZ shader is not supported on this platform! Disabling.");
            this.enabled = false;
            return;
        }

        // Disable if HighlightingBlur shader is not supported
        if (!blurShader.isSupported)
        {
            Debug.LogWarning("HighlightingSystem : HighlightingBlur shader is not supported on this platform! Disabling.");
            this.enabled = false;
            return;
        }

        // Disable if HighlightingComposite shader is not supported
        if (!compShader.isSupported)
        {
            Debug.LogWarning("HighlightingSystem : HighlightingComposite shader is not supported on this platform! Disabling.");
            this.enabled = false;
            return;
        }

        // Set the initial intensity in blur shader
        blurMaterial.SetFloat("_Intensity", _blurIntensity);
    }

    // Performs one blur iteration
    public void FourTapCone(RenderTexture source, RenderTexture dest, int iteration)
    {
        float off = blurMinSpread + iteration * blurSpread;
        blurMaterial.SetFloat("_OffsetScale", off);
        Graphics.Blit(source, dest, blurMaterial);
    }

    // Downsamples source texture
    private void DownSample4x(RenderTexture source, RenderTexture dest)
    {
        float off = 1.0f;
        blurMaterial.SetFloat("_OffsetScale", off);
        Graphics.Blit(source, dest, blurMaterial);
    }

    // Render all highlighted objects to the stencil buffer
    void OnPreRender()
    {
#if UNITY_4_0
		if (this.enabled == false || go.activeInHierarchy == false)
#else
        if (this.enabled == false || go.active == false)
#endif
            return;

        if (stencilBuffer != null)
        {
            RenderTexture.ReleaseTemporary(stencilBuffer);
            stencilBuffer = null;
        }

        // Turn on highlighted shaders
        if (highlightingEvent != null)
        {
            highlightingEvent(true, (stencilZBufferDepth > 0));
        }
        // We don't need to render the scene if there's no HighlightableObjects
        else
        {
            return;
        }

        stencilBuffer = RenderTexture.GetTemporary((int)GetComponent<Camera>().pixelWidth, (int)GetComponent<Camera>().pixelHeight, stencilZBufferDepth, RenderTextureFormat.ARGB32);

        if (!shaderCameraGO)
        {
            shaderCameraGO = new GameObject("HighlightingCamera", typeof(Camera));
            shaderCameraGO.GetComponent<Camera>().enabled = false;
            shaderCameraGO.hideFlags = HideFlags.HideAndDontSave;
        }

        if (!shaderCamera)
        {
            shaderCamera = shaderCameraGO.GetComponent<Camera>();
        }

        shaderCamera.CopyFrom(refCam);
        //shaderCamera.projectionMatrix = refCam.projectionMatrix;		// Uncomment this line if you have problems using Highlighting System with custom projection matrix on your camera
        shaderCamera.cullingMask = layerMask;
        shaderCamera.rect = new Rect(0f, 0f, 1f, 1f);
        shaderCamera.renderingPath = RenderingPath.VertexLit;
        shaderCamera.allowHDR = false;
        shaderCamera.useOcclusionCulling = false;
        shaderCamera.backgroundColor = new Color(0f, 0f, 0f, 0f);
        shaderCamera.clearFlags = CameraClearFlags.SolidColor;
        shaderCamera.targetTexture = stencilBuffer;
        shaderCamera.Render();

        // Turn off highlighted shaders
        if (highlightingEvent != null)
        {
            highlightingEvent(false, false);
        }
    }

    // Compose final frame with highlighting
    void OnRenderImage(RenderTexture source, RenderTexture destination)
    {
        // If stencilBuffer is not created by some reason
        if (stencilBuffer == null)
        {
            // Simply transfer framebuffer to destination
            Graphics.Blit(source, destination);
            return;
        }

        // Create two buffers for blurring the image
        int width = source.width / _downsampleFactor;
        int height = source.height / _downsampleFactor;
        RenderTexture buffer = RenderTexture.GetTemporary(width, height, stencilZBufferDepth, RenderTextureFormat.ARGB32);
        RenderTexture buffer2 = RenderTexture.GetTemporary(width, height, stencilZBufferDepth, RenderTextureFormat.ARGB32);

        // Copy stencil buffer to the 4x4 smaller texture
        DownSample4x(stencilBuffer, buffer);

        // Blur the small texture
        bool oddEven = true;
        for (int i = 0; i < iterations; i++)
        {
            if (oddEven)
            {
                FourTapCone(buffer, buffer2, i);
            }
            else
            {
                FourTapCone(buffer2, buffer, i);
            }

            oddEven = !oddEven;
        }

        // Compose
        compMaterial.SetTexture("_StencilTex", stencilBuffer);
        compMaterial.SetTexture("_BlurTex", oddEven ? buffer : buffer2);
        Graphics.Blit(source, destination, compMaterial);

        // Cleanup
        RenderTexture.ReleaseTemporary(buffer);
        RenderTexture.ReleaseTemporary(buffer2);
        if (stencilBuffer != null)
        {
            RenderTexture.ReleaseTemporary(stencilBuffer);
            stencilBuffer = null;
        }
    }
}

2.HightLightableObject

代码如下(示例):

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class HighlightableObject : MonoBehaviour
{
	#region Editable Fields
	// Builtin layer reserved for the highlighting
	public static int highlightingLayer = 7;
	
	// Constant highlighting turning on speed
	private static float constantOnSpeed = 4.5f;
	
	// Constant highlighting turning off speed
	private static float constantOffSpeed = 4f;
	
	// Default transparent cutoff value used for shaders without _Cutoff property
	private static float transparentCutoff = 0.5f;
	#endregion
	
	#region Private Fields
	// 2 * PI constant required for flashing
	private const float doublePI = 2f * Mathf.PI;
	
	// Cached materials
	private List<HighlightingRendererCache> highlightableRenderers;
	
	// Cached layers of highlightable objects
	private int[] layersCache;
	
	// Need to reinit materials flag
	private bool materialsIsDirty = true;
	
	// Current state of highlighting
	private bool currentState = false;
	
	// Current materials highlighting color
	private Color currentColor;
	
	// Transition is active flag
	private bool transitionActive = false;
	
	// Current transition value
	private float transitionValue = 0f;
	
	// Flashing frequency
	private float flashingFreq = 2f;
	
	// One-frame highlighting flag
	private bool once = false;
	
	// One-frame highlighting color
	private Color onceColor = Color.red;
	
	// Flashing state flag
	private bool flashing = false;
	
	// Flashing from color
	private Color flashingColorMin = new Color(0.0f, 1.0f, 1.0f, 0.0f);
	
	// Flashing to color
	private Color flashingColorMax = new Color(0.0f, 1.0f, 1.0f, 1.0f);
	
	// Constant highlighting state flag
	private bool constantly = false;
	
	// Constant highlighting color
	private Color constantColor = Color.yellow;
	
	// Occluder
	private bool occluder = false;
	
	// Currently used shaders ZWriting state
	private bool zWrite = false;
	
	// Occlusion color (DON'T TOUCH THIS!)
	private readonly Color occluderColor = new Color(0.0f, 0.0f, 0.0f, 0.005f);
	
	// 
	private Material highlightingMaterial
	{
		get
		{
			return zWrite ? opaqueZMaterial : opaqueMaterial;
		}
	}
		
	// Common (for this component) replacement material for opaque geometry highlighting
	private Material _opaqueMaterial;
	private Material opaqueMaterial
	{
		get
		{
			if (_opaqueMaterial == null)
			{
				_opaqueMaterial = new Material(opaqueShader);
				_opaqueMaterial.hideFlags = HideFlags.HideAndDontSave;
			}
			return _opaqueMaterial;
		}
	}
	
	// Common (for this component) replacement material for opaque geometry highlighting with Z-Buffer writing enabled
	private Material _opaqueZMaterial;
	private Material opaqueZMaterial
	{
		get
		{
			if (_opaqueZMaterial == null)
			{
				_opaqueZMaterial = new Material(opaqueZShader);
				_opaqueZMaterial.hideFlags = HideFlags.HideAndDontSave;
			}
			return _opaqueZMaterial;
		}
	}
	
	// 
	private static Shader _opaqueShader;
	private static Shader opaqueShader
	{
		get
		{
			if (_opaqueShader == null)
			{
				_opaqueShader = Shader.Find("Hidden/Highlighted/StencilOpaque");
			}
			return _opaqueShader;
		}
	}
	
	// 
	private static Shader _transparentShader;
	public static Shader transparentShader
	{
		get
		{
			if (_transparentShader == null)
			{
				_transparentShader = Shader.Find("Hidden/Highlighted/StencilTransparent");
			}
			return _transparentShader;
		}
	}
	
	// 
	private static Shader _opaqueZShader;
	private static Shader opaqueZShader
	{
		get
		{
			if (_opaqueZShader == null)
			{
				_opaqueZShader = Shader.Find("Hidden/Highlighted/StencilOpaqueZ");
			}
			return _opaqueZShader;
		}
	}
	
	// 
	private static Shader _transparentZShader;
	private static Shader transparentZShader
	{
		get
		{
			if (_transparentZShader == null)
			{
				_transparentZShader = Shader.Find("Hidden/Highlighted/StencilTransparentZ");
			}
			return _transparentZShader;
		}
	}
	#endregion
	
	#region Common
	// Internal class for renderers caching
	private class HighlightingRendererCache
	{
		public Renderer rendererCached;
		public GameObject goCached;
		private Material[] sourceMaterials;
		private Material[] replacementMaterials;
		private List<int> transparentMaterialIndexes;
		
		// Constructor
		public HighlightingRendererCache(Renderer rend, Material[] mats, Material sharedOpaqueMaterial, bool writeDepth)
		{
			rendererCached = rend;
			goCached = rend.gameObject;
			sourceMaterials = mats;
			replacementMaterials = new Material[mats.Length];
			transparentMaterialIndexes = new List<int>();
			
			for (int i = 0; i < mats.Length; i++)
			{
				Material sourceMat = mats[i];
				if (sourceMat == null)
				{
					continue;
				}
				string tag = sourceMat.GetTag("RenderType", true);
				if (tag == "Transparent" || tag == "TransparentCutout")
				{
					Material replacementMat = new Material(writeDepth ? transparentZShader : transparentShader);
					if (sourceMat.HasProperty("_MainTex"))
					{
						replacementMat.SetTexture("_MainTex", sourceMat.mainTexture);
						replacementMat.SetTextureOffset("_MainTex", sourceMat.mainTextureOffset);
						replacementMat.SetTextureScale("_MainTex", sourceMat.mainTextureScale);
					}
					
					replacementMat.SetFloat("_Cutoff", sourceMat.HasProperty("_Cutoff") ? sourceMat.GetFloat("_Cutoff") : transparentCutoff);
					
					replacementMaterials[i] = replacementMat;
					transparentMaterialIndexes.Add(i);
				}
				else
				{
					replacementMaterials[i] = sharedOpaqueMaterial;
				}
			}
		}
		
		// Based on given state variable, replaces materials of this cached renderer to the highlighted ones and back
		public void SetState(bool state)
		{
			rendererCached.sharedMaterials = state ? replacementMaterials : sourceMaterials;
		}
		
		// Sets given color as the highlighting color on all transparent materials for this cached renderer
		public void SetColorForTransparent(Color clr)
		{
			for (int i = 0; i < transparentMaterialIndexes.Count; i++)
			{
				replacementMaterials[transparentMaterialIndexes[i]].SetColor("_Outline", clr);
			}
		}
	}
	
	// 
	private void OnEnable()
	{
		StartCoroutine(EndOfFrame());
		// Subscribe to highlighting event
		HighlightingEffect.highlightingEvent += UpdateEventHandler;
	}
	
	// 
	private void OnDisable()
	{
		StopAllCoroutines();
		// Unsubscribe from highlighting event
		HighlightingEffect.highlightingEvent -= UpdateEventHandler;
		
		// Clear cached renderers
		if (highlightableRenderers != null)
		{
			highlightableRenderers.Clear();
		}
		
		// Reset highlighting parameters to default values
		layersCache = null;
		materialsIsDirty = true;
		currentState = false;
		currentColor = Color.clear;
		transitionActive = false;
		transitionValue = 0f;
		once = false;
		flashing = false;
		constantly = false;
		occluder = false;
		zWrite = false;
		
		/* 
		// Reset custom parameters of the highlighting
		onceColor = Color.red;
		flashingColorMin = new Color(0f, 1f, 1f, 0f);
		flashingColorMax = new Color(0f, 1f, 1f, 1f);
		flashingFreq = 2f;
		constantColor = Color.yellow;
		*/
		
		if (_opaqueMaterial)
		{
			DestroyImmediate(_opaqueMaterial);
		}
		
		if (_opaqueZMaterial)
		{
			DestroyImmediate(_opaqueZMaterial);
		}
	}
	#endregion
	
	#region Public Methods
	/// <summary>
	/// Materials reinitialization. 
	/// Call this method if your highlighted object changed his materials or child objects.
	/// Can be called multiple times per update - renderers reinitialization will occur only once.
	/// </summary>
	public void ReinitMaterials()
	{
		materialsIsDirty = true;
	}
	
	/// <summary>
	/// Immediately restore original materials. Obsolete. Use ReinitMaterials() instead.
	/// </summary>
	public void RestoreMaterials()
	{
		Debug.LogWarning("HighlightingSystem : RestoreMaterials() is obsolete. Please use ReinitMaterials() instead.");
		ReinitMaterials();
	}
	
	/// <summary>
	/// Set color for one-frame highlighting mode.
	/// </summary>
	/// <param name='color'>
	/// Highlighting color.
	/// </param>
	public void OnParams(Color color)
	{
		onceColor = color;
	}
	
	/// <summary>
	/// Turn on one-frame highlighting.
	/// </summary>
	public void On()
	{
		// Highlight object only in this frame
		once = true;
	}
	
	/// <summary>
	/// Turn on one-frame highlighting with given color.
	/// Can be called multiple times per update, color only from the latest call will be used.
	/// </summary>
	/// <param name='color'>
	/// Highlighting color.
	/// </param>
	public void On(Color color)
	{
		// Set new color for one-frame highlighting
		onceColor = color;
		On();
	}
	
	/// <summary>
	/// Set flashing parameters.
	/// </summary>
	/// <param name='color1'>
	/// Starting color.
	/// </param>
	/// <param name='color2'>
	/// Ending color.
	/// </param>
	/// <param name='freq'>
	/// Flashing frequency.
	/// </param>
	public void FlashingParams(Color color1, Color color2, float freq)
	{
		flashingColorMin = color1;
		flashingColorMax = color2;
		flashingFreq = freq;
	}
	
	/// <summary>
	/// Turn on flashing.
	/// </summary>
	public void FlashingOn()
	{
		flashing = true;
	}
	
	/// <summary>
	/// Turn on flashing from color1 to color2.
	/// </summary>
	/// <param name='color1'>
	/// Starting color.
	/// </param>
	/// <param name='color2'>
	/// Ending color.
	/// </param>
	public void FlashingOn(Color color1, Color color2)
	{
		flashingColorMin = color1;
		flashingColorMax = color2;
		FlashingOn();
	}
	
	/// <summary>
	/// Turn on flashing from color1 to color2 with given frequency.
	/// </summary>
	/// <param name='color1'>
	/// Starting color.
	/// </param>
	/// <param name='color2'>
	/// Ending color.
	/// </param>
	/// <param name='freq'>
	/// Flashing frequency.
	/// </param>
	public void FlashingOn(Color color1, Color color2, float freq)
	{
		flashingFreq = freq;
		FlashingOn(color1, color2);
	}
	
	/// <summary>
	/// Turn on flashing with given frequency.
	/// </summary>
	/// <param name='f'>
	/// Flashing frequency.
	/// </param>
	public void FlashingOn(float freq)
	{
		flashingFreq = freq;
		FlashingOn();
	}
	
	/// <summary>
	/// Turn off flashing.
	/// </summary>
	public void FlashingOff()
	{
		flashing = false;
	}
	
	/// <summary>
	/// Switch flashing mode.
	/// </summary>
	public void FlashingSwitch()
	{
		flashing = !flashing;
	}
	
	/// <summary>
	/// Set constant highlighting color.
	/// </summary>
	/// <param name='color'>
	/// Constant highlighting color.
	/// </param>
	public void ConstantParams(Color color)
	{
		constantColor = color;
	}
	
	/// <summary>
	/// Fade in constant highlighting.
	/// </summary>
	public void ConstantOn()
	{
		// Enable constant highlighting
		constantly = true;
		// Start transition
		transitionActive = true;
	}
	
	/// <summary>
	/// Fade in constant highlighting with given color.
	/// </summary>
	/// <param name='color'>
	/// Constant highlighting color.
	/// </param>
	public void ConstantOn(Color color)
	{
		// Set constant highlighting color
		constantColor = color;
		ConstantOn();
	}
	
	/// <summary>
	/// Fade out constant highlighting.
	/// </summary>
	public void ConstantOff()
	{
		// Disable constant highlighting
		constantly = false;
		// Start transition
		transitionActive = true;
	}
	
	/// <summary>
	/// Switch Constant Highlighting.
	/// </summary>
	public void ConstantSwitch()
	{
		// Switch constant highlighting
		constantly = !constantly;
		// Start transition
		transitionActive = true;
	}
	
	/// <summary>
	/// Turn on constant highlighting immediately (without fading in).
	/// </summary>
	public void ConstantOnImmediate()
	{
		constantly = true;
		// Set transition value to 1
		transitionValue = 1f;
		// Stop transition
		transitionActive = false;
	}
	
	/// <summary>
	/// Turn on constant highlighting with given color immediately (without fading in).
	/// </summary>
	/// <param name='color'>
	/// Constant highlighting color.
	/// </param>
	public void ConstantOnImmediate(Color color)
	{
		// Set constant highlighting color
		constantColor = color;
		ConstantOnImmediate();
	}
	
	/// <summary>
	/// Turn off constant highlighting immediately (without fading out).
	/// </summary>
	public void ConstantOffImmediate()
	{
		constantly = false;
		// Set transition value to 0
		transitionValue = 0f;
		// Stop transition
		transitionActive = false;
	}
	
	/// <summary>
	/// Switch constant highlighting immediately (without fading in/out).
	/// </summary>
	public void ConstantSwitchImmediate()
	{
		constantly = !constantly;
		// Set transition value to the final value
		transitionValue = constantly ? 1f : 0f;
		// Stop transition
		transitionActive = false;
	}
	
	/// <summary>
	/// Enable occluder mode
	/// </summary>
	public void OccluderOn()
	{
		occluder = true;
	}
	
	/// <summary>
	/// Disable occluder mode
	/// </summary>
	public void OccluderOff()
	{
		occluder = false;
	}
	
	/// <summary>
	/// Switch occluder mode
	/// </summary>
	public void OccluderSwitch()
	{
		occluder = !occluder;
	}
	
	/// <summary>
	/// Turn off all types of highlighting. 
	/// </summary>
	public void Off()
	{
		// Turn off all types of highlighting
		once = false;
		flashing = false;
		constantly = false;
		// Set transition value to 0
		transitionValue = 0f;
		// Stop transition
		transitionActive = false;
	}
	
	/// <summary>
	/// Destroy this HighlightableObject component.
	/// </summary>
	public void Die()
	{
		Destroy(this);
	}
	#endregion
	
	
	#region Private Methods
	// Materials initialisation
	private void InitMaterials(bool writeDepth)
	{
		currentState = false;
		
		zWrite = writeDepth;
		
		highlightableRenderers = new List<HighlightingRendererCache>();
		
		MeshRenderer[] mr = GetComponentsInChildren<MeshRenderer>();
		CacheRenderers(mr);
		
		SkinnedMeshRenderer[] smr = GetComponentsInChildren<SkinnedMeshRenderer>();
		CacheRenderers(smr);
		
		#if !UNITY_FLASH
	//	ClothRenderer[] cr = GetComponentsInChildren<ClothRenderer>();
	//	CacheRenderers(cr);
		#endif
		
		currentState = false;
		materialsIsDirty = false;
		currentColor = Color.clear;
	}
	
	// Cache given renderers properties
	private void CacheRenderers(Renderer[] renderers)
	{
		for (int i = 0; i < renderers.Length; i++)
		{
			Material[] materials = renderers[i].sharedMaterials;
			
			if (materials != null)
			{
				highlightableRenderers.Add(new HighlightingRendererCache(renderers[i], materials, highlightingMaterial, zWrite));
			}
		}
	}
	
	// Update highlighting color to a given value
	private void SetColor(Color c)
	{
		if (currentColor == c)
		{
			return;
		}
		
		if (zWrite)
		{
			opaqueZMaterial.SetColor("_Outline", c);
		}
		else
		{
			opaqueMaterial.SetColor("_Outline", c);
		}
		
		for (int i = 0; i < highlightableRenderers.Count; i++)
		{
			highlightableRenderers[i].SetColorForTransparent(c);
		}
		
		currentColor = c;
	}
	
	// Set new color if needed
	private void UpdateColors()
	{
		// Don't update colors if highlighting is disabled
		if (currentState == false)
		{
			return;
		}
		
		if (occluder)
		{
			SetColor(occluderColor);
			return;
		}
		
		if (once)
		{
			SetColor(onceColor);
			return;
		}
		
		if (flashing)
		{
			// Flashing frequency is not affected by Time.timeScale
			Color c = Color.Lerp(flashingColorMin, flashingColorMax, 0.5f * Mathf.Sin(Time.realtimeSinceStartup * flashingFreq * doublePI) + 0.5f);
			SetColor(c);
			return;
		}
		
		if (transitionActive)
		{
			Color c = new Color(constantColor.r, constantColor.g, constantColor.b, constantColor.a * transitionValue);
			SetColor(c);
			return;
		}
		else if (constantly)
		{
			SetColor(constantColor);
			return;
		}
	}
	
	// Calculate new transition value if needed.
	private void PerformTransition()
	{
		if (transitionActive == false)
		{
			return;
		}
		
		float targetValue = constantly ? 1f : 0f;
		
		// Is transition finished?
		if (transitionValue == targetValue)
		{
			transitionActive = false;
			return;
		}
		
		if (Time.timeScale != 0f)
		{
			// Calculating delta time untouched by Time.timeScale
			float unscaledDeltaTime = Time.deltaTime / Time.timeScale;
			
			// Calculating new transition value
			transitionValue += (constantly ? constantOnSpeed : -constantOffSpeed) * unscaledDeltaTime;
			transitionValue = Mathf.Clamp01(transitionValue);
		}
		else
		{
			return;
		}
	}
	
	// Highlighting event handler (main highlighting method)
	private void UpdateEventHandler(bool trigger, bool writeDepth)
	{
		// Update and enable highlighting
		if (trigger)
		{
			// ZWriting state changed?
			if (zWrite != writeDepth)
			{
				materialsIsDirty = true;
			}
			
			// Initialize new materials if needed
			if (materialsIsDirty)
			{
				InitMaterials(writeDepth);
			}
			
			currentState = (once || flashing || constantly || transitionActive || occluder);
			
			if (currentState)
			{
				UpdateColors();
				PerformTransition();
				
				if (highlightableRenderers != null)
				{
					layersCache = new int[highlightableRenderers.Count];
					for (int i = 0; i < highlightableRenderers.Count; i++)
					{
						GameObject go = highlightableRenderers[i].goCached;
						// cache layer
						layersCache[i] = go.layer;
						// temporary set layer to renderable by the highlighting effect camera
						go.layer = highlightingLayer;
						highlightableRenderers[i].SetState(true);
					}
				}
			}
		}
		// Disable highlighting
		else
		{
			if (currentState && highlightableRenderers != null)
			{
				for (int i = 0; i < highlightableRenderers.Count; i++)
				{
					highlightableRenderers[i].goCached.layer = layersCache[i];
					highlightableRenderers[i].SetState(false);
				}
			}
		}
	}
	
	IEnumerator EndOfFrame()
	{
		while (enabled)
		{
			yield return new WaitForEndOfFrame();
			// Reset one-frame highlighting state after each HighlightingEffect in the scene has finished rendering
			once = false;
		}
	}
	#endregion
}

2.HightLightableObject

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class FoodPickUp_2 : MonoBehaviour
{
    private HighlightableObject m_ho;//*外发光特效
    public AudioClip FoodGrab;//拾取音效
    public int FoodId;
    private GameObject player;
    public float time = 0.0f;
    public float timer;

    private bool isGrab = false;
    public UIBag Bag;
    //UI部分
    public Text text;
    private string[] objectName = new string[5] { "LuoTuoCi", "Grass", "GuanMu", "Tree", "handrail" };
    private string[] objectCollisionText = new string[5] { "这是针茅草,按E试试", "这是一棵草,按E试试", "这是地衣,按E试试", "这是胡杨林", "再往前走就要掉下去啦!!" };

    //标记在本轮中该对象是否为食物
    private int[] objectFoodFlag = { 0, 1, 2 };
    private bool isFood = false;
    private bool isEat = false;
    private bool flag = true;

    private int k = 0;

    void Update()//一定时间之后,文本消失
    {
        if (text.text == "吃掉啦~~")
        {
            time = time + Time.deltaTime;
        }
        if (time >= 2)
        {
            text.text = "";
        }
        if (text.text == "")
        {
            time = 0f;
        }
    }
    void Awake()//*外发光
    {
        m_ho = GetComponent<HighlightableObject>();//初始化组件
    }
    void Start()
    {
        player = GameObject.FindGameObjectWithTag("Player");
    }

    private void OnTriggerStay(Collider other)
    {

        if (other.gameObject == player)
        {
            text.text = "";
            // print(this.gameObject.tag);
            objectCollision(this.tag);//碰撞事件
            //外发光    
            if (this.tag == "GuanMu")
            {
                m_ho.ConstantOn(Color.green);
            }
            if (this.tag == "LuoTuoCi")
            {
                m_ho.ConstantOn(Color.white);
            }
            if (this.tag == "Gress")
            {
                m_ho.ConstantOn(Color.white);
            }
            /*
            if (this.tag == "Tree")
            {
                m_ho.ConstantOn(Color.cyan);
            }
            if (this.tag == "smallStone")
            {
                m_ho.ConstantOn(Color.blue);
            }*/
            //*
            if (Input.GetKeyDown(KeyCode.E) && isFood)
            {
                Eat();
            }
        }
    }
    //物体碰撞事件
    private void objectCollision(string name)
    {
        for (int i = 0; i < objectName.Length; i++)
        {
            if (name == objectName[i])
            {
                k = i;
                break;
            }
        }
        text.text = objectCollisionText[k];
        for (int i = 0; i < objectFoodFlag.Length; i++)
        {
            if (name == objectName[i])
            {
                isFood = true;
                break;
            }
        }
    }
    //*碰撞结束后字消失,外发光消失
    private void OnTriggerExit(Collider other)
    {
        text.text = "";
        m_ho.ConstantOff();
    }
    public void Eat()
    {

        text.text = "吃掉啦~~";
        AudioSource.PlayClipAtPoint(FoodGrab, transform.position);
        if (!isEat)
            Bag.cellGenerate(k);
        isGrab = true;
        isFood = false;
        isEat = true;
        Destroy(this.gameObject);
    }
    private void textRemove()
    {
        text.text = " ";
    }


}

引用代码

代码功能
private HighlightableObject m_ho;定义外发光物体
m_ho = GetComponent();Awake()中引用,初始化
m_ho.ConstantOn(Color.green);开始发光
m_ho.ConstantOff();发光消失
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值