*本文仅作技术研究,因为合规原因,本文不提供任何法律敏感和版权相关的诸如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
工具仓库:
AxibugNSPTools Unity用自动化打包工具(自动完成NSP打包并Repack)
https://github.com/sin365/AxibugNSPTools
AxiNSApi 已经封装好的Unity下Switch的用户访问,存储挂载,读写API,直接可用
https://github.com/sin365/AxiNSApi
再次申明,以上文章和仓库,不提供不包含任何敏感和版权文件,和授权开发者一样,仅讨论和演示上层使用经验交流。
祝君愉快
*本文仅作技术研究,因为合规原因,本文不提供任何法律敏感和版权相关的诸如SDK的文件。
本文主要探讨Unity下的Nintendo Switch平台 存档或存储相关,
有朋友就问了,Unity开发的文件存储,不就是Syatem.IO 下直接操作么?并非如此,他就是不一样,可以说是传统方式完全不可用 ~
我先介绍,再告诉你代码怎么写,安心先看
我们先来看看在Switch平台下的,情况:
Application.persistentDataPath 不可用 调用就崩溃,也不用在任何地方动态或静态初始化
Application.DataPath 可用 输出 rom:/Data
Application.streamingAssetsPath 可用 输出 rom:/Data/StreamingAssets
Application.temporaryCachePath 可用 输出 host:/Temp
像Application.DataPath,Application.streamingAssetsPath这种只读的路径,也不能通过System.IO去访问,调用就会卡死掉。
而要存储,如Application.persistentDataPath 在Switch下是直接不可用的,类似我PSVita文章讲到的,但比PSVita更严格,甚至不能取值。
那么,比如我们要开发模拟器亦或者需要可读写的目录怎么办呢?
他这里有一个 挂载点的概念,列个表吧。
挂载点 | 描述 | 用途 | 是否可读写 | 大小限制 | 注意事项 |
---|---|---|---|---|---|
rom:/ |
只读文件系统,存储游戏资源 | 加载静态资源(如模型、纹理等) | 只读 | 受NSP包大小限制(通常几GB) |
- 需优化资源以减少加载时间 - 不可动态修改 |
host:/ |
开发环境中的主机文件系统 | 调试时访问开发机文件 | 可读写(开发时) | 受开发机存储限制 |
- 零售版不可用 - 需USB或网络连接开发机 |
save:/ |
保存数据挂载点,存储存档 | 保存游戏进度、玩家设置等 | 可读写 | 几MB(由游戏注册信息决定) |
用Unity默认的TitleID为例:0x01004b9000490000
格式: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。
推荐:
使用随
2013-12-2~ [公益品牌] 皓月云伊始 PSP/掌机联机 | 定名皓月远程联机平台
2014-年中~ [转折点] 仅剩一台服务器(第一次服务器危机)
2014-12-2~ [周年] 皓月远程联机平台1周年纪念(b站视频:av1793873)
2014-12-中下旬~ [多元化] 泰拉瑞亚
2014-12-中下旬~ [多元化] 星界边境早期版本
2014-12-中下旬~ [多元化] 魔方世界alpha
2014-12-2~ [周年] 皓月远程联机平台1周年纪念(b站视频:av3315708)
2015-上半年~ [多元化] 梦幻之星蓝色脉冲
2015-年中~ [多元化] 鸡蛇(支撑阵面对决贴吧卡牌服务器)
2015-年中~ [公益品牌] 新官网 axibug.com
2015-年中~ [多元化] 二次元传奇公益
2015-年中~ [转折点/BF3] 皓月云战地3服务器伊始(相对封闭小众)
2015-下半年~ [多元化] 皓月伤害世界
2015-12-2~ [周年] 皓月远程联机平台2周年纪念(b站视频:av3315708)
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-上半年~ [公益品牌] 皓月远程联机平台 更名为:皓月云
2017-上半年~ [转折点/BF3] 国内仅剩皓月云 支撑BF3、最艰难时期度过。
2017-年中~ [周边服务] 皓月左心房APP
2017-年中~ [MC] 使用树莓派(5
スーパーアイドルの笑顔(えがお)よりも
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
文本探索了PSVita移植过程中,关于网络请求的问题
仅针对Unity的情况。(实测发现Unity下PSVita开发比C/C++原生PSVita开发底层提供的东西太少了)
本文用于记录我开发UNITY PSVITA跨平台联机模拟器项目,所遇到的问题,以及解决方案,
尤其是Http的坑,我提供了代码。随着我的联机项目持续开发,本文持续更新……
直接进入正题:
模式有三种,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,在PSVita中是直接可用的。
但PSVita不允许包含IPv6,即便是他隐式支持了。也要手动排除
不过 虽然你大概率在PSV上IPv6,但是Socket默认是要初始化IPv6的,需要手动指定一下。
使用时,要注意避免使用C#内部实现初始化了IPv6的实现。
例如
Socket 的构造函数中 SocketType和 ProtocolType两个参数的构造函数不可用。
会报协议不支持的错误:SocketException: Protocol not Supported
因为该构造函数,会自动补底层基类的类型为IPV6优先。
//不要用如下方式
Socket client = new Socket(SocketType.Stream, ProtocolType.Tcp);
//C#内部实际基类透传 是ipv6优先 ↓↓↓
public Socket(SocketType socketType, ProtocolType pro
PSV ge
Application.persistentDataPath
Windows -> C:/Users/用户/AppData/LocalLow/DefaultCompany/项目名
PSVita -> 返回空
Application.temporaryCachePath
Windows -> C:/Users/用户/AppData/Local/Temp/DefaultCompany/AxibugPSVAnyTest
PSVita -> 返回空
Application.streamingAssetsPath
Windows -> 游戏安装目录/StreamingAssets
PSVita -> /app0/Media/StreamingAssets
Unity在很多需求下,不得不进行颜色的像素级填充,
诸如:实时贴花功能,绘图功能开发,乃至非Native的情况下视频播放(比如视频是CPU计算出来的,而不是文件流或直播流,提交颜色),各种游戏模拟器,等画面显示;
亦或者,必须要通过CPU逻辑运算,得到一个图形,并展示到UI中,或某个贴图上时,
采用类似Rendertexture的方式,都就需要处理Textture2d的填充。
尤其在高频填充的情况下(指60帧或者更高刷新率绘制),我们就需要考虑效率了。
以下是我做Unity下街机模拟器画面显示开发的心得
* 最终我还要上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
//这里是一个代码构建的Texture2D用于填充数据和提交
private Texture2D m_rawBufferWarper;
//这里是UI上一个RawImage组件作为显示
private RawImage m_drawCanvas;