using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using UnityEngine;
using Debug = UnityEngine.Debug;

public class ResTest2 : MonoBehaviour
{
    private AssetBundleManifest abm;
    private List<string> absList = new List<string>();
    private List<AssetBundle> abs = new List<AssetBundle>();

    // Use this for initialization
    void Start()
    {
        StartCoroutine(LoadABM(ABMLoaded));
    }

    IEnumerator LoadABM(Action action)
    {
        WWW www = new WWW(Application.streamingAssetsPath + "/windows.t");
        yield return www;
        if (string.IsNullOrEmpty(www.error))
        {
            abm = www.assetBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
        }
        www.Dispose();
        www = null;
        if (action != null)
        {
            action();
        }
    }

    void ABMLoaded()
    {
        Debug.Log("ABM加载完成");
        LoadAllAB();
    }

    #region 测试整体的预加载耗时
    Stopwatch load = new Stopwatch();
    #endregion

    /// <summary>
    /// 没有依赖文件的AB
    /// </summary>
    Dictionary<string, AB> lABs = new Dictionary<string, AB>();
    /// <summary>
    /// 有依赖文件的AB
    /// </summary>
    Dictionary<string, AB> dABs = new Dictionary<string, AB>();

    /// <summary>
    /// 加载所有AB文件
    /// </summary>
    private void LoadAllAB()
    {
        #region 测试整体的预加载耗时
        load.Start();
        #endregion
        string[] abNames = abm.GetAllAssetBundles();
        Debug.LogWarning("AB总数:" + abNames.Length);
        foreach (string abName in abNames)
        {
            string[] dNames = abm.GetAllDependencies(abName);
            if (dNames != null && dNames.Length > 0)
            {
                AB ab = new AB();
                ab.name = abName;
                foreach (string dName in dNames)
                {
                    AB dAB = new AB();
                    dAB.name = dName;
                    ab.dABs.Add(dAB);
                }
                if (!dABs.ContainsKey(abName))
                {
                    dABs.Add(abName, ab);
                }
            }
            else
            {
                AB ab = new AB();
                ab.name = abName;
                if (!lABs.ContainsKey(abName))
                {
                    lABs.Add(abName, ab);
                }
            }
        }
        Debug.LogWarning("无依赖:" + lABs.Count);
        Debug.LogWarning("有依赖:" + dABs.Count); 
        labCount = lABs.Count;
        foreach (AB ab in lABs.Values)
        {
            StartCoroutine(LoadLAB(ab, OnLLoaded));
        }
    }

    private void OnLLoaded()
    { 
        Debug.LogWarning("无依赖的AB加载完毕");
        labCount = dABs.Count;
        foreach (AB ab in dABs.Values)
        {
            StartCoroutine(LoadLAB(ab, OnDLoaded));
        }
    }

    private void OnDLoaded()
    {
        #region 测试预加载整体耗时
        load.Stop();
        Debug.LogWarning("加载耗时:" + load.ElapsedMilliseconds);
        load.Reset();
        #endregion 
        Debug.LogWarning("有依赖的AB加载完毕");

        LoadABI("lobby.ui.lobbyroot", null);
    }

    /// <summary>
    /// 无依赖的ab数
    /// </summary>
    private int labCount = 0;
    /// <summary>
    /// 已加载的无依赖ab数
    /// </summary>
    private int lloadedCount = 0;
    /// <summary>
    /// 加载无依赖的AB
    /// </summary>
    /// <param name="abName"></param>
    /// <param name="action"></param>
    /// <returns></returns>
    private IEnumerator LoadLAB(AB ab, Action action)
    {
        WWW www = new WWW(Application.streamingAssetsPath + "/" + ab.name + ".t");
        yield return www;
        if (string.IsNullOrEmpty(www.error))
        {
            AssetBundle assetBundle = www.assetBundle;
            ab.ab = assetBundle;
            ab.isLoaded = true;
            www.Dispose();
            www = null;
            lloadedCount += 1;
            if (lloadedCount == labCount)
            {
                labCount = 0;
                lloadedCount = 0;
                if (action != null)
                {
                    action();
                }
            }
        }
        else
        {
            Debug.LogWarning("www.error:" + www.error);
        }
    }

