Unity基础(15)-Application与SceneManager类

Application类与SceneManager类

  • 在较早Unity版本之前,Application类负责:应用程序运行时数据,获取并加载场景(异步,同步),随着移动端兴起,后期版本中只负责获取跟应用程序运行时数据,而场景相关的被SceneManager替代。这也是与其他移动平台结合的改变。


    Unity基础(15)-Application与SceneManager类_第1张图片
    移动端
Unity基础(15)-Application与SceneManager类_第2张图片
静态属性
  • Application静态属性:
    dataPath属性 : 数据文件路径
    public static string dataPath{ get; }
    Application.dataPath 返回程序的数据文件所在文件夹的路径(只读).返回路径为相对路径,不同游戏平台的数据文件保存路径不同,Editor中就是项目的Assets文件夹的路径,通过这个路径可以访问项目中任何文件夹中的资源,但是在移动端它是完全没用。
    Application.persistentDataPath 此属性返回一个持久化数据存储目录的路径,可以在此路径下存储一些持久化的数据文件。这个路径可读、可写,但是只能在程序运行时才能读写操作,不能提前将数据放入这个路径。在IOS上是应用程序的沙盒,可以被iCloud自动备份,可以通过同步推送一类的助手直接取出文件;在Android上的位置是根据Project Setting里设置的Write Access路径,可以设置是程序沙盒还是sdcard,注意:如果在Android设置保存在沙盒中,那么就必须root以后才能用电脑取出文件,因此建议写入sdcard里。一般情况下,建议将获得的文件保存在这个路径下,例如可以从StreamingAsset中读取的二进制文件或者从AssetBundle读取的文件写入PersistentDatapath。
    Application.streamingAassetsPath 此属性用于返回流数据的缓存目录,返回路径为相对路径,适合设置一些外部数据文件的路径.在PC/MAC中可实现对文件的“增删改查”等操作,但在移动端是一个只读路径。
    Application.temporaryCachePath 此属性返回一个临时数据的缓存目录,跟Application.persistentDataPath类似,但是在IOS上不能被自动备份
    以上各路径中的资源加载方式都可以用WWW类加载,但要注意各个平台路径需要加的访问名称,例如Android平台的路径前要加"jar:file://",其他平台使用"file://"。以下是各路径在各平台中的具体位置信息:
  • Android平台
Application.dataPath :  /data/app/xxx.xxx.xxx.apk
Application.streamingAssetsPath :  jar:file:///data/app/xxx.xxx.xxx.apk/!/assets
Application.persistentDataPath :  /data/data/xxx.xxx.xxx/files
Application.temporaryCachePath :  /data/data/xxx.xxx.xxx/cache
  • IOS平台
Application.dataPath :                    Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/xxx.app/Data
Application.streamingAssetsPath : Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/xxx.app/Data/Raw
Application.persistentDataPath :    Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/Documents
Application.temporaryCachePath : Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/Library/Caches
  • Windows Web Player
Application.dataPath :  file:///D:/MyGame/WebPlayer (即导包后保存的文件夹,html文件所在文件夹)
Application.streamingAssetsPath : 
Application.persistentDataPath : 
Application.temporaryCachePath : 
#if UNITY_EDITOR
string filepath = Application.dataPath +"/StreamingAssets"+"/version.txt";
#elif UNITY_IPHONE
 string filepath = Application.dataPath +"/Raw"+"/my.xml";
#elif UNITY_ANDROID
 string filepath = "jar:file://" + Application.dataPath + "!/assets/"+"/version.txt";
#endif

StreamingAssets在各个平台上的文本支持读取方式
string path = System.IO.Path.Combine(Application.streamingAssetsPath,"version.txt");

Unity基础(15)-Application与SceneManager类_第3张图片

## Editor:
1::System.IO.File.ReadAllText (path);
2:path = "file://"+path;或者 path = "file:/"+path;或者 path = "file:\\"+path或者 path = "file:\\\\"+path;在win7上都可以 在mac上path = "file:/"+path不可以外,别的都可以 
然后WWW www = new WWW (path);

## Android:
1:WWW www = new WWW (path);

##  iphone:
1:System.IO.File.ReadAllText (path);
2:path = "file://"+path;System.IO.File.ReadAllText (path); 

还有一点就是在读取streamingAssets目录下的文本文件时android平台必须要用www来读取哦,因为android平台是被压缩在apk中,
所以不能直接用CSharp去读,ios可以直接用System.IO.File.ReadAllText(filePath)

  • loadedLevel属性 :
    SceneManager.GetActiveScene().buildIndex返回当前场景的索引值
    SceneManager.GetActiveScene().name返回当前场景的名字
    SceneManager.sceneCountInBuildSettings游戏中可被加载的场景数量
    Application.platform 当前游戏的运行平台,返回值为枚举类型
    Application.isPlaying 当前游戏是否正在运行
    Application.isEditor 游戏是否处于Unity编辑模式

  • Application类静态方法:
    旧方法Application.CaptureScreenshot方法 : 截屏

