2015-10-28 10:15:05 laipixiaoxi 阅读数 2154
3d游戏中  一个场景往往斗劲大  若是游戏的进行须要下载一个10M甚至更大的场景时  加载所用的时候会导致很大项目组玩家的流失

我们知道unity3d中的内置地形是应用一张高度图  对其地形进行打包今后  发明<=100KB

那么若是采取unity3d的内置地形作为游戏中的地形时  起首加载地形并显示  再去加载场景中的部件(比如树、房子等)  将会很有须要

在加载场景中的部件时  可以按照玩家当前地点的地位  由近到远的去加载

 

场景中的每个部件实际上并不都是独一无二的  

比如一棵一模一样的树  可能同一个场景中呈如今很多处所  不合的只是树的地位信息  

那么在加载场景的时辰则只须要加载一个树的模型  并记录下N个树的transform信息  将会大大的削减场景所占的空间  

若是模型的重用率较高  那么这个题目的解决将会成倍的削减一个场景所占的空间

场景在加载时  也只须要下载一个树的模型  并按照transform信息  在指定的地位复制出N棵树即可

 

在应用unity3d的BuildPipeline进行打包之前  须要遍历一边所选文件夹下的场景文件 

若是文件的MeshFilter的Mesh为在该文件夹中只呈现了一次  则申明该模型在场景中没有反复  则记录下该模型文件的transform信息  并打包

若是该Mesh呈现的次数大于一次  则记录下这些和该Mesh雷同的模型的transform信息  打包时包含一个模型和多个transform信息

 

在unity3d中有个名为ScriptableObject的类  可以哄骗它来存储本身所需的各类百般的资料

 


public class TransformHolder : ScriptableObject
{
public int Length;
public Vector3[] position;
public Quaternion[] eulerAngles;
public Vector3[] localScale;
}


如许一来  每一个资料包中都包含一个模型和一个TransformHolder类型的文件
TransformHolder的Length若为1  则申明该模型在场景中只呈现了一次

若大于1  则可以按照记录的transform信息轮回生成多个

本来有几百个资料包  大小有十几兆的场景  

用该办法后  变成了二十多个资料包  大小削减到不足2M  

当然这实用于场景中的模型有重用的现象
2017-03-02 22:32:41 yueye30121 阅读数 4521

新建工程,在Assets下新建Scenes文件夹存放场景文件,新建三个Cube,分别命名为Cube、Cube1、Cube2并保存为三个预设,保存新建在ReanAssetbundle.cs脚本,脚本内容如下:


using UnityEngine;
using System.Collections;


public class ReanAssetbundle : MonoBehaviour {




    
// Use this for initialization
void Start () {
        
}
    
    


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

}


    //不同平台下StreamingAssets的路径是不同的,这里需要注意一下。  
    public static readonly string m_PathURL =
#if UNITY_ANDROID  
        "jar:file://" + Application.dataPath + "!/assets/";  
#elif UNITY_IPHONE  
        Application.dataPath + "/Raw/";  
#elif UNITY_STANDALONE_WIN || UNITY_EDITOR
 "file://" + Application.dataPath + "/AssetBundleLearn/";
#else  
        string.Empty;  
#endif


    void OnGUI()
    {
        if (GUILayout.Button("加载分开打包的Assetbundle"))
        {
            StartCoroutine(LoadGameObjectPackedByThemselves(m_PathURL + "Cube.assetbundle"));
            StartCoroutine(LoadGameObjectPackedByThemselves(m_PathURL + "Cube1.assetbundle"));
            StartCoroutine(LoadGameObjectPackedByThemselves(m_PathURL + "Cube2.assetbundle"));


        }


        if (GUILayout.Button("加载打包在一起的Assetbundle"))
        {
            StartCoroutine(LoadGameObjectPackedTogether(m_PathURL + "Together.assetbundle"));
        }        
    }


    //单独读取资源  
    private IEnumerator LoadGameObjectPackedByThemselves(string path)
    {
        WWW bundle = new WWW(path);
        yield return bundle;


        //加载  
        yield return Instantiate(bundle.assetBundle.mainAsset);
        bundle.assetBundle.Unload(false);
    }


    IEnumerator LoadGameObjectPackedTogether(string path)
    {
        WWW bundle = new WWW(path);
        yield return bundle;


        Object one = bundle.assetBundle.Load("Cube");
        Object two = bundle.assetBundle.Load("Cube1");
        Object three = bundle.assetBundle.Load("Cube2");


        //加载  
        yield return Instantiate(one);
        yield return Instantiate(two);
        yield return Instantiate(three);
        bundle.assetBundle.Unload(false);
    }
}

