2014-03-21 11:30:40 jiangchao5411 阅读数 6121
文笔很差劲,大家凑合看。一个unity场景中摄像机的淡入淡出效果,也是借鉴别人的,新手,有点笨。先上代码,很简单:
#pragma strict
public var fadeSpeed = 0.1;
private var alpha = 1.0;
private var fadeDir = -1;
public var fadeTexture : Texture2D;
function Start(){
	fadeOut();
}
function Update(){
	alpha += fadeDir * fadeSpeed * Time.deltaTime;
	alpha = Mathf.Clamp01(alpha);
	GUI.DrawTexture(Rect(0, 0, Screen.width, Screen.height), fadeTexture);
}


function fadeIn(){
	fadeDir = -1;
}

function fadeOut(){
	fadeDir = 1;
}

需要一张纯黑色的图片,在unity中赋给fadeTexture。把脚本赋给摄像机,当想出现淡入淡出的时候就可以这样调用:Camera.main.SendMessage("fadeIn");或者Camera.main.SendMessage("fadeOut");方法就是改变黑色图片的透明度来实现淡入淡出效果,这是利用GUI来实现的。这个时候如果你想在屏幕变黑的时候绘制其他GUI就不行了。

这时候改变一下思路,在场景中创建一个片plane(cube压扁也行),让片完全的遮挡住摄像机视野,将黑色图片给这个片,改变一下shader属性Transparent->Diffuse,稍微修改一下代码:

#pragma strict
public var fadeSpeed = 0.1;
private var alpha = 1.0;
private var fadeDir = -1;
function Start(){
	fadeOut();
}
function Update(){
	alpha += fadeDir * fadeSpeed * Time.deltaTime;
	alpha = Mathf.Clamp01(alpha);
	gameObject.renderer.material.color.a = alpha;
}


function fadeIn(){
	fadeDir = -1;
}

function fadeOut(){
	fadeDir = 1;
}
这时候可以实现同样的效果。而且在屏幕变黑的时候还可以加其他的GUI,像黑屏时加上button,点击button场景变亮,或者黑屏时加上一些说明文字(GUI Text)等等,如果感觉场景中一块黑板碍眼,可以把他的main color的a值改成0,这样你就看不见了。对了,这时候实现淡入淡出要调用这个片上脚本的fadeIn()或者fadeOut,而不再是摄像机上的。同等类似,你可以实现GUI Text文字出现的淡入淡出效果!再说一点,因为程序一运行这个脚本就会执行,你要明确你场景初始状态是什么。alpha=1.0是全黑,我上面代码就是程序一运行场景是黑的。举个例子:你的alpha=1.0,start调用fadeIn(),程序一运行会由黑变亮,。alpha=0,start调用fadeIn(),一运行,程序一直是亮的。好像说的有点多,聪明的大家可能都能看懂,那就当我练习打字了吧。

2017-05-03 16:54:47 q568360447 阅读数 6804
在制作游戏时,我们在切换场景时经常需要增加一个淡入淡出的效果。这里,我们利用Unity自带的动画系统制作一个场景的淡入淡出的效果。步骤如下:
1.在游戏中新建一个游戏对象,给游戏添加一个GUITexture组件,并设置好相关的参数后,制作成prefab。如下图:

![这里写图片描述](http://img.blog.csdn.net/20170503163347320?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcTU2ODM2MDQ0Nw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)

2.给这个prefab制作1个动作文件Animation,这个动作一会持续2秒,动画的持续过程会改变此prefab中GUITexture里的Color.a的值。在第0帧处,color.a的值为0,在动画的第1秒处color.a的值为0.5,在动画第2秒处color.a的值又变化为0.此时就完成了一个alpha值的渐变动画。

3.加控制代码。
using UnityEngine;
using System.Collections;
using UnityEngine.SceneManagerment;

public class LoadLevelFadeEffect : MonoBehaviour {
    [HideInInspector]
    public int levelIndex;

    // Use this for initialization
    void Awake () {
        //这个脚本不会在切换场景时被销毁
        DontDestroyOnLoad(this.gameObject);
    }

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


    }

    /// <summary>
    /// 注:这个方法在unity引擎中的动画系统中利用事件调用。下面的DestroySelf同样在Unity中调用
    /// </summary>
    public void Test()
    {
        //这里是场景切换的逻辑。
        SceneManager.LoadScene(levelIndex);
        ……
    }

    public void DestroySelf()
    {
        Destroy(this.gameObject);
    }
}
4.将上面的脚本添加给我们制作的prefab中,并在该prefab的动画的第1秒处的关键帧上添加事件,执行Test()函数。在动画播放完毕后的关键帧上再添加事件,执行DestroySelf()函数。表示销毁自身。

