2025-04-07 10:11:08    21    0    0

*本文仅作技术研究,因为合规原因,本文不提供任何法律敏感和版权相关的诸如SDK的文件

前言和声明


Unity Switch 开发打包移植相关的一系列教程,by 皓月狩魂(sin365) axibug.com
初版分享:

声明:
*文章和开源代码仓库,仅作技术研究,因为合规原因,不包含也提供任何法律敏感和版权相关的诸如SDK的文件。
*请自行获取,建议您使用官方授权的开发套件。
*谢绝讨论任何技术外的,诸如NS移植游戏开发的性质等无意义问题,我只是技术爱好者。相互尊重,相互学习。

文章:

1.Unity Switch 开发/打包/移植教程(包含如何重新Repack NSP,让捣鼓后的零售机运行)
http://note.axibug.com/blog/post/akiragatsu/UnitySwitchDev

2.Unity下Switch开发文件存储踩坑,以及解决方案范例 (Unity Switch下不能用System.IO,只能用nn.fs)
http://note.axibug.com/blog/post/akiragatsu/UnitySwitchDevForIO

3.Switch系统错误码,方便排查问题 (我AxiNSApi中也提供了转换打印,方便排查)
http://note.axibug.com/blog/post/akiragatsu/SwitchErrCode

4.Switch TitleID规则
http://note.axibug.com/blog/post/akiragatsu/SwitchTitleID

工具仓库:

  1. AxibugNSPTools Unity用自动化打包工具(自动完成NSP打包并Repack)
    https://github.com/sin365/AxibugNSPTools

  2. AxiNSApi 已经封装好的Unity下Switch的用户访问,存储挂载,读写API,直接可用
    https://github.com/sin365/AxiNSApi

再次申明,以上文章和仓库,不提供不包含任何敏感和版权文件,和授权开发者一样,仅讨论和演示上层使用经验交流。

祝君愉快

2025-04-08 01:01:05    12    0    0

*本文仅作技术研究,因为合规原因,本文不提供任何法律敏感和版权相关的诸如SDK的文件。

意义?

本文主要探讨Unity下的Nintendo Switch平台 存档或存储相关,

有朋友就问了,Unity开发的文件存储,不就是Syatem.IO 下直接操作么?并非如此,他就是不一样,可以说是传统方式完全不可用 ~

我先介绍,再告诉你代码怎么写,安心先看

我们先来看看在Switch平台下的,情况:

  1. Application.persistentDataPath 不可用 调用就崩溃,也不用在任何地方动态或静态初始化
  2. Application.DataPath 可用 输出 rom:/Data
  3. Application.streamingAssetsPath 可用 输出 rom:/Data/StreamingAssets
  4. Application.temporaryCachePath 可用 输出 host:/Temp

像Application.DataPath,Application.streamingAssetsPath这种只读的路径,也不能通过System.IO去访问,调用就会卡死掉。

而要存储,如Application.persistentDataPath 在Switch下是直接不可用的,类似我PSVita文章讲到的,但比PSVita更严格,甚至不能取值。

那么,比如我们要开发模拟器亦或者需要可读写的目录怎么办呢?

他这里有一个 挂载点的概念,列个表吧。

挂载点 描述 用途 是否可读写 大小限制 注意事项
rom:/ 只读文件系统,存储游戏资源 加载静态资源(如模型、纹理等) 只读 受NSP包大小限制(通常几GB)
    构建时打包
    - 需优化资源以减少加载时间
    - 不可动态修改
host:/ 开发环境中的主机文件系统 调试时访问开发机文件 可读写(开发时) 受开发机存储限制
    仅限开发套件
    - 零售版不可用
    - 需USB或网络连接开发机
save:/ 保存数据挂载点,存储存档 保存游戏进度、玩家设置等 可读写 几MB(由游戏注册信息决定)
2025-04-08 00:47:37    13    0    0
2025-04-06 02:04:26    18    0    0

用Unity默认的TitleID为例:0x01004b9000490000

  1. TitleID 命名规则
    1.1 TitleID 概述
    定义:TitleID 是 Nintendo Switch 用来唯一标识一个应用(游戏、DLC、更新等)的 16 位十六进制字符串(64 位整数),共 16 个字符。

格式:0x<16位十六进制>,例如 01004b9000490000。

用途:
区分不同的应用、存档、更新等。

