Unity3d

Unity基础(15)-Application与SceneMan

2018-07-06  本文已影响111人  元宇宙协会

Application类与SceneManager类

静态属性
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
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
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");

## 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)

目前改为了: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);
  }

方法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;
    }

    /// <summary>
    /// log callback check
    /// </summary>
    /// <param name="condition">日志描述信息log内容.</param>
    /// <param name="stackTrace">log产生的栈数据追踪</param>
    /// <param name="type">log的类型.</param>
    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;
    }
上一篇下一篇

猜你喜欢

热点阅读