至此,整个切换场景的淡入淡出效果实现完毕。但是这样做有几点是需要注意的:
1、在需要切换场景的时候只需要生成这个Prefab即可,生成代码如下:
        //在场景中生成该Prefab
        GameObject go = UIManager.Instance.LoadGameObject("Others/Fade");
        GUITexture gt = go.GetComponent<GUITexture>();
        //保证GUITexture可以覆盖整个游戏屏幕
        gt.pixelInset = new Rect(-100, -100, Screen.width, Screen.height);
2.这个淡入淡出只针对游戏内的场景有效,无法将游戏中的UI也淡入淡出。
3.这样做会让游戏中的很多代码在工程外调用,由引擎调用,因此后期在维护时会增加成本。因此必须在调用代码时做好注释,表明这一段代码是由引擎调用的。
2018-03-30 16:38:43 mango9126 阅读数 4824

简介:

在Unity场景切换的时候,可以用RawImage很简单的制作场景的淡入淡出过渡。

新建RawImage,覆盖全屏,在UI顶层,然后拖到脚本上

代码比较简单,如下:

public class SceneFadeInOut : MonoBehaviour
{

    public float fadeSpeed = 1.5f;
    public bool sceneStarting = true;
    private RawImage rawImage;
    void Awake()
    {
        rawImage = GetComponent<RawImage>();
    }

    void Start()
    {
    }

    void Update()
    {
        if (sceneStarting)
            StartScene();
    }

    private void FadeToClear()
    {
        rawImage.color = Color.Lerp(rawImage.color, Color.clear, fadeSpeed * Time.deltaTime);
    }

    private void FadeToBlack()
    {
        rawImage.color = Color.Lerp(rawImage.color, Color.black, fadeSpeed * Time.deltaTime);
    }

    void StartScene()
    {
        FadeToClear();
        if (rawImage.color.a < 0.05f)
        {
            rawImage.color = Color.clear;
            rawImage.enabled = false;
            sceneStarting = false;
        }
    }

    void EndScene()
    {
        rawImage.enabled = true;
        FadeToBlack();
        if (rawImage.color.a > 0.95f)
        {
            SceneManager.LoadScene(0);
        }
    }

    void OnDestroy()
    {

    }
}

2016-03-15 22:54:16 puraples 阅读数 1929
  1. 说明
    由于近期项目需求,在网上找了淡入淡出的代码,但都是两张图片淡入淡出结束后就没有了(可能我没找到其他好的作品)。所以我做了简单的扩展

  2. 简单思路
    既然待机状态下的图片淡入淡出切换,所以,首先要判断何时为待机状态(即屏幕没有任何操作的情况下);其次,图片静止一段时间后,开始淡入淡出,第一张图片淡入,第二张淡出;接着图片再次静止一段时间,然后接着下次的淡入淡出,但因为是循环淡入淡出,所以要考虑重新加载第一张照片(再下一次淡入淡出要重新加载第二张照片)。还有在淡入淡出的循环中还要考虑图片alpha值从1到0然后从0到1的循环(可以避免闪烁淡入淡出,有种自然的感觉);最后判断进入非待机状态,即有操作。

  3. 代码实现及分析
    引入UI命名空间,用UI做淡入淡出效果;
    using UnityEngine.UI;

public Image nobody_Img1;
public Image nobody_Img2;//淡入淡出的两张图片
public float fadeTotalTime=5f;//淡入淡出的时间
public float imageStaticTime=3f;//图片静止时间
public float runningTime=10f;//程序运行时间
public int StandbyTime=5;//无操作时间
/*
[HideInInspector]
public bool standby=false;
*/

