Hololens开发(11) WCF接收通用回调处理

1.生成问题(泛型脚本导致的)

接刚刚的Hololens开发(10),因为给每个返回消息都写Update脚本麻烦,打算写一个通用的脚本。

写好了,重新打包。打包好后,生成hololens发布,突然不能生成了。

Severity	Code	Description	Project	File	Line	Suppression State
Error		The command ""D:\SoftwareProjects\Hololens\UnityProjects\NoToolkit\NoToolkit\bin\Unity\Tools\AssemblyConverter.exe" -platform=uap -lock="D:\SoftwareProjects\Hololens\UnityProjects\NoToolkit\NoToolkit\bin\NoToolkit\project.lock.json" -bits=32 -configuration=Release -removeDebuggableAttribute=False -uwpsdk=10.0.10586.0 -path="." -path="C:\Program Files\Unity5.6\Editor\Data\PlaybackEngines\MetroSupport\Players\UAP\dotnet\x86\Release" "D:\SoftwareProjects\Hololens\UnityProjects\NoToolkit\NoToolkit\bin\NoToolkit\Assembly-CSharp.dll" "D:\SoftwareProjects\Hololens\UnityProjects\NoToolkit\NoToolkit\bin\NoToolkit\Assembly-CSharp-firstpass.dll" "D:\SoftwareProjects\Hololens\UnityProjects\NoToolkit\NoToolkit\bin\NoToolkit\Assembly-UnityScript.dll" "D:\SoftwareProjects\Hololens\UnityProjects\NoToolkit\NoToolkit\bin\NoToolkit\UnityEngine.dll" "D:\SoftwareProjects\Hololens\UnityProjects\NoToolkit\NoToolkit\bin\NoToolkit\nunit.framework.dll" "D:\SoftwareProjects\Hololens\UnityProjects\NoToolkit\NoToolkit\bin\NoToolkit\UnityEngine.UI.dll" "D:\SoftwareProjects\Hololens\UnityProjects\NoToolkit\NoToolkit\bin\NoToolkit\UnityEngine.HoloLens.dll" "D:\SoftwareProjects\Hololens\UnityProjects\NoToolkit\NoToolkit\bin\NoToolkit\UnityEngine.Networking.dll" "D:\SoftwareProjects\Hololens\UnityProjects\NoToolkit\NoToolkit\bin\NoToolkit\UnityEngine.VR.dll"" exited with code 1.	NoToolkit	D:\SoftwareProjects\Hololens\UnityProjects\NoToolkit\NoToolkit\bin\NoToolkit\NoToolkit.csproj	358	
 这个提示和在以前刚刚开始时,用VS2017打开的问题一样。但是,其他项目都好好的,
刚刚(虽然中间去开了个很久的会)也是能正常打包的。

原因是出在我刚刚写的脚本上?

将相关脚本注释掉,也不行。


和其他项目比较一下,多了个Assembly-UnityScript.dll相关的东西。

查了一下Assembly-UnityScript.dll是UnityScript(脚本语言)的相关dll,把他删除看看。

先把启动项目中的dll删除了, 引用删了,然后把项目文件中的AssemblyConverter.exe那里的也删了


生成,出了个问题


把obj文件夹删除,也没用,生成还是有。


在Unity项目中把“可疑的”文件删除,多了个Editor文件夹,似乎是点击Test Runner时产生的,把WSATestCertificate也删除,把JavaScript脚本文件删除。重新生成一个新的位置。

可以生成了。

但是,后来再加上这些可以的文件,还是可以的。

奇怪了。

结论是,是某个文件导致的,但是哪个?什么原因不知道。总之下次再碰到,再找一找。


===============================================

后来发现是泛型脚本不行

using System;
using UnityEngine;

public class TaskManager : MonoBehaviour {

    public static TaskManager Instance;

    void Awake()
    {
        Instance = this;
    }

    public void Add<T>(Action<T> action, T arg)
    {
        TaskScript<T> task = gameObject.AddComponent<TaskScript<T>>();
        task.Action = action;
        task.Arg = arg;
    }
}

public class TaskScript<T> : MonoBehaviour
{
    public Action<T> Action;