    private void LoadABI(string abName, Action action)
    {
        #region 测试整体的预加载耗时
        load.Start();
        #endregion
        AB ab = null;
        dABs.TryGetValue(abName, out ab);
        if (ab != null)
        {
            UnityEngine.Object[] assets = ab.ab.LoadAllAssets();
            GameObject go = Instantiate(assets[0]) as GameObject;
        }
        #region 测试预加载整体耗时
        load.Stop();
        Debug.LogWarning("加载耗时:" + load.ElapsedMilliseconds);
        load.Reset();
        #endregion 
        //WWW www = new WWW(Application.streamingAssetsPath + "/" + abName + ".t");
        //yield return www;
        //if (string.IsNullOrEmpty(www.error))
        //{
        //    AssetBundle ab = www.assetBundle;
        //    abs.Add(ab);
        //    UnityEngine.Object[] assets = ab.LoadAllAssets();
        //    www.Dispose();
        //    www = null;
        //    absList.Add(abName);
        //    GameObject go = Instantiate(assets[0]) as GameObject;
        //    yield return new WaitForEndOfFrame();
        //}
    }

    private void OnApplicationQuit()
    {
        for (int i = 0; i < abs.Count; i++)
        {
            abs[i].Unload(true);
            abs[i] = null;
        }
        abs.Clear();
        absList.Clear();
        Resources.UnloadUnusedAssets();
    }
}

using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// AssetBundle Item
/// </summary>
public class AB
{
    /// <summary>
    /// abname
    /// </summary>
    public string name = "";
    public AssetBundle ab = null;
    /// <summary>
    /// 依赖文件
    /// </summary>
    public List<AB> dABs = new List<AB>();
    /// <summary>
    /// 是否已加载
    /// </summary>
    public bool isLoaded = false;
} 

TIM截图20191011121521.jpg

using System;
using System.IO;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Internal;
using Microsoft.AspNetCore.Mvc;

namespace WebApplication1.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class UpLoadController : ControllerBase
    {
        private readonly IHostingEnvironment _hostingEnvironment;

        public UpLoadController(IHostingEnvironment hostingEnvironment)
        {
            _hostingEnvironment = hostingEnvironment;
        }

        [HttpPost]
        public string Post([FromForm] IFormCollection formCollection)
        {
            string result = "";
            string webRootPath = _hostingEnvironment.ContentRootPath;
            string contentRootPath = _hostingEnvironment.ContentRootPath;

            FormFileCollection filelist = (FormFileCollection)formCollection.Files;

            foreach (IFormFile file in filelist)
            {
                String Tpath = "/" + DateTime.Now.ToString("yyyy-MM-dd") + "/";
                string name = file.FileName;
                string FileName = DateTime.Now.ToString("yyyyMMddHHmmssfff");
                string FilePath = webRootPath + Tpath;

                string type = Path.GetExtension(name);
                DirectoryInfo di = new DirectoryInfo(FilePath);

                if (!di.Exists)
                {
                    di.Create();
                }

                using (FileStream fs = System.IO.File.Create(FilePath + FileName + type))
                {
                    // 复制文件
                    file.CopyTo(fs);
                    // 清空缓冲区数据
                    fs.Flush();
                }
                result = "1";
            }
            return result;
        }
    }
}

Unity中调用

    private IEnumerator UpLoadImg(string filePath)
    {   
        byte[] bs = File.ReadAllBytes(filePath); 
        Log.Debug("bs.Length:" + bs.Length.ToString());  
        WWWForm test = new WWWForm();
        test.AddBinaryData("imgbase.jpg", bs, "imgbase.jpg");
        WWW www = new WWW("http://192.168.2.185/api/upload", test);
        yield return www;
        Log.Debug(www.text);
    }

1、Failed building wheel for pyaudio
使用 sudo apt-get install python-pyaudio python3-pyaudio安装
2、TypeError: unsupported operand type(s) for -=: 'Retry' and 'int'
安装超时,最简单解决方案:pip --default-timeout=5000 install
3、FileNotFoundError: [Errno 2] No such file or directory: 'fswebcam': 'fswebcam'
安装fswebcam sudo apt-get install fswebcam

img.jpg

using Net.Media;
using System;
using System.IO;
using System.Runtime.InteropServices;
using UnityEngine;