private bool standby=false;//是否处于待机状态
private float startTime=0;//开始待机时间
private int imgIndex=2;//图片索引(图片名字)
private float remainder=0//下一次待机开始时间
private bool hasStartNext=false;//是否已经加载过下一张待机图片
private bool canLoad=true;//是否可以加载图片
private bool startCountTime=false;//是否可以统计待机时间
private int standbyTime=0;//待机时间
private int time=0;//帧数,用于统计待机时间
private Vector3 prevMousePos=Vector3.zero;//鼠标上一帧所处的位置

/*变量说明
判断屏幕无操作(而且鼠标的位置要没有变化)后就开始统计无操作的时间(即startCountTime=true,time++(放在FixedUpdate函数中),standbyTime++),当standbyTime超过规定时间,standby=true;开始图片淡入淡出
*/

/*
程序刚运行时,不管有没有操作,十秒钟后开始统计开机时间
*/
IEnumerator StartPrepareStandby()
{
    yield return new WaitForSeconds(runningTime);
    startCountTime=true;//开始统计待机时间
}

/*
进入待机后,显示两张图片,并静止一段时间后在循环淡入淡出
*/
IEnumerator StartFirstFade()
{
    //现实两张图片
    nobody_Img1.enabled=true;
    nobody_Img2.enabled=true;
    yield return new WaitForSeconds(imageStaticTime);
    //重置时间
    startTime=Time.time;//开始待机时间等于程序现在的时间
    remainder=startTime;//记录淡入淡出开始的时间
    //开始待机
    standby=true;
}

/*
第一次淡入淡出后开始以后的淡入淡出循环
*/
IEnumerator StartNextFade()
{
    if(imgIndex>=4)//判断图片索引是否越界(图片索引也是图片名)
        imgIindex=0;
    //canLoad在这用于判断加载哪一张图片
    if(canLoad)
    {
        nobody_Img1.sprite=Resources.Load(imgIndex.ToString(),typeof(Sprite)) as Sprite;
    }
    else
    {
        nobody_Img2.sprite=Resources.Load(imgIndex.ToString(),typeof(Sprite)) as Sprite;
    }
    canLoad = !canLoad;//取反,用于区分图片的加载
    imgIndex++;//图片索引累加,下次加载下一张图片
    yield return new WaitForSeconds(imageStaticTime);
    //重置淡入淡出时间
    startTime=Time.time;
    remainder=startTime;
    //图片已加载,等待下次的加载
    hasStartNext=false;
}

void Start()
{
    //调用开始统计待机时间的协程
    StartCoroutine(StartPrepareStandby());
}

void FixedUpdate()
{
    if(startCountTime)
    {//无操作下统计时间
        if(Input.mousePosition==prevMousePos)
        {//判断鼠标是否还在移动
            time++;
        }
        else
        {//鼠标移动时,重置待机时间
            standbyTime=0;
            time=0;
        }
    }
    if(time>=50)
    {
        time=0;
        standbyTime++;//待机秒数
    }
    if(standbyTime>StandbyTime)
    {//超出规定的无操作的时间即认为待机状态
        standbyTime--;//开始第一次图片淡入淡出协程只执行一次
        startCountTime=false;//停止待机时间的统计
        StartCoroutine(StartFirstFade());//开始第一图片淡入淡出
    }
}