把此脚本挂在Main Camera上,将当前场景保存为Cube.unity,保存到Scenes文件夹下。


Assets文件夹下新建Editor文件夹,在Editor下新建ExportAssetBundles.cs脚本,脚本的内容为

using UnityEngine;

using UnityEditor;

using System.Collections;

 

public class ExportAssetBundles :EditorWindow

{

   ///<summary> 

   ///将选中的预制分别打包 

   ///</summary> 

    [MenuItem("AssetBundleDemo/CreateAssetBundles By themselves")]

   static void CreateAssetBundleThemelves()

    {

       //获取要打包的对象(在Project视图中) 

       Object []selects = Selection.GetFiltered(typeof(Object),SelectionMode.DeepAssets);

       //遍历选中的对象 

       foreach (Objectobjin selects)

        {      

                      //Assets下新建AssetBundleLearn文件夹,存放打包的预设   

           stringtargetPath = Application.dataPath +"/AssetBundleLearn/" +obj.name + ".assetbundle";//文件的后缀名是assetbundleunity都可以 

           if (BuildPipeline.BuildAssetBundle(obj,null,targetPath,BuildAssetBundleOptions.CollectDependencies))

            {

 

               Debug.Log(obj.name +"ispacked successfully!");

            }

           else

            {

               Debug.Log(obj.name +"ispacked failly!");

            }

        }

       //刷新编辑器(不写的话要手动刷新,否则打包的资源不能及时在Project视图内显示) 

       AssetDatabase.Refresh();

    }


     ///<summary> 

   ///将选中的预制一起打包 

   ///</summary>

    [MenuItem("AssetBundleDemo/CreateAssetBundles Together")]

   static void CreateAssetBundleTogether()

    {

       //要打包的对象 

        Object[]selects =Selection.GetFiltered(typeof(Object),SelectionMode.DeepAssets);

       //要打包到的路径 

       stringtargetPath = Application.dataPath +"/AssetBundleLearn/Together.assetbundle";

       if (BuildPipeline.BuildAssetBundle(null,selects, targetPath,BuildAssetBundleOptions.CollectDependencies))

        {

           Debug.Log("Packedsuccessfully!");

 

        }

       else

        {

           Debug.Log("Packedfailly!");

        }

       //刷新编辑器(不写的话要手动刷新) 

       AssetDatabase.Refresh();

    }

 

 

     ///<summary> 

   ///打包场景 

   ///</summary>

    [MenuItem("CustomEditor/Create Scene")]

   static void CreateSceneALL()

    {

       //清空一下缓存

       Caching.CleanCache();

//打包后的资源名为MyScene.unity3d

       stringPath = Application.dataPath +"/MyScene.unity3d";

//被打包的场景名字为Cube.unity

       string[]levels = { "Assets/Scenes/Cube.unity"};

       //打包场景

       BuildPipeline.BuildPlayer(levels,Path,BuildTarget.WebPlayer, BuildOptions.BuildAdditionalStreamedScenes);

       AssetDatabase.Refresh();

    }

}

ExportAssetBundles 脚本完成后,会在unity的菜单栏中出现以上两个菜单,AssetBundleDemo/Create AssetBundles By themselves和AssetBundleDemo/Create AssetBundles Together,选中三个cube的预设,,点击第一个菜单会分别创建三个资源,再点击第二个菜单会将三个预设存入一个资源包中,资源包会保存在AssetBundleLearn文件夹下,运行程序,分别点击"加载分开打包的Assetbundle"和"加载打包在一起的Assetbundle"按钮,会创建被打包的资源。

隐藏掉Main Camera上的ReanAssetbundle脚本,点击Custom Editor/CreateScene菜单,会在Assets下创建一个MyScene.unity3d资源文件,新建一个Scene场景,命名为Load.unity,拖入一个空的GameObject,新建一个脚本LoadScene.cs,内容如下:

using UnityEngine;
using System.Collections;


public class LoadScene : MonoBehaviour {


    private string url;
    private string assetname;
// Use this for initialization
void Start () {
        url = "file://" + Application.dataPath + "/MyScene.unity3d";
}

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

}


    IEnumerator Download()
    {


        WWW www = new WWW(url);
        yield return www;
        if (www.error != null)
        {
            Debug.Log("下载失败");
        }
        else
        {
            AssetBundle bundle = www.assetBundle;
            Application.LoadLevel("Cube");
            // AssetBundle.Unload(false),释放AssetBundle文件内存镜像,不销毁Load创建的Assets对象
            // AssetBundle.Unload(true),释放AssetBundle文件内存镜像同时销毁所有已经Load的Assets内存镜像
            bundle.Unload(false);
        }


        // 中断正在加载过程中的WWW
        www.Dispose();
    }


    void OnGUI()
    {        
        if (GUILayout.Button("加载打包的场景"))
        {
            StartCoroutine(Download());
        }
    }
}