目前改为了:ScreenCapture.CaptureScreenshot
public static void CaptureScreenshot(string filename);
参数filename 截屏文件名称 superSize放大系数,默认为0,即不放大
public static void CaptureScreenshot(string filename, int superSize);
此方法截取当前游戏画面并保存为PNG格式,文件默认保存在根目录下,若有重名文件则替换.

 public void CameraGame()
 {
         Debug.Log(Application.dataPath);
         string fileName = Application.dataPath +"/Images/" + Time.time+ ".png";
         ScreenCapture.CaptureScreenshot(fileName);
 }
  public void CameraGame()
  {
         Debug.Log(Application.dataPath);
        StartCoroutine(GetScreenCamera());
  }

 IEnumerator GetScreenCamera()
 {
        yield return new WaitForEndOfFrame();
        Texture2D t = new Texture2D(100, 100, TextureFormat.RGB24, false);
        t.ReadPixels(new Rect(0, 0, 100, 100), 0, 0);
        // 保存图片
        t.Apply();
        byte[] imgB = t.EncodeToPNG();
        System.IO.File.WriteAllBytes(Application.dataPath + "/Images/" + Time.time + ".png", imgB);
  }
  • RegisterLogCallback方法 :注册委托
    方法1:Application.RegisterLogCallback
    static function RegisterLogCallback (handler : Application.LogCallback) : void
    在一个日志信息上注册一个委托来被调用,这个函数和RegisterLogCallback唯

方法2:Application.RegisterLogCallbackThreaded
static function RegisterLogCallbackThreaded (handler : Application.LogCallback) : void
在一个日志信息上注册一个委托来被调用,这个函数和RegisterLogCallback唯一不同的是,这个函数将从不同的线程被调用,注意:你只有你知道你在做什么时才能使用这个函数,否则使用Application.RegisterLogCallback。

两个方法在使用的时候,都需要传递一个委托
public delegate void LogCallback (string condition, string stackTrace, LogType type);
第一个参数为日志描述信息,第二个参数为日志产生的栈数据,第三个参数为日志的类型

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

public class LogMessage : MonoBehaviour {
    string  message="";
    public Text text;
    void Start () {
        //在一个日志信息上注册一个委托来被调用
        Application.logMessageReceivedThreaded +=MyLogCallback;
    }

    void Update () {
        text.text = message;
    }

    /// 
    /// log callback check
    /// 
    /// 日志描述信息log内容.
    /// log产生的栈数据追踪
    /// log的类型.
    void  MyLogCallback (string condition, string stackTrace, LogType type){
        switch(type){
        case LogType.Assert:
            message += "      receive an assert log"+",condition="+condition+",stackTrace="+stackTrace;
            break;
        case LogType.Error:
            message += "      receive an Error log"+",condition="+condition+",stackTrace="+stackTrace;
            break;
        case LogType.Exception:
            message += "      receive an Exception log"+",condition="+condition+",stackTrace="+stackTrace;
            break;
        case LogType.Log:
            message += "      receive an Log log"+",condition="+condition+",stackTrace="+stackTrace;
            break;
        case LogType.Warning:
            message += "      receive an Warning log"+",condition="+condition+",stackTrace="+stackTrace;
            break;
        }
    }

    void OnGUI(){
        if(GUI.Button(new Rect(10,20,200,40),"assert")){
            Debug.LogAssertion ("assertion");
        }else if(GUI.Button(new Rect(10,80,200,40),"error")){
            Debug.LogError ("error");
        }else if(GUI.Button(new Rect(10,140,200,40),"exception")){
            Debug.LogException (new System.NullReferenceException());
        }else if(GUI.Button(new Rect(10,200,200,40),"log")){
            Debug.Log ("log");
        }else if(GUI.Button(new Rect(10,260,200,40),"warning")){
            Debug.LogWarning ("waring");
        }
    }
}

Application相关事件函数

OnApplicationPause(bool pause) 如果应用程序暂停,则为True,否则为False
OnApplicationFocus(bool focus) 如果应用程序失去焦点
OnApplicationQuit() 程序退出事件