void Update()
{
    if(Input.GetMouseButtonDown(0))
    {//每次鼠标按下都停止待机及相关的判断
        StopCoroutine(StartNextFade());//停止淡入淡出
        standby=false;//退出待机状态
        //保留当前图片的alpha值
        if(canLoad)
        {//根据当前canLoad来判断那一张照片在淡入淡出
            nobody_Img1.color=new Color(1,1,1,1);
            nobody_Img2.color=new Color(1,1,1,0);
        }
        else
        {
            nobody_Img1.color=new Color(1,1,1,0);
            nobody_Img2.color=new Color(1,1,1,1);
        }
        //隐藏待机图片
         nobody_Img1.enabled=false;
         nobody_Img2.enabled=false;
         //重置待机时间
         standbyTime=0;
         time=0;
    }
    else if(Input.GetMouseButtonUp(0))
    {//鼠标每次抬起都认为是无操作
        startCountTime=true;
        prevMousePos=Input.mousePosition;
    }
    if(standby)
    {
        if(Time.time<startTime+fadeTotalTime)
        {
            float alphaValue=(Time.time-remainder)/fadeTotalTime;
            if(canLoad)
            {
                nobody_Img1.color=new Color(1,1,1,1-alphaValue);
                nobody_Img2.color=new Color(1,1,1,alphaValue);
            }
            else
            {
                nobody_Img1.color=new Color(1,1,1,alphaValue);
                nobody_Img2.color=new Color(1,1,1,1-alphaValue);
            }
        }
        else
        {
            if(!hasStartNext)
            {
                hasStartNext=true;//已开始加载下一张照片
                StartCoroutine(StartNextFade());//开始下一次淡入淡出协程
            }
        }
    }
    prevMousePos=Input.mousePosition;//记录每一帧鼠标的位置
}
  1. 总结
    虽然此次感觉思路较为清晰但还是花费了很长时间来完成这一简单的程序;我也深信对这一简单的程序,肯定还有简单的做法;自我感觉自己的程序有点绕且繁琐(对程序的扩展也可以引用设计模式的单例模式或其他模式进行再其他脚本处的待机状态判断)。欢迎各位指点一二!
2013-03-05 16:01:12 minitail_ 阅读数 7323

今天研究一下场景间跳转,能够加入一张载入图并实现淡入淡出功能。先上图。


1.进入场景,点击跳转至Scene2.



2.转场景。



3.转场景完毕。



其实这个东西是很久很久以前网上一位童鞋写的。我把代码拿来,做了一些修改,加了一些注释,让我们用起来更方便。

如果有什么不妥的地方,希望大家予以告知。


这个功能大体上的思路就是控制GUI的Alpha值,达到一个淡入淡出的效果。

同时,状态机的使用我们有必要学习一下。


上代码:

SceneLoad脚本

using UnityEngine;
using System.Collections;

//淡入淡出跳转场景
public class SceneLoad : MonoBehaviour
{
	//载入图的绘制深度
	public int guiDepth = 0;
	//要加载的场景名
	public string levelToLoad = "";
	//载入界面图片
	public Texture2D splashLogo;
	//淡入淡出速度
	public float fadeSpeed = 0.8f;
	//等待时间
	public float waitTime = 0.2f;
	//是否等待任意操作跳转
	public bool waitForInput = false;
	//是否自动跳转
	public bool startAutomatically = true;
	//淡出的停留时间
	private float timeFadingInFinished = 0.0f;
	//淡出方式(分为先加载后淡出和先淡出后加载两种)
	public enum SplashType
	{
		LoadNextLevelThenFadeOut,
		FadeOutThenLoadNextLevel
	}
	public SplashType splashType;
	//透明度
	private float alpha = 0.0f;
	//淡入淡出的状态
	private enum FadeStatus
	{
		Paused,
		FadeIn,
		FadeWaiting,
		FadeOut
	}
	private FadeStatus status = FadeStatus.FadeIn;
	//摄像机
	private Camera oldCam;
	private GameObject oldCamGO;
	//载入图绘制范围
	private Rect splashLogoPos = new Rect();
	//载入图位置
	public enum LogoPositioning
	{
		Centered,
		Stretched
	}
	public LogoPositioning logoPositioning;
	//是否绘制下个场景
	private bool loadingNextLevel = false;
	
	void Start ()
	{
		//是否自动淡入淡出
		if(startAutomatically)
		{
			status = FadeStatus.FadeIn;
		}
		else
		{
			status = FadeStatus.Paused;
		}
		//指定摄像机
		oldCam = Camera.main;
		oldCamGO = Camera.main.gameObject;
		//载入图位置大小判断
		if(logoPositioning == LogoPositioning.Centered)
		{
			splashLogoPos.x = (Screen.width * 0.5f) - (splashLogo.width * 0.5f);
			splashLogoPos.y = (Screen.height * 0.5f) - (splashLogo.height * 0.5f);
			
			splashLogoPos.width = splashLogo.width;
			splashLogoPos.height = splashLogo.height;
		}
		else
		{
			splashLogoPos.x = 0;
			splashLogoPos.y = 0;
			
			splashLogoPos.width = Screen.width;
			splashLogoPos.height = Screen.height;
		}
		
		if(splashType == SplashType.LoadNextLevelThenFadeOut)
		{
			DontDestroyOnLoad(this);
			DontDestroyOnLoad(Camera.main);
		}
		//判断待加载场景是否为空
		if((Application.levelCount <= 1)||(levelToLoad == ""))
		{
			Debug.LogWarning("Invalid levelToLoad value.");
		}
	}
	