public class Test : MonoBehaviour
{
    //视频宽
    public int width = 1024;
    //视频高
    public int height = 768;
    public Texture2D texture;
    public Material mat;
    IntPtr libvlc_instance_t;
    IntPtr libvlc_media_player_t;
    IntPtr handle;

    private VideoLockCB _videoLockCB;
    private VideoUnlockCB _videoUnlockCB;
    private VideoDisplayCB _videoDisplayCB;

    private int _pixelBytes = 4;
    private int _pitch;
    private IntPtr _buff = IntPtr.Zero;
    bool ready = false;

    string snapShotpath;
    // Use this for initialization
    void Start()
    {
        Loom.Initialize();
        snapShotpath = "file:///" + Application.streamingAssetsPath;

        _videoLockCB += VideoLockCallBack;

        _videoUnlockCB += VideoUnlockCallBack;

        _videoDisplayCB += VideoDiplayCallBack;


        handle = new IntPtr(1);

        libvlc_instance_t = MediaPlayer.Create_Media_Instance();

        libvlc_media_player_t = MediaPlayer.Create_MediaPlayer(libvlc_instance_t, handle);
        //湖南卫视直播地址
        string videoPath = "rtmp://58.200.131.2:1935/livetv/hunantv";
        //本地视频地址
        //string videoPath = "file:///" + Application.streamingAssetsPath + "/test.mp4";
        bool state = MediaPlayer.SetLocation(libvlc_instance_t, libvlc_media_player_t, videoPath);
        Debug.Log("state:" + state);
        width = MediaPlayer.GetMediaWidth(libvlc_media_player_t);
        Debug.Log("width: " + width);
        height = MediaPlayer.GetMediaHeight(libvlc_media_player_t);
        Debug.Log("height: " + height);
        //网络地址不晓得怎么拿到视频宽高
        if(width==0&&height==0)
        {
            width = 1024;
            height = 576;
        }
        _pitch = width * _pixelBytes;
        _buff = Marshal.AllocHGlobal(_pitch * height);
        texture = new Texture2D(width, height, TextureFormat.RGBA32, false);
        mat.mainTexture = texture;

        MediaPlayer.SetCallbacks(libvlc_media_player_t, _videoLockCB, _videoUnlockCB, _videoDisplayCB, IntPtr.Zero);
        MediaPlayer.SetFormart(libvlc_media_player_t, "ARGB", width, height, _pitch);

        ready = MediaPlayer.MediaPlayer_Play(libvlc_media_player_t);
        Debug.Log("ready:" + ready);

        Debug.Log(MediaPlayer.MediaPlayer_IsPlaying(libvlc_media_player_t));
    }


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

    }

    private void FixedUpdate()
    {

    }

    private void OnGUI()
    {
        if (GUI.Button(new Rect(0, 0, 100, 100), "Take"))
        {
            Debug.Log("snapShotpath:" + snapShotpath);
            Debug.Log("@snapShotpath:" + @snapShotpath);
            //vlc截图未解决 用Unity保存帧图,画面是上下反转左右反转的
            //Debug.Log(MediaPlayer.TakeSnapShot(libvlc_media_player_t, snapShotpath, "testa.jpg", width, height));
            byte[] bs = texture.EncodeToJPG();
            File.WriteAllBytes(Application.streamingAssetsPath + "/test.jpg", bs);
        }

    }

    private IntPtr VideoLockCallBack(IntPtr opaque, IntPtr planes)
    {
        Lock(); 
        Marshal.WriteIntPtr(planes, 0, _buff);
        Loom.QueueOnMainThread(() =>
        {
            texture.LoadRawTextureData(_buff, _buff.ToInt32());
            texture.Apply();
        });
        return IntPtr.Zero;
    }

    private void VideoDiplayCallBack(IntPtr opaque, IntPtr picture)
    { 
        
    }

    private void VideoUnlockCallBack(IntPtr opaque, IntPtr picture, IntPtr planes)
    { 
        Unlock();
    }
     
    bool obj = false;
    private void Lock()
    {
        obj = true;
    }
    private void Unlock()
    {
        obj = false;
    }
    private bool Islock()
    {
        return obj;
    }

    private void OnDestroy()
    {

    }

    private void OnApplicationFocus(bool focus)
    {

    }

    private void OnApplicationQuit()
    {
        try
        {
            if (MediaPlayer.MediaPlayer_IsPlaying(libvlc_media_player_t))
            {
                MediaPlayer.MediaPlayer_Stop(libvlc_media_player_t);
            }

            MediaPlayer.Release_MediaPlayer(libvlc_media_player_t);

            MediaPlayer.Release_Media_Instance(libvlc_instance_t); 
        }
        catch (Exception e)
        {
            Debug.Log(e.Message);
        }
    }
}