    public T Arg;
    void Start()
    {
        if (Action != null)
        {
            Action.Invoke(Arg);
        }
    }
}

这里的TaskScript<T>不能用,仅仅是定义不会有影响,

TaskScript<T> task = gameObject.AddComponent<TaskScript<T>>();
这句话加上就会有问题,不能生成。

语法上没问题,生成时就报错了。

关键是错误里面根本就没说清楚。
AssemblyConverter.exe .....什么的

另外这说明AssemblyConverter.exe的问题,是Unity自身运行脚本时会出的任何问题导致的。


在Unity中测试了一下泛型脚本

using UnityEngine;

public class GenericScript<T> : MonoBehaviour {

    public T Data;

	// Use this for initialization
	void Start () {
        Debug.Log("GenericScript:" + typeof(T));
	}
}
using UnityEngine;

public class GenericScriptUse : MonoBehaviour {

	// Use this for initialization
	void Start () {
        GenericScript<int> script = gameObject.AddComponent<GenericScript<int>>();
        script.Data = 10;
    }
}
结果是:



那不用泛型就好了,说白了把需要用到的类型具体指定就好了。

using System;
using UnityEngine;

public class TaskManager : MonoBehaviour {

    public static TaskManager Instance;

    void Awake()
    {
        Instance = this;
    }

    public void AddActionString(Action<string> action, string arg)
    {
        TaskScriptString task = gameObject.AddComponent<TaskScriptString>();
        task.Action = action;
        task.Arg = arg;
    }

    public void AddActionInt(Action<int> action, int arg)
    {
        TaskScriptInt task = gameObject.AddComponent<TaskScriptInt>();
        task.Action = action;
        task.Arg = arg;
    }
}

public class TaskScriptString : MonoBehaviour
{
    public Action<string> Action;

    public string Arg;
    void Start()
    {
        if (Action != null)
        {
            Action.Invoke(Arg);
        }
    }
}
public class TaskScriptInt : MonoBehaviour
{
    public Action<int> Action;

    public int Arg;
    void Start()
    {
        if (Action != null)
        {
            Action.Invoke(Arg);
        }
    }
}
        public void ReceiveString(int count, Action<string> callback)
        {
            if (Client != null)
            {
                Client.ReceiveString(count, msg=> {
                    TaskManager.Instance.AddActionString(callback, msg);
                });
            }
            else
            {
                Debug.Log("WCFClientFactory.RecevieString");
                if (callback != null)
                {
                    callback("");
                }
            }
        }
但是!实际上这样虽然能生成, 运行时也是不行的,因为回调函数函数中用了gameObject

结果是抛出异常:

UnityEngine.UnityException: get_gameObject can only be called from the main thread.

改成

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

public class TaskManager : MonoBehaviour {

    public static TaskManager Instance;

    public List<Action> Tasks=new List<Action>();

    public bool IsDirty;

    void Awake()
    {
        Instance = this;
    }

    void Update()
    {
        if (IsDirty)
        {
            foreach (Action action in Tasks)
            {
                if (action != null)
                {
                    action.Invoke();
                }
            }
            Tasks.Clear();
            IsDirty = false;
        }
    }

    public void AddTask<T>(Action<T> action, T arg)
    {
        IsDirty = true;
        Tasks.Add(() =>
        {
            if (action != null)
            {
                action(arg);
            }
        });
    }
}

这里的Tasks是无法直接添加action的,要通过一个匿名函数再封装一下。

调用的地方:

        public void ReceiveString(int count, Action<string> callback)
        {
            if (Client != null)
            {
                //Client.ReceiveString(count, callback);

                Client.ReceiveString(count, msg =>
                {
                    TaskManager.Instance.AddTask(callback, msg);
                });
            }
            else
            {
                Debug.Log("WCFClientFactory.RecevieString");
                if (callback != null)
                {
                    callback("");
                }
            }
        }

这样以后在Client中处理回调函数用TaskManager调用一下就好了,不用每种回调处理都写一个脚本在Update中调用了。


然后打包测试,Hololens中启动,界面闪一下,就退出了。

App.cs的代码运行没问题,就是无法进入Unity。
怎么修改脚本都没用。

Unity重新生成一下Hololens项目,可以了。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值