	//外部调用接口执行淡入淡出转场景
	public void StartSplash ()
	{
		status = FadeStatus.FadeIn;
	}
	
	void Update ()
	{
		//状态机判断
		switch(status)
		{
		case FadeStatus.FadeIn:
			alpha += fadeSpeed * Time.deltaTime;
			break;
		case FadeStatus.FadeWaiting:
			if((!waitForInput && Time.time >= timeFadingInFinished + waitTime)||(waitForInput && Input.anyKey))
			{
				status = FadeStatus.FadeOut;
			}
			break;
		case FadeStatus.FadeOut:
			alpha += -fadeSpeed * Time.deltaTime;
			break;
		}
	}
	
	void OnGUI()
	{
		//图片Alpha控制
		GUI.depth = guiDepth;
		if(splashLogo != null)
		{
			GUI.color = new Color(GUI.color.r,GUI.color.g,GUI.color.b,Mathf.Clamp01(alpha));
			GUI.DrawTexture(splashLogoPos,splashLogo);
		}
		if(alpha > 1.0f)
		{
			status = FadeStatus.FadeWaiting;
			timeFadingInFinished = Time.time;
			alpha = 1.0f;
			if(splashType == SplashType.LoadNextLevelThenFadeOut)
			{
				oldCam.depth = -1000;
				loadingNextLevel = true;
				if((Application.levelCount) >= 1 && (levelToLoad != ""))
				{
					Application.LoadLevel(levelToLoad);
				}
			}
		}
		if(alpha < 0.0f)
		{
			if(splashType == SplashType.FadeOutThenLoadNextLevel)
			{
				if((Application.levelCount >= 1)||(levelToLoad != ""))
				{
					Application.LoadLevel(levelToLoad);
				}
			}
			else
			{
				Destroy(oldCamGO);
				Destroy(oldCam);
			}
		}
	}
	
	//场景加载完毕后销毁摄像机和摄像机物体
	void OnLevelWasLoaded (int lvlIdx)
	{
		if(loadingNextLevel)
		{	
			if(alpha == 0.0f)
			{
				Destroy(oldCam);
				Destroy(oldCamGO);
			}
		}	
	}
	
	//绘制Gizmos
	void OnDrawGizmos ()
	{
		Gizmos.color = new Color(1.0f,0.0f,0.0f,0.5f);
		Gizmos.DrawCube(transform.position,new Vector3(1,1,1));
	}
}

SceneControl脚本

using UnityEngine;
using System.Collections;

//场景跳转控制
public class SceneControl : MonoBehaviour 
{
	SceneLoad sceneload;
	public string sceneName;
	
	// Use this for initialization
	void Start () 
	{
		sceneload = GetComponent<SceneLoad>();
		sceneName = sceneload.levelToLoad;
	}
	
	// Update is called once per frame
	void Update () 
	{
		
	}
	
	void OnGUI ()
	{
		if(GUILayout.Button("http://blog.csdn.net/minitail_"))
		{
			Application.OpenURL("http://blog.csdn.net/minitail_");
		}
		if(GUI.Button(new Rect(Screen.width / 2 - 100,Screen.height * 2 / 3,200,80),"跳转至" + sceneName))
		{
			sceneload.StartSplash();
		}
	}
}


个人觉得这个简单的功能稍加改进,就可以制作大资源场景之间切换的Loading图控制脚本。


工程包地址:http://www.vdisk.cn/down/index/12487978


PS:下面还有一个通过发送摄像机消息淡入淡出的工程。思路跟刚才的差不多。工程包送上。


工程包地址:http://www.vdisk.cn/down/index/12488795

没有更多推荐了,返回首页