用于系统管理(如存档路径 /atmosphere/contents//)。

在 hacBrewPack 等工具中需要指定。

1.2 TitleID 命名规则
Switch 的 TitleID 遵循一定的规则,分为以下部分:
前 4 位(第 1-4 字符):0100
表示这是一个应用(Application)。

其他类型:
0100:应用(Game/Application)。

0101:系统应用(System Application)。

0102:系统模块(System Module)。

0103:固件包(Firmware Package)。

0104:DLC(Downloadable Content)。

0105:更新(Update/Patch)。

第 5-12 位(第 5-12 字符):开发者/发行商 ID
由 Nintendo 分配给开发者或发行商的唯一标识。

例如 4b900049 是某个开发者的 ID。

对于 Homebrew 开发者,通常随机选择一个未被占用的值,但需避免与官方游戏冲突。

第 13-16 位(第 13-16 字符):应用编号
通常为 0000,表示主应用。

如果是 DLC 或更新,可能递增(如 8000 表示更新)。

示例:
01004b9000490000:
0100:应用。

4b900049:开发者 ID。

0000:主应用。

1.3 Homebrew 环境下的 TitleID 选择
规则:
必须以 0100 开头(表示应用)。

第 5-12 位可以随机选择,但建议避免与官方游戏冲突。

第 13-16 位通常为 0000。

推荐:
使用随

2023-11-02 11:15:21    859    0    0

皓月云 axibug.com

一个非盈利性质的公益

始于2013,一路走来,感谢有你。

皓月云发展编年史:

 

2013-12-2~  [公益品牌] 皓月云伊始 PSP/掌机联机 | 定名皓月远程联机平台

> 2014:【以PSP起步初探的一年】

2014-年中~ [转折点] 仅剩一台服务器(第一次服务器危机)

2014-12-2~ [周年] 皓月远程联机平台1周年纪念(b站视频:av1793873)

2014-12-中下旬~ [多元化] 泰拉瑞亚

2014-12-中下旬~ [多元化] 星界边境早期版本

2014-12-中下旬~ [多元化] 魔方世界alpha

2014-12-2~ [周年] 皓月远程联机平台1周年纪念(b站视频:av3315708

> 2015:【真正形成多元圈子的一年】

2015-上半年~  [多元化] 梦幻之星蓝色脉冲

2015-年中~  [多元化] 鸡蛇(支撑阵面对决贴吧卡牌服务器)

2015-年中~ [公益品牌] 新官网 axibug.com

2015-年中~  [多元化] 二次元传奇公益

2015-年中~  [转折点/BF3] 皓月云战地3服务器伊始(相对封闭小众)

2015-下半年~  [多元化] 皓月伤害世界

2015-12-2~ [周年] 皓月远程联机平台2周年纪念(b站视频:av3315708

> 2016:【BF3发力的一年】

2016-上半年~ [BF3] ZAFT BF3服并入皓月(皓月服务器全面公开)

2016-下半年~ [BF3] 战地服务器增设 皓月战术引擎、排行榜

2016-下半年~ [BF3] 皓月BF3进入最艰难时期,和别有用心的人斗争,以及大量DDOS(同时也开始进入巅峰时期)

2016-下半年~  [多元化]  皓月StarBound服务器重启(给星界边境贴吧和星核汉化组提供)

2016-11-左右~ [周边服务] 皓月学习资料站

2016-12-2~ [周年] 皓月远程联机平台3周年纪念(b站视频: av7350469

2016-12-月底~ [BF3] 皓月BF3开始提供自助开服服务

> 2017:【BF3稳定的一年】

2017-上半年~ [公益品牌] 皓月远程联机平台 更名为:皓月云

2017-上半年~  [转折点/BF3] 国内仅剩皓月云 支撑BF3、最艰难时期度过。

2017-年中~ [周边服务] 皓月左心房APP

2017-年中~ [MC] 使用树莓派(5

2023-11-01 03:12:26    228    0    0

这里是一个分享生活的趣味小站点

有罗马音歌词,有技术文档,有生活感悟……

 

渝ICP备15002983号-1

 

2021-07-26 11:07:56    323    0    0

スーパーアイドルの笑顔(えがお)よりも
su pa a i do ru no e ga o yo ri mo
比超级偶像的笑容还要灿烂

あの八月(はちがつ)の午後(ごご)よりも
a no ha chi ga tsu no no go go yo ri mo
比八月午后的阳光还要耀眼

105(ヒャくご)セルシウス度(ど)より
hya ku go se ru shi u su do yo ri
你是比105度还要

光(ひか)る君(きみ)へ
hi ka ru ki mi he
闪闪发光的存在

「かわいい」っと言える(いえる)なら
「ka wa i i」 tsu to i e ru
如果要问“可爱”是什么

転(ころ)んでもすぐ笑(わら)う君(きみ)は
ko ro n de mo su gu wa ra ki mi wa
摔倒后马上就会开怀笑的你

夢(ゆえ)は遠(とおい)いはずなのに
yu me wa to o i na zu na no ni
梦想本来应该很遥远

指向した星(ほし)が近付い(ちかい)た
** shi ta ho shi ga chi ka zu i ta
指向的那颗星却近了

優し(やさし)い風吹いて
ya sa shi i ka ze fu i te
温柔的风正吹来

「隣り」(となり)以上(いじよう)もっと近く(ちかく)
「to na ri」i ji yo u mo tsu to chi ka ku
想要比“身边”的距离更近

「二人(ふたり)なら大丈夫(だじよぶ)」そう言ったら
「fu da ri na ra da ji yo bu」 so u i ta ra
说着“只要我们一起就不怕风浪”

 

スーパーアイドルの笑顔(えがお)よりも
su pa a i do ru no e ga o yo ri mo
比超级偶像的笑容还要灿烂

あの八月(はちがつ)の午後(ごご)よりも
a no ha chi ga tsu no no go go yo ri mo
比八月午后的阳光还要耀眼

105(ヒャくご)セルシウス度(ど)より
hya ku go se ru shi u su do yo ri
你是比105度还要

 

光(ひか)る君(きみ)へ
hi ka ru ki mi he
闪闪发光的存在

 

一人きりじゃない

不再是孤身一人

 

歩いてゆこう

迈出脚步吧

 

全てを忘れ恋をして

将所有都丢掉全力恋爱吧

 

105(ヒャくご)セルシウス度(ど)より
hya k

2024-09-24 17:04:10    122    0    0

文本探索了PSVita移植过程中,关于网络请求的问题

仅针对Unity的情况。(实测发现Unity下PSVita开发比C/C++原生PSVita开发底层提供的东西太少了)

本文用于记录我开发UNITY PSVITA跨平台联机模拟器项目,所遇到的问题,以及解决方案,
尤其是Http的坑,我提供了代码。随着我的联机项目持续开发,本文持续更新……

直接进入正题:

PSV电源模式 (模式A和模式C可以联网 仅模式B不可以)

模式有三种,Unity官方描述是
ModeA - default.
ModeB - GPU High - No WLAN or COM.
ModeC - GPU High - No Camera, OLED Low brightness.

模式A不限制,模式B关闭WLAN和COM接口,给GPU争取更多功率
那么,看样子是 是模式C限制得更狠。
实测,模式C限制摄像头和OLED之外,并没有限制WLAN;
如果项目需要联网不需要摄像头,那就选模式C吧。

*没准COM就是那个神秘接口(小声说道)

原生SOCKET(IPv4可用,IPv6不可用)

使用原生Socket,在PSVita中是直接可用的。

但PSVita不允许包含IPv6,即便是他隐式支持了。也要手动排除

不过 虽然你大概率在PSV上IPv6,但是Socket默认是要初始化IPv6的,需要手动指定一下。
使用时,要注意避免使用C#内部实现初始化了IPv6的实现。

例如
Socket 的构造函数中 SocketType和 ProtocolType两个参数的构造函数不可用。
会报协议不支持的错误:SocketException: Protocol not Supported
因为该构造函数,会自动补底层基类的类型为IPV6优先。

  1. //不要用如下方式
  2. Socket client = new Socket(SocketType.Stream, ProtocolType.Tcp);
  3. //C#内部实际基类透传 是ipv6优先 ↓↓↓
  4. public Socket(SocketType socketType, ProtocolType pro
2024-09-24 16:52:30    59    0    0

PSV ge

Unity官方可读写目录,PSV没有,返回空路径

  1. Application.persistentDataPath
  2. Windows -> C:/Users/用户/AppData/LocalLow/DefaultCompany/项目名
  3. PSVita -> 返回空

Unity缓存temporaryCachePath目录,PSV没有,返回空路径

  1. Application.temporaryCachePath
  2. Windows -> C:/Users/用户/AppData/Local/Temp/DefaultCompany/AxibugPSVAnyTest
  3. PSVita -> 返回空

StreamingAssets目录,有

  1. Application.streamingAssetsPath
  2. Windows -> 游戏安装目录/StreamingAssets
  3. PSVita -> /app0/Media/StreamingAssets
2024-07-31 16:14:15    285    0    0

Unity在很多需求下,不得不进行颜色的像素级填充,
诸如:实时贴花功能,绘图功能开发,乃至非Native的情况下视频播放(比如视频是CPU计算出来的,而不是文件流或直播流,提交颜色),各种游戏模拟器,等画面显示;

亦或者,必须要通过CPU逻辑运算,得到一个图形,并展示到UI中,或某个贴图上时,

采用类似Rendertexture的方式,都就需要处理Textture2d的填充。
尤其在高频填充的情况下(指60帧或者更高刷新率绘制),我们就需要考虑效率了。

以下是我做Unity下街机模拟器画面显示开发的心得
title
* 最终我还要上PSVita,使用unity(113M的极限内存可用,还要预留性能给我的网络联机网络库,害只能用77M的模式,主频非超频也只有333Mhz,所以能省则省了)

省流版,总结,几种:
Plan1. 使用SetPixelData< T > (T[] data, int mipLevel, int sourceDataStartIndex = 0)
Plan2. GetNativeTexturePtr纹理指针,对底层指针,进行绘制。如果你对DX11/DX9的绘制指针比较了解 ,可以使用Texture2d的GetNativeTexturePtr 获取指针,在C++扩展下进行操作。(跨平台不友好)
Plan3. 低版本Unity使用 LoadRawTextureData< T >(NativeArray data),LoadRawTextureData(byte[] data)
Plan4. 低版本Unity使用 LoadRawTextureData 的指针用法 (推荐) LoadRawTextureData(IntPtr data, int size)
Plan5. 交给shader

好好好,咱们从低到高,说说各种用法的演进

全局参数

  1. //这里是一个代码构建的Texture2D用于填充数据和提交
  2. private Texture2D m_rawBufferWarper;
  3. //这里是UI上一个RawImage组件作为显示
  4. private RawImage m_drawCanvas;
1/23