`强制暂停时`,先 `OnApplicationPause`,后 `OnApplicationFocus`;
`重新“启动”手机时`,先`OnApplicationFocus`,后 `OnApplicationPause`;
`启用键盘按Home`不会调用OnApplicationFocus,而是调用OnApplicationPause;
`安卓上启用手机键盘`,会调用OnApplicationFocus](false)事件。
  private void OnApplicationPause(bool pause)
    {
        Debug.Log("停止程序" + pause);
    }
    private void OnApplicationFocus(bool focus)
    {
        Debug.Log("程序失去焦点" + focus);
    }


  // 当前应用双击Home,然后Kill(IOS 有回调,android 没回调)
  private void OnApplicationQuit()
    {
        QuitGame();
    }
    public void QuitGame()
    {
        Debug.Log("Quit");
        // 在编辑器或者web播放器中退出被忽略
        // Application.Quit();
#if UNITY_EDITOR
        UnityEditor.EditorApplication.isPlaying = false;
#elif UNITY_IPHONE
        Application.Quit();
#elif UNITY_ANDROID
       Application.Quit();
#else
        Application.Quit();
#endif
    }

SceneManager

通常游戏的主场景包含的资源较多,这会导致加载场景的时间较长。
为了避免这个问题,可以首先加载Loading场景,然后再通过Loading场景来加载主场景。
因为Loading场景包含的资源较少,所以加载速度快。
在加载主场景的时候一般会在Loading界面中显示一个进度条来告知玩家当前加载的进度。
在Unity中可以通过调用SceneManager.LoadSceneAsync(旧版本:Application.LoadLevelAsync)函数来异步加载游戏场景,
通过查询AsyncOperation.progress的值来得到场景加载的进度。
通过Unity提供的Coroutine机制,我们可以方便的在每一帧结束后调用SetLoadingPercentage函数来更新界面中显示的进度条的数值。
SceneManager.LoadSceneAsync()
此方法用于按照关卡名字在后台异步加载关卡到当前场景中,此方法只是将新关卡加载到当前场景,当前场景的原有内容不会被销毁.
AsynvOperation colve = public static AsynvOperation LoadLevelAdditiveAsync(int index);
colve.isDone 是否加载完成
colve.progress 加载进度

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

public class Loading : MonoBehaviour {

    public Slider loadingSlider;
    public Text loadingText;
    public AsyncOperation op;
    public float targetValue;

    void Start () {
        loadingSlider.value = 0.0f;
        // 判断当前场景的名字是Loading
        if (SceneManager.GetActiveScene().name == "Loading")
        {
            // 加载下一个场景
            StartCoroutine(AsyncLoading());
        }
    }

    private IEnumerator AsyncLoading()
    {
        op =  SceneManager.LoadSceneAsync(3);
        // 阻止当加载完成自动切换
        op.allowSceneActivation = false;
        // 
        yield return op;
    }

    void Update () {
        Debug.Log(op.progress);
        targetValue = op.progress;
        if (op.progress >= 0.9f)
        {
                //operation.progress的值最大为0.9
                targetValue = 1.0f;
        }
        if (targetValue != loadingSlider.value)
        {
            //插值运算
            loadingSlider.value = Mathf.Lerp(loadingSlider.value, targetValue, Time.deltaTime * 1);
            if (Mathf.Abs(loadingSlider.value - targetValue) < 0.01f)
            {
                loadingSlider.value = targetValue;
            }
        }
        loadingText.text = ((int)(loadingSlider.value * 100)).ToString() + "%";
        if ((int)(loadingSlider.value * 100) == 100)
        {
            //允许异步加载完毕后自动切换场景
            op.allowSceneActivation = true;
        }
    }
}

第二种方式:进度条加载

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

public class LoadScene : MonoBehaviour {
    public Slider sl;
    public Text t;
    void Start () {
        sl.value = 0;
        StartCoroutine(LoadingScene());
    }

    private IEnumerator LoadingScene(int scene)
    {
        AsyncOperation op = SceneManager.LoadSceneAsync(3);
        while (!op.isDone)
        {
            t.text = op.progress * 100 + "%";
           sl.value = op.progress * 100 ;
            yield return new WaitForEndOfFrame();        
        }
    }

    private IEnumerator LoadingScene()
    {
        int displayProgress = 0;
        int toProgress = 0;
        AsyncOperation op = SceneManager.LoadSceneAsync(3);
        op.allowSceneActivation = false;
        while (op.progress < 0.9f)
        {
            toProgress = (int)op.progress * 100;
            while (displayProgress < toProgress)
            {
                ++displayProgress;
                t.text = displayProgress + "%";
                sl.value = displayProgress * 0.01f;
                yield return new WaitForEndOfFrame();
            }
        }
        toProgress = 100;
        while (displayProgress < toProgress)
        {
           ++displayProgress;
           t.text = displayProgress  + "%";
           sl.value = displayProgress * 0.01f;
           yield return new WaitForEndOfFrame();
        }
       op.allowSceneActivation = true;
    }

你可能感兴趣的:(Unity基础(15)-Application与SceneManager类)