从asssetBundle加载的预制可以传递给Vuforia AnchorBehavior声明(Ca

2019-09-27 00:14发布

我们的目标是一个两步过程,其中在接地面Vuforia对象的预制选自AssetBundle加载,并在为了将游戏物体传递给AnchorBehavior变量声明。

而我的道歉,如果作为一个新人到Unity C#我不像我想的准确

想尽各种办法等号加载预制的AnchorBehavior。 但因为这是两个类型的对象,出现错误表明这些不能隐等于

声明如下:

public PlaneFinderBehaviour plane;
public ContentPositioningBehaviour planeFinder;
public AnchorBehaviour model;
public string nameOfAssetBundle;
public string nameOfObjectToLoad;

想法是通过“nameOfObjectToLoad”表示预制并把它传递到“AnchorBehavior”值,则可以使用下面的方法“的onClick”,当脚本被附加到按钮。

public void create()
{
    planeFinder.AnchorStage = model.GetComponent<AnchorBehaviour>();
}

人们期望的是,预制会被传递到AnchorBehavior和实例预制“的onClick”

下面是从中提取这些片段的完整剧本。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Vuforia;

public class anchorManagerBundles : MonoBehaviour
{
    public PlaneFinderBehaviour plane;
    public ContentPositioningBehaviour planeFinder;
    public AnchorBehaviour model;
    public string nameOfAssetBundle;
    public string nameOfObjectToLoad;

    void Start()
    {
        StartCoroutine(LoadAsset(nameOfAssetBundle, nameOfObjectToLoad));
    } 

    IEnumerator LoadAsset(string assetBundleName, string objectNameToLoad)
    {
        string filePath = System.IO.Path.Combine(Application.streamingAssetsPath, "AssetBundles");
        filePath = System.IO.Path.Combine(filePath, assetBundleName);

        //Load "nameOfAssetBundle" AssetBundle
        var assetBundleCreateRequest = AssetBundle.LoadFromFileAsync(filePath);
        yield return assetBundleCreateRequest;

        AssetBundle assetBundle = assetBundleCreateRequest.assetBundle;

        //Load the "nameOfOjectToLoad" Asset (Use Texture2D since it's a Texture. Use GameObject if prefab)
        AssetBundleRequest asset = assetBundle.LoadAssetAsync<GameObject>(objectNameToLoad);
        yield return asset;

        //Retrieve the object (Use Texture2D since it's a Texture. Use GameObject if prefab)
        GameObject loadedAsset = asset.asset as GameObject;

        //Do something with the loaded loadedAsset  object (Load to RawImage for example) 
        //model = loadedAsset;
    }
    public void create()
    {
        planeFinder.AnchorStage = model.GetComponent<AnchorBehaviour>();
    }

}

进一步的研究揭示我的新手技能。 最终意图,的“模型= loadedAsset;” 是,我试图直接从一种数据类型转换为另一种,不能明确地进行。 但迄今为止,我的研究并没有发现从AssetBundle需要加载的预制和饲料它的AnchorBehaviour变量的手段。

如果任何人有办法对这种数据类型之间的转换的经验,在你的指导是非常赞赏。

更新通过正确铸造的声明,被淘汰的转换错误。

model = (asset.asset as AnchorBehaviour);

但现在我有一个在NullReference错误,说明我没能正确申报的价值,在这条线

    {
        planeFinder.AnchorStage = model.GetComponent<AnchorBehaviour>();
    }

这是我现在新的困境,因为我不知道在那里我有未能正确声明变量。

当AnchorBehaviour变量设置为私有更新解决了这个错误。 所以,现在的脚本编译,但不能产生预期的结果。 这可能指向一个需要改变如何如IEnumerator的部分所述加载AssetBundle组件。 统一控制台打印出以下日志评论

There is no content to place at the anchor. Set the "Anchor Stage" field to the content you wish to place.
UnityEngine.Debug:LogError(Object)

所有的意见后,这里是脚本最新,不幸的是不把从AssetBundle内容。 对我而言更多的研究和测试,我可以看到。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Vuforia;

public class anchorManagerBundles : MonoBehaviour
{
    public PlaneFinderBehaviour plane;
    public ContentPositioningBehaviour planeFinder;
    private AnchorBehaviour model;
    public string nameOfAssetBundle;
    public string nameOfObjectToLoad;
    private static bool alreadyLoading;
    private static AssetBundle assetBundle;

    void Start()
    {
        // only load the bundle once
        if (!alreadyLoading)
        {
            // set the flag to make sure this is never done again
            alreadyLoading = true;
            StartCoroutine(LoadAsset(nameOfAssetBundle, nameOfObjectToLoad));
        }
        else
        {
            LoadObjectFromBundle(nameOfObjectToLoad);
        }
    }

    private IEnumerator LoadAsset(string assetBundleName, string objectNameToLoad)
    {
        string filePath = System.IO.Path.Combine(Application.streamingAssetsPath, "AssetBundles");
        filePath = System.IO.Path.Combine(filePath, assetBundleName);

        if (assetBundle == null) 
        { 
            var assetBundleCreateRequest = AssetBundle.LoadFromFileAsync(filePath); 
            yield return assetBundleCreateRequest; assetBundle = assetBundleCreateRequest.assetBundle; 
        }

    private IEnumerator LoadObjectFromBundle(string objectNameToLoad)
    {
        AssetBundleRequest assetRequest = assetBundle.LoadAssetAsync<GameObject>(objectNameToLoad);
        yield return assetRequest;

        GameObject loadedAsset = (GameObject)assetRequest.asset;

        model = loadedAsset.GetComponent<AnchorBehaviour>();
    }

    public void create()
    {
        planeFinder.AnchorStage = model;
    }
}

添加if语句的资产,它编译罚款后,我继续有“模型”(AnchorBehavior /锚阶段)字段需要有一个价值的控制台警报。 如此看来,剧本是什么或者不传入“nameOfObjectToLoad”现场宣布AssetBundle对象,或者什么是传球不匹配。 因此,对于相同的解释,我暂时取得了“模式”领域的公众和手动填充字段。 你会看到它标识了预制作为一个“AnchorBehavior”对象。 按钮价值观编辑器-期望的结果

这是在编辑器控制台完整的错误试图将对象时。

There is no content to place at the anchor. Set the "Anchor Stage" field to the content you wish to place.
UnityEngine.Debug:LogError(Object)
Vuforia.ContentPositioningBehaviour:CreateAnchorAndPlaceContent(Func`2, Vector3, Quaternion)
Vuforia.ContentPositioningBehaviour:PositionContentAtPlaneAnchor(HitTestResult)
UnityEngine.Events.UnityEvent`1:Invoke(HitTestResult)
Vuforia.PlaneFinderBehaviour:PerformHitTest(Vector2)
UnityEngine.Events.UnityEvent`1:Invoke(Vector2)
Vuforia.AnchorInputListenerBehaviour:Update()

在努力进一步调试问题,我ammended以下部分这一点。

        if (assetBundle == null)
        {
            Debug.Log("Failed to Load assetBundle!!");
            yield break;
        }

其目的是试图确定是否AssetBundle实际上被加载。 这是非常有用的,但它产生的一个非常奇怪的结果,为此,我会征求建议。

此脚本连接到一系列按钮,使得按钮被点击时,则create()函数用于基于变量来实例化预制。

这些按钮在3个不同的UI面板分组。 所选择的小组用户点击按钮以暴露欲望按钮面板。

什么是很奇怪的是,当用户点击面板选择按钮,下面的错误放置在编辑器中登录。 这是一个有附加的脚本已被点击的实际按钮之前。

在面板按钮点击

Failed to Load assetBundle!!
UnityEngine.Debug:Log(Object)
<LoadAsset>d__8:MoveNext() (at Assets/Scripts/anchorManagerBundles.cs:38)
UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator)
anchorManagerBundles:Start() (at Assets/Scripts/anchorManagerBundles.cs:23)

在按钮单击(附加脚本按钮)

There is no content to place at the anchor. Set the "Anchor Stage" field to the content you wish to place.
UnityEngine.Debug:LogError(Object)
Vuforia.ContentPositioningBehaviour:CreateAnchorAndPlaceContent(Func`2, Vector3, Quaternion)
Vuforia.ContentPositioningBehaviour:PositionContentAtPlaneAnchor(HitTestResult)
UnityEngine.Events.UnityEvent`1:Invoke(HitTestResult)
Vuforia.PlaneFinderBehaviour:PerformHitTest(Vector2)
UnityEngine.Events.UnityEvent`1:Invoke(Vector2)
Vuforia.AnchorInputListenerBehaviour:Update()

我不明白为什么脚本被在面板按钮,它不具有附加脚本的点击调用。

任何建议最看重的是对这个令人费解的问题。

Answer 1:

结帐AssetBundle.LoadAssetAsync

5.0版本之前,用户可以直接提取使用LoadAsync各个组件。 这是不支持了。 相反,请使用LoadAssetAsync先加载游戏的对象,然后查找对象的组件。


你不能简单的类型转换检索到的GameObject参照AnchorBehaviour参考。 相反,你必须使用GetComponent


所以,你应该做的是什么

AssetBundleRequest assetRequest = assetBundle.LoadAssetAsync<GameObject>(objectNameToLoad);
yield return assetRequest;

GameObject loadedAsset = (GameObject)assetRequest.asset;

// since model is already of type AnchorBehaviour
// you should do the GetComponent already here
model = loadedAsset.GetComponent<AnchorBehavior>();

现在,你已经有了类的参考AnchorBehaviour第二GetComponent电话是多余的,因为它返回相同的参考。 所以现在只能用

public void create()
{
    planeFinder.AnchorStage = model;
}

如果你有这样的脚本它可能是有意义的加载assetBundle的多个实例,只有一次像

private static bool alreadyLoading;
private static AssetBundle assetBundle;

void Start()
{
    // only load the bundle once
    if(!alreadyLoading) 
    {
        // set the flag to make sure this is never done again
        alreadyLoading = true;
        StartCoroutine(LoadAsset(nameOfAssetBundle, nameOfObjectToLoad));
    }
    else
    {
        LoadObjectFromBundle(nameOfOjectToLoad);
    }
} 

private IEnumerator LoadAsset(string assetBundleName, string objectNameToLoad)
{
    string filePath = System.IO.Path.Combine(Application.streamingAssetsPath, "AssetBundles");
    filePath = System.IO.Path.Combine(filePath, assetBundleName);

    var assetBundleCreateRequest = AssetBundle.LoadFromFileAsync(filePath);
    yield return assetBundleCreateRequest;

    assetBundle = assetBundleCreateRequest.assetBundle;

    LoadObjectFromBundle(objectNameToLoad);
}

private IEnumerator LoadObjectFromBundle(string objectNameToLoad)
{
    AssetBundleRequest assetRequest = assetBundle.LoadAssetAsync<GameObject>(objectNameToLoad);
    yield return assetRequest;

    GameObject loadedAsset = (GameObject)assetRequest.asset;

    model = loadedAsset.GetComponent<AnchorBehavior>();
}


文章来源: Can a Prefab loaded from asssetBundle be passed to Vuforia AnchorBehavior declaration