将此脚本挂在空的GameObject上,运行程序,点击会加载已保存的MyScene.unity3d资源包。


2018-07-13 10:51:27 zengjunjie59 阅读数 1260

1、打包场景(转)

    把场景文件打包成 .unity3d 后缀的文件。

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

public class PackAB {

#if UNITY_EDITOR
    [MenuItem("Custom Editor/Create Scene")]
    static void CreateSceneALL()
    {
        //清空一下缓存  
        Caching.ClearCache();

        //获得用户选择的路径的方法,可以打开保存面板(推荐)
        string Path = EditorUtility.SaveFilePanel("保存资源", "SS", "" + "Scene_02", "unity3d");
        //string Path = Application.dataPath + "/Scene_02.unity3d";

        //另一种获得用户选择的路径,默认把打包后的文件放在Assets目录下
        //string Path = Application.dataPath + "/MyScene.unity3d";

        //选择的要保存的对象 
        string[] levels = { "Assets/Scenes/Scene_02.unity" };

        //打包场景  
        BuildPipeline.BuildPlayer(levels, Path, BuildTarget.StandaloneWindows64, BuildOptions.BuildAdditionalStreamedScenes);

        // 刷新,可以直接在Unity工程中看见打包后的文件
        AssetDatabase.Refresh();
    }
#endif
}

2、用WWW下载刚才打包的.unity3d文件并加载出来。

using UnityEngine.SceneManagement;
using UnityEngine;
using System.Collections;

public class SceneCreate : MonoBehaviour
{
    public GameObject prefab1;
    public Transform trans;
    void Start()
    {
        //加载.unity3d后缀的场景文件
        StartCoroutine("LoadScene");                                     
    }
    private IEnumerator LoadScene()
    {
        WWW download = WWW.LoadFromCacheOrDownload("file://" + Application.dataPath + "/Scene_02.unity3d", 1);  
        yield return download;
        var bundle = download.assetBundle;
        AsyncOperation ao = SceneManager.LoadSceneAsync("Scene_02", LoadSceneMode.Additive);   //不需要在build and settings窗口中设置好,这里可以直接用
        yield return ao;
        Scene newScene2 = SceneManager.GetSceneByName("Scene_02");  //获取刚才加载的场景
        SceneManager.SetActiveScene(newScene2);                     //把场景激活
        GameObject newObj = GameObject.Instantiate(prefab1, trans.position, trans.rotation);    //在场景中实例化prefab
    }
}

2019-02-25 11:39:36 hddghhfd 阅读数 411

分享一下我老师大神的人工智能教程。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

               

1. 简介

    在Windows环境下测试好之后,然后导出apk在Android盒子上运行(在电视机上进行显示),场景中所有图片模糊得惨忍睹。本人开发环境为Unity3D 5.0,可从以下两方面解决此问题。

2. 解决方案

2.1 设置Quality

     Edit->Project Settings->Quality,其设置方式如下图所示:


2.2 设置Texture

    其设置方式如下图所示:









           

分享一下我老师大神的人工智能教程。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

2015-05-09 15:49:10 d814617937 阅读数 2426

在unity3d开发中,为了降低场景的运行消耗,通常要利用Unity3d的静态合批和动态合批。因为动态合批要求的条件比较苛刻。所以大部分用的都是静态核批。
利用静态核批就需要尽量的合并场景的贴图,用相同的材质。并把场景物件设置成静态的。这样unity在运行的时候就会自动进行合批,从而降低drawcall。
这样的静态设置在打包的时候就有问题了。因为当你把预设设置成静态之后,在打包的时候是不会进行去重打包的。也就是同样的两个预设只要设置成静态的,就会被打成两份,最终占用两份的包空间。这在游戏项目的空间浪费是很客观的。因为目前游戏的关卡基本都是分章节的。每章用的基本都是一样的模型,只是位置不同。
如果不设置成静态,drawcall又会很多。为了两者都兼备,这里可以利用unity提供的一个api。在打包的时候所以的场景预设都取消静态设置,在运行的时候调用StaticBatchingUtility.Combine(gameObject);gameobject就是场景预设。这样就可以进行静态合批,无论你有没有设置预设为静态。这样就既减少了drawcall又节省了包体空间。

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