工程地址https://gitee.com/awnuxcvbn/UnityVLC

目前有截图、点击的功能,其他只有测试(划屏,装软件,输入中文)代码,需要修改

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI;

public class Main : MonoBehaviour
{
    private string adbPath;
    private string filePath;
    /// <summary>
    /// 列出设备按钮
    /// </summary>
    public Button btnList;

    public Transform togglePrefab;

    /// <summary>
    /// 所有设备
    /// </summary>
    Dictionary<string, GameObject> advs = new Dictionary<string, GameObject>();
    /// <summary>
    /// 选中的设备
    /// </summary>
    public List<string> sdvs = new List<string>();

    public InputField inputFieldX;
    public InputField inputFieldY;
    /// <summary>
    /// 点击指定位置按钮
    /// </summary>
    public Button btnClick;
    public Image screenImage;
    public Button btnCapture;
    public Button getCapture;

    private void Awake()
    {
        Loom.Initialize();
    }

    // Use this for initialization
    void Start()
    {
        adbPath = @Application.streamingAssetsPath + "/adb.exe";
        filePath = @Application.streamingAssetsPath;
        btnList.onClick.AddListener(ClickList);
        togglePrefab.gameObject.SetActive(false);
        btnClick.onClick.AddListener(ClickPose);
        btnCapture.onClick.AddListener(Capture);
    }

    string StartProcess(string args, Action action)
    {
        Process process = new Process();
        process.StartInfo.FileName = adbPath;
        process.StartInfo.Arguments = args;
        process.StartInfo.CreateNoWindow = true;
        process.StartInfo.UseShellExecute = false;
        process.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
        process.StartInfo.RedirectStandardInput = true;
        process.StartInfo.RedirectStandardOutput = true;
        process.StartInfo.RedirectStandardError = true;
        process.StartInfo.StandardOutputEncoding = Encoding.UTF8;
        process.Start();
        process.WaitForExit();
        if (action != null)
        {
            action();
        }
        return process.StandardOutput.ReadToEnd();
    }

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

    }

    private void OnGUI()
    {
        //if (GUI.Button(new Rect(0, 0, 200, 50), "列出设备"))
        //{
        //    string args = "devices";
        //    UnityEngine.Debug.Log(StartProcess(args));
        //}
        //if (GUI.Button(new Rect(500, 50, 200, 50), "点击"))
        //{
        //    string args = "-s de81f1c shell input tap 400 400";
        //    UnityEngine.Debug.Log(StartProcess(args));
        //}
        //if (GUI.Button(new Rect(500, 100, 200, 50), "手机截屏"))
        //{
        //    string args = "-s de81f1c shell screencap -p /sdcard/screenshot.jpg";
        //    UnityEngine.Debug.Log(StartProcess(args));
        //}
        //if (GUI.Button(new Rect(500, 150, 200, 50), "获取截屏"))
        //{
        //    string args = "-s de81f1c pull /sdcard/screenshot.jpg " + @Application.streamingAssetsPath + "/screenshot.jpg";
        //    UnityEngine.Debug.Log(StartProcess(args));
        //}
        //if (GUI.Button(new Rect(500, 200, 200, 50), "划屏"))
        //{
        //    string args = "-s de81f1c shell input swipe 800 300 200 300";
        //    UnityEngine.Debug.Log(StartProcess(args));
        //}
        //if (GUI.Button(new Rect(500, 250, 200, 50), "安装ADB键盘"))
        //{
        //    string args = "-s 127.0.0.1:62001 install " + Application.streamingAssetsPath + "/ADBKeyboard.apk";
        //    UnityEngine.Debug.Log(StartProcess(args));
        //}
        //if (GUI.Button(new Rect(500, 300, 200, 50), "设置ADB默认键盘"))
        //{
        //    string args = "-s 127.0.0.1:62001 shell ime set com.android.adbkeyboard/.AdbIME";
        //    UnityEngine.Debug.Log(StartProcess(args));
        //}
        //if (GUI.Button(new Rect(500, 350, 200, 50), "输入文字"))
        //{
        //    string args = "-s 127.0.0.1:62001 shell am broadcast -a ADB_INPUT_TEXT --es msg '曹尼玛终于出中文了!'";
        //    UnityEngine.Debug.Log(StartProcess(args));
        //}

    }

    void ClickList()
    {
        string args = "devices";
        string opt = StartProcess(args, null);
        List<string> list = opt.Split(new string[] { "\r\n" }, StringSplitOptions.None).ToList();
        list = list.Where(s => !string.IsNullOrEmpty(s)).ToList();
        if (list.Count < 2)
        {
            return;
        }
        for (int i = 1; i < list.Count; i++)
        {
            string[] dns = list[i].Split('\t');
            string id = dns[0];
            string name = dns[1];
            if (advs.ContainsKey(id))
            {
                continue;
            }
            Transform item = CreateItem(togglePrefab);
            item.Find("Label").GetComponent<Text>().text = "设备ID:" + id + "  设备名:" + name;
            item.name = dns[0];
            item.GetComponent<Toggle>().onValueChanged.AddListener(state => { ToggleClick(state, item); });
            item.gameObject.SetActive(true);
            advs.Add(id, item.gameObject);
        }
        UnityEngine.Debug.Log(opt);
    }

    void ToggleClick(bool state, Transform go)
    {
        if (state)
        {
            sdvs.Add(go.name);
        }
        else
        {
            sdvs.Remove(go.name);
        }
    }

    /// <summary>
    /// 点击
    /// </summary>
    void ClickPose()
    {
        for (int i = 0; i < sdvs.Count; i++)
        {
            string args = "-s " + sdvs[i] + " shell input tap " + inputFieldX.text + " " + inputFieldY.text;
            Loom.RunAsync(() =>
            {
                string opt = StartProcess(args, Capture);
                UnityEngine.Debug.Log(opt);
            });
        }
    }

    /// <summary>
    /// 截图
    /// </summary>
    void Capture()
    {
        for (int i = 0; i < sdvs.Count; i++)
        {
            string args = "-s " + sdvs[i] + " shell screencap -p /sdcard/screenshot.jpg";
            Loom.RunAsync(() =>
            {
                string opt = StartProcess(args, GetCapture);
                UnityEngine.Debug.Log(opt);
            });
        }
    }

    /// <summary>
    /// 获取截图
    /// </summary>
    void GetCapture()
    {
        for (int i = 0; i < sdvs.Count; i++)
        {
            string args = "-s " + sdvs[i] + " pull /sdcard/screenshot.jpg " + filePath + "/screenshot.jpg";
            Loom.RunAsync(() =>
            {
                string opt = StartProcess(args, ShowCapture);
                UnityEngine.Debug.Log(opt);
            });
        }
    }

    /// <summary>
    /// 显示截图
    /// </summary>
    void ShowCapture()
    {
        Loom.QueueOnMainThread(() =>
        {
            StartCoroutine(LoadImg());
        });
    }

    /// <summary>
    /// 加载图片
    /// </summary>
    /// <returns></returns>
    IEnumerator LoadImg()
    {
        WWW www = new WWW("file:///" + filePath + "/screenshot.jpg");
        yield return www;
        Sprite sprite = Sprite.Create(www.texture,new Rect(0, 0, www.texture.width, www.texture.height), Vector2.zero);
        screenImage.sprite = sprite;
        www.Dispose();
        www = null;
    }

    private Transform CreateItem(Transform prefab)
    {
        Transform item = Instantiate(prefab);
        item.SetParent(prefab.parent);
        item.localPosition = Vector3.zero;
        item.localScale = new Vector3(1, 1, 1);
        return item;
    }

    private void OnApplicationQuit()
    {

    }
}

TIM截图20190321164754.jpg

工程地址https://gitee.com/awnuxcvbn/GroupControl