转自:http://www.manew.com/forum.php?mod=viewthread&tid=98520&page=1#pid1275560
为什么需要预加载场景?
一般我们的过图的时候很少考虑到预加载场景,所以我们在过图的时候经常会显示加载进度条等待场景加载完成,那么加载一些很大的场景的话就会让玩家等待很久的时间。但是在某一些项目有瞬间过图的需求的时候,那么我们就需要预加载场景了。当你需要切换场景的时候再把allowSceneActivation设置成true就成功进行了场景切换。
示例代码
//unity内置的场景加载
public
class
UnityBuiltSceneLoadAsync : SceneLoadAsync {
private
AsyncOperation sceneAsync =
null
;
public
UnityBuiltSceneLoadAsync(
string
scene_name,
bool
allowSceneActivation, Action<
float
> progressCallBack, Action loadCompleted) {
this
.sceneName = scene_name;
this
.progressCallBack = progressCallBack;
this
.loadCompleted = loadCompleted;
this
.allowSceneActivation = allowSceneActivation;
string
assetPath =
string
.Format(
"res/scenes/{0}.scene"
, scene_name);
Coroutine coroutine = Global.coroutine.Execute(LoadLevelBundle(scene_name, assetPath));
}
protected
override
IEnumerator LoadLevelBundle(
string
levelName,
string
assetPath) {
Global.coroutine.Execute(
base
.LoadLevelBundle(levelName, assetPath));
sceneAsync = Application.LoadLevelAsync(levelName);
sceneAsync.allowSceneActivation = allowSceneActivation;
float
progress = 0;
while
(!sceneAsync.isDone) {
progress = sceneAsync.progress;
if
(progress >= 0.9f) {
progress = 1;
assetProgresCallBacks[assetPath](assetPath, progress);
if
(
this
.loadCompleted !=
null
)
this
.loadCompleted();
this
.isDone =
true
;
LOG.Log(
"[UnityBuiltSceneLoadAsync-LoadLevelBundle] sceneAsync load isDone"
);
allowSceneActivation =
true
;
yield
break
;
}
yield
return
null
;
}
}
public
override
void
Unload(
bool
unloadAllLoadedObjects) {
base
.Unload(unloadAllLoadedObjects);
sceneAsync =
null
;
}
public
override
bool
allowSceneActivation {
get
{
return
base
.allowSceneActivation;
}
set
{
base
.allowSceneActivation = value;
LOG.Log(
"[UnityBuiltSceneLoadAsync-allowSceneActivation] allowSceneActivation="
+ value);
if
(sceneAsync !=
null
) {
sceneAsync.allowSceneActivation = value;
if
(value) {
if
(onSceneActiveBegin !=
null
)
onSceneActiveBegin(sceneName);
LOG.Log(
"[ActiveScene] "
+ sceneName);
}
}
}
}
protected
override
void
OnLoadSceneProgress(
string
assetPath,
float
progress) {
if
(
this
.progressCallBack !=
null
)
this
.progressCallBack(progress);
}
}
|
//ab资源的场景加载
public
class
AssetBundleSceneLoadAsync : SceneLoadAsync {
public
class
SceneAssetData {
private
UnityEngine.Object mainAsset_ =
null
;
private
AssetBundle assetBundle_ =
null
;
public
string
sceneName {
get
;
set
; }
public
string
assetName {
get
;
set
; }
public
Coroutine assetCoroutine {
get
;
set
; }
public
AssetBundle assetBundle {
get
{
return
assetBundle_; }
set
{
if
(value !=
null
) {
assetBundle_ = value;
mainAsset_ = assetBundle.Load(sceneName,
typeof
(GameObject));
if
(mainAsset_ !=
null
) {
if
((mainAsset_
as
GameObject) ==
null
) {
LOG.LogError(
string
.Format(
"场景加载出错,加载的AB资源{0}中资源{1}[{2}]的类型错误,请美术检查相应AB资源"
, assetName, sceneName, mainAsset_.GetType().Name));
}
}
else
if
(!assetName.EndsWith(
".scene"
))
LOG.LogError(
string
.Format(
"场景加载出错,加载的AB资源{0}中无{1}资源,请美术检查相应AB资源"
, assetName, sceneName));
}
}
}
public
UnityEngine.Object mainAsset {
get
{
return
mainAsset_;
}
}
public
SceneAssetData(
string
sceneName,
string
assetName, Coroutine assetCoroutine, AssetBundle assetBundle) {
this
.sceneName = sceneName;
this
.assetName = assetName;
this
.assetCoroutine = assetCoroutine;
this
.assetBundle = assetBundle;
}
public
void
Unload(
bool
unloadAllLoadedObjects) {
if
(assetCoroutine !=
null
) {
Global.coroutine.Stop(assetCoroutine);
assetCoroutine =
null
;
}
if
(assetBundle !=
null
)
assetBundle.Unload(unloadAllLoadedObjects);
//unloadAllLoadedObjects=false表示的是过完场景后对场景AB资源进行卸载
//unloadAllLoadedObjects=true表示对整个场景的预加载的卸载
if
(!unloadAllLoadedObjects && mainAsset !=
null
&& mainAsset
is
GameObject && !assetName.EndsWith(
".scene"
)) {
GameObject obj = UnityEngine.Object.Instantiate(mainAsset)
as
GameObject;
CombineAssetStatic(obj.transform);
}
}
private
void
CombineAssetStatic(Transform root) {
for
(
int
i = 0; i < root.childCount; i++) {
if
(root.GetChild(i).name ==
"static"
) {
StaticBatchingUtility.Combine(root.GetChild(i).gameObject);
}
}
}
}
private
Map<
string
, SceneAssetData> sceneAssets =
new
Map<
string
, SceneAssetData>();
private
Map<
string
,
float
> assetsProgressMap =
new
Map<
string
,
float
>();
public
AssetBundleSceneLoadAsync(
int
scene_id,
bool
allowSceneActivation, Action<
float
> progressCallBack, Action loadCompleted) {
MapReference mapref = Global.map_mgr.GetReference(scene_id);
this
.sceneName = mapref.FileName;
this
.progressCallBack = progressCallBack;
this
.loadCompleted = loadCompleted;
this
.allowSceneActivation = allowSceneActivation;
string
assetPath =
string
.Format(
"res/scenes/{0}.scene"
, sceneName);
Coroutine coroutine = Global.coroutine.Execute(LoadLevelBundle(sceneName, assetPath));
sceneAssets.Add(assetPath,
new
SceneAssetData(sceneName,assetPath, coroutine,
null
));
if
(!
string
.IsNullOrEmpty(mapref.ResPath)) {
assetPath =
string
.Format(
"res/scenes/{0}.go"
, mapref.ResPath);
coroutine = Global.coroutine.Execute(LoadLevelBundle(sceneName, assetPath));
sceneAssets.Add(assetPath,
new
SceneAssetData(sceneName, assetPath, coroutine,
null
));
}
}
protected
override
IEnumerator LoadLevelBundle(
string
levelName,
string
assetPath) {
Global.coroutine.Execute(
base
.LoadLevelBundle(levelName, assetPath));
WWW loadSceneWWW =
new
WWW(CDirectory.MakeFullPath(assetPath));
while
(!loadSceneWWW.isDone) {
assetProgresCallBacks[assetPath](assetPath, loadSceneWWW.progress);
yield
return
null
;
}
assetProgresCallBacks[assetPath](assetPath, 1.0f);
yield
return
loadSceneWWW;
if
(loadSceneWWW.error !=
null
) {
LOG.LogError(
"WWW download:"
+ loadSceneWWW.error +
" path : "
+ loadSceneWWW.url);
yield
break
;
}
if
(loadSceneWWW.isDone) {
sceneAssets[assetPath].assetBundle = loadSceneWWW.assetBundle;
loadSceneWWW.Dispose();
if
(isSceneLoadCompleted()) {
if
(loadCompleted !=
null
)
loadCompleted();
isDone =
true
;
allowSceneActivation = sceneActive;
}
}
}
private
bool
isSceneLoadCompleted() {
int
complateCount = 0;
for
(sceneAssets.Begin(); sceneAssets.Next(); ) {
if
(sceneAssets.Value.assetBundle !=
null
)
complateCount++;
}
return
complateCount == sceneAssets.Count && complateCount != 0;
}
public
override
void
Unload(
bool
unloadAllLoadedObjects) {
base
.Unload(unloadAllLoadedObjects);
for
(sceneAssets.Begin(); sceneAssets.Next(); ) {
sceneAssets.Value.Unload(unloadAllLoadedObjects);
}
sceneAssets.Clear();
assetsProgressMap.Clear();
}
public
override
bool
allowSceneActivation {
get
{
return
base
.allowSceneActivation;
}
set
{
base
.allowSceneActivation = value;
if
(value && isSceneLoadCompleted()) {
if
(onSceneActiveBegin !=
null
)
onSceneActiveBegin(sceneName);
Application.LoadLevel(sceneName);
LOG.Log(
"[ActiveScene] "
+ sceneName);
}
}
}
protected
override
void
OnLoadSceneProgress(
string
assetPath,
float
progress) {
if
(assetsProgressMap.ContainsKey(assetPath))
assetsProgressMap[assetPath] = progress;
else
assetsProgressMap.Add(assetPath, progress);
float
tempProgress = 0f;
for
(assetsProgressMap.Begin(); assetsProgressMap.Next(); ) {
tempProgress += assetsProgressMap.Value;
}
if
(
this
.progressCallBack !=
null
) {
this
.progressCallBack(tempProgress / assetsProgressMap.Count);
}
}
}
|