1. 程式人生 > >Unity實現震動效果,抖動,震屏等

Unity實現震動效果,抖動,震屏等

上篇震屏部落格說到的簡單震屏效果,雖然可以實現,但是螢幕邊界會給人一種扭曲感,振幅越大感覺越明顯。所以本篇部落格做出了大幅度更改,以正弦規律震動,效果更加自然,若實現震屏將此指令碼掛載到相機上即可,可以設定震動幅度,震動角度,震動次數等,具體引數效果可以通過更改控制面板上的引數測試,也可用於其他物體的晃動,反覆控制enabled=true,即可反覆震動。

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

public class ShakeCamera : MonoBehaviour {


	public Vector3 positionShake;//震動幅度
	public Vector3 angleShake;   //震動角度
	public float cycleTime = 0.2f;//震動週期
	public int cycleCount = 6;    //震動次數
	public bool fixShake = false; //為真時每次幅度相同,反之則遞減
	public bool unscaleTime = false;//不考慮縮放時間
	public bool bothDir = true;//雙向震動
	public float fCycleCount = 0;//設定此引數,以此震動次數為主
	public bool autoDisable = true;//自動disbale
	

	float currentTime;
	int curCycle;
	Vector3 curPositonShake;
	Vector3 curAngleShake;
	float curFovShake;
	Vector3 startPosition;
	Vector3 startAngles;
	Transform myTransform;

	void OnEnable()
	{
		currentTime = 0f;
		curCycle = 0;
		curPositonShake = positionShake;
		curAngleShake = angleShake;
		myTransform = transform;
		startPosition = myTransform.localPosition;
		startAngles = myTransform.localEulerAngles;
		if (fCycleCount > 0)
			cycleCount = Mathf.RoundToInt(fCycleCount);
	}

	void OnDisable()
	{
		myTransform.localPosition = startPosition;
		myTransform.localEulerAngles = startAngles;
	}

	// Update is called once per frame
	void Update () {

		#if UNITY_EDITOR
		if (fCycleCount > 0)
			cycleCount = Mathf.RoundToInt(fCycleCount);
		#endif

		if (curCycle >= cycleCount)
		{
			if (autoDisable)
				enabled = false;
			return;
		}

		float deltaTime = unscaleTime ? Time.unscaledDeltaTime : Time.deltaTime;
		currentTime += deltaTime;
		while (currentTime >= cycleTime)
		{
			currentTime -= cycleTime;
			curCycle++;
			if (curCycle >= cycleCount)
			{
				myTransform.localPosition = startPosition;
				myTransform.localEulerAngles = startAngles;
				return;
			}

			if (!fixShake)
			{
				if (positionShake != Vector3.zero)
					curPositonShake = (cycleCount - curCycle) * positionShake / cycleCount;
				if (angleShake != Vector3.zero)
					curAngleShake = (cycleCount - curCycle) * angleShake / cycleCount;
			}
		}

		if (curCycle < cycleCount)
		{
			float offsetScale = Mathf.Sin((bothDir ? 2 : 1) * Mathf.PI * currentTime / cycleTime);
			if (positionShake != Vector3.zero)
				myTransform.localPosition = startPosition + curPositonShake * offsetScale;
			if (angleShake != Vector3.zero)
				myTransform.localEulerAngles = startAngles + curAngleShake * offsetScale;
		}
	}
    //重置
	public void Restart()
	{
		if (enabled)
		{
			currentTime = 0f;
			curCycle = 0;
			curPositonShake = positionShake;
			curAngleShake = angleShake;
			myTransform.localPosition = startPosition;
			myTransform.localEulerAngles = startAngles;
			if (fCycleCount > 0)
				cycleCount = Mathf.RoundToInt(fCycleCount);
		}
		else
			enabled = true;
	}
}