当前位置: 首页 > news >正文

unity 读取PPT显现到屏幕功能

1.准备一份PPT文件 和System.Drawing,Aspose.Slides这些dll文件,如图

2.unity默认设置,在Player下面找到api兼容级别 改成.NETFrameWork 如图

3.创建这些东西,并挂载脚本,脚本是其他大佬分享的,挺好使

4.运行即可 页数多的情况得另外搞

5.参考大佬的地址

⭐ Unity 异步加载PPT页面 并 首帧无卡顿显现_unity 加载ppt-CSDN博客

这个也能使用,有案例694fe · 万能工具箱/PPT加载插件v2.0Unity - GitCode

6.dll的话可以去上面工程找下,有报错也是dll的障碍和项目设置的问题

7.PPTCtrl脚本在这里

using Aspose.Slides;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.UI;

public class PPTCtrl : MonoBehaviour
{
public UnityEngine.UI.Image ShowImg;//展示图片
public Text pagetext;//页数
public GameObject LastBtn, NextBtn;
public Sprite PlaceholderSprite; // 设置一个默认占位图 行用ppt第一张图

private Presentation presentation = null;
private int NowPage = 0;
private bool isLoading = false;

private Dictionary<int, Sprite> slideSprites = new Dictionary<int, Sprite>();

private async void Start()
{
UnityMainThreadDispatcher.Instance(); // 初始化主线程调度器

string PPTPath = Application.dataPath + "/Plugins/Aspose.Slides.NET.18.10.0(Crack)/165.pptx";
presentation = new Presentation(PPTPath);

// 用占位图先顶上 UI
ShowImg.sprite = PlaceholderSprite;

// 优先加载第一页
await LoadAndCacheSlideAsync(0);

// 延迟一帧再刷新 UI,避免卡顿
await Task.Delay(100);
SwitchPage(0);

// 后台加载其他页
_ = Task.Run(() => PreloadOtherSlidesAsync());
}

private void OnEnable()
{
LastBtn.GetComponent<Button>().onClick.AddListener(ClickLast);
NextBtn.GetComponent<Button>().onClick.AddListener(ClickNext);
}

private void OnDisable()
{
LastBtn.GetComponent<Button>().onClick.RemoveListener(ClickLast);
NextBtn.GetComponent<Button>().onClick.RemoveListener(ClickNext);
}


private async Task PreloadOtherSlidesAsync()
{
int total = presentation.Slides.Count;

for (int i = 1; i < total; i++)
{
if (!slideSprites.ContainsKey(i))
await LoadAndCacheSlideAsync(i);
}
}

private async Task LoadAndCacheSlideAsync(int page)
{
var slide = presentation.Slides[page];
var bitmap = slide.GetThumbnail(1f, 1f);
var bytes = GetBitMapBytes(bitmap);

await Task.Yield(); // 推出当前线程

UnityMainThreadDispatcher.Instance().Enqueue(() =>
{
var tex = new Texture2D(bitmap.Width, bitmap.Height, TextureFormat.RGBA32, false);
tex.LoadImage(bytes);
var sprite = Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), Vector2.zero);
slideSprites[page] = sprite;
});
}

public void SwitchPage(int page)
{
if (isLoading || page < 0 || page >= presentation.Slides.Count)
return;

NowPage = page;
pagetext.text = (page + 1) + " / " + presentation.Slides.Count;
LastBtn.SetActive(page > 0);
NextBtn.SetActive(page < presentation.Slides.Count - 1);

if (slideSprites.TryGetValue(page, out Sprite sprite))
{
ShowImg.sprite = sprite;
}
else
{
ShowImg.sprite = PlaceholderSprite;
StartCoroutine(LoadSlideAsync(page));
}
}

private IEnumerator LoadSlideAsync(int page)
{
isLoading = true;

yield return Task.Run(async () =>
{
await LoadAndCacheSlideAsync(page);
UnityMainThreadDispatcher.Instance().Enqueue(() =>
{
if (NowPage == page && slideSprites.ContainsKey(page))
{
ShowImg.sprite = slideSprites[page];
}
isLoading = false;
});
});
}

private byte[] GetBitMapBytes(Bitmap bm)
{
try
{
using (MemoryStream ms = new MemoryStream())
{
bm.Save(ms, ImageFormat.Png);
return ms.ToArray();
}
}
catch (Exception e)
{
Debug.LogWarning("Get Bytes failed: " + e);
return null;
}
}

public void ClickNext() => SwitchPage(NowPage + 1);
public void ClickLast() => SwitchPage(NowPage - 1);
}

8.主线程调度的脚本在这

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

public class UnityMainThreadDispatcher : MonoBehaviour
{
private static readonly Queue<Action> _executionQueue = new Queue<Action>();
private static UnityMainThreadDispatcher _instance = null;

public static UnityMainThreadDispatcher Instance()
{
if (_instance == null)
{
var go = GameObject.Find("MainThreadDispatcher");
if (go == null)
{
go = new GameObject("MainThreadDispatcher");
DontDestroyOnLoad(go);
_instance = go.AddComponent<UnityMainThreadDispatcher>();
}
else
{
_instance = go.GetComponent<UnityMainThreadDispatcher>();
if (_instance == null)
_instance = go.AddComponent<UnityMainThreadDispatcher>();
}
}
return _instance;
}

public void Enqueue(Action action)
{
if (action == null) return;

lock (_executionQueue)
{
_executionQueue.Enqueue(action);
}
}

private void Update()
{
lock (_executionQueue)
{
while (_executionQueue.Count > 0)
{
_executionQueue.Dequeue()?.Invoke();
}
}
}
}

http://www.gsyq.cn/news/26125.html

相关文章:

  • 文档智能处理桌面软件开源
  • 万象EXCEL开发(十)excel 高级混合查询 ——东方仙盟金丹期 - 教程
  • za3J5cHRvc+WvhueggeWOn+aWhw
  • 五自由度机械臂阻抗控制下的力跟踪
  • uploads-lab通关攻略
  • 初始化vue3项目和打包vue3项目
  • Continuation Passing Style 连续传递样式
  • Bean 生命周期的关键阶段和详细流程
  • https://juejin.cn/post/7529730683963588627
  • PCB布线一定不能走直角吗?一个或许有些离经叛道又颠覆常识的答案
  • 替代ftp的文件传输协议:提升数据安全与传输效率的新选择
  • Gitee DevOps:中国企业的研发效能加速器
  • 软件中版本号V1.0.0含义
  • LabVIEW继电保护检测 - 教程
  • 数据安全交换系统介绍及其应用场景分析
  • DBeaver 设置语言为中文
  • 国内开发者如何选择最适合的代码管理工具?Gitee、GitHub、Bitbucket横向评测
  • 2025国产ITSM厂商选型指南:聚焦五大ITSM平台,赋能企业数字化运维
  • 理解C++20的革命特性——协程支持1 - 实践
  • 飞驰云联亮相军工数字化转型发展峰会 共筑军工数字生态新范式
  • 2025 年土工布生产厂家最新推荐榜权威发布:聚焦 3 万平厂房与 50 年寿命产品,优选实力品牌
  • 2025年10月留香沐浴露排行:蓝蕨等五款香水级体验评测
  • 2025 年工业连接器厂家最新推荐榜单:聚焦 M8/M12 / 防水 / 重载 / 以太网品类,精选优质国产企业助力高效采购
  • 2025 年药包材辅导公司最新推荐榜:GMP 验证 / 质量体系 / 实验室装修等服务优质机构权威评选
  • 2025年10月防脱生发产品推荐榜:十款临床验证口碑对比
  • 界面控件DevExpress WPF v25.2新功能预览 - 聚焦AI功能提升
  • 【开题答辩实录分享】以《 Python基于大数据的四川旅游景点数据分析与可视化》为例进行答辩实录分享 - 实践
  • ida pro 9.2 接入 ida-pro-mcp
  • 2025 年淬火炉源头厂家最新推荐榜:聚焦技术创新与市场口碑深度解析,精选优质企业供采购参考
  • 2025 年国际物流服务公司最新推荐排行榜:覆盖海运快递跨境专线,精选优质企业助力跨境电商商家高效选择合作伙伴