Honey Select 2 VNGE的基本介紹
VNGE這玩意其實(shí)功能還是有點(diǎn)強(qiáng)的,只是不知道為啥,到處都看不到討論,但是更新又很多。各種基于SSB和SSSB的制作也不少。關(guān)于偏代碼方向的討論還真不多。
其代碼核心位于BepInEx下的Plugins/Console/Lib中
其中主要有三個(gè)組件 VNFrame VNActor和VNAnime, 這三個(gè)組件都是python文件。Console這個(gè)插件應(yīng)該是直接給Unity框架開的口子,本身游戲運(yùn)行時(shí)打開的Console,除了顯示加載信息錯(cuò)誤信息,也可以輸入python函數(shù),讓Python可以直接和游戲進(jìn)程中的對(duì)象交互。
其他各種SSB SSSB,SceneUtils都基于或者大部分基于這三個(gè)組件所提供的功能。
VNFrame提供基本框架,可以調(diào)用游戲中的多數(shù)系統(tǒng)級(jí)別的功能。
VNActor提供人物和道具的操作。
VNAnime提供一個(gè)動(dòng)畫框架,可以實(shí)現(xiàn)基于關(guān)鍵幀的動(dòng)畫,并且導(dǎo)出為Json。
基本介紹就是如此,下面是基本操作。
_____________________________________________________________________
這玩意兒在游戲里的熱鍵就是Ctrl+F3和Ctrl+F8
建立VNGE新游戲的時(shí)候
在NeoStudio中,先Ctrl+F8叫出界面。
然后Clip Man—>? Scene Helper->new python 建立游戲
game name 自己起,game folder要在UserData/Studio/scene下預(yù)先建立,
png名字自己起,python名字也是自己起。
執(zhí)行成功之后,會(huì)在UserData/Studio/scene下面自己起的game folder下看到一個(gè)自己起名字的png,也就是場景存檔
同時(shí)在BepInEx/Plugins/Console/Lib 下面看到一個(gè)按照自己起名字的py文件。這就是自己的游戲代碼文件了。
同目錄下的simplegamedemoavg.py,? techdemo.py, vnftut_neo.py是一些作者提供的例子。
建立好的游戲在Ctrl+F8喚出的VNGE主界面中的All games可以找到。同時(shí)也可以運(yùn)行作者提供的例子游戲。
還要注意在編輯場景png的時(shí)候,需要在scene helper里,選save scene來保存修改,否則alt+S會(huì)在UserData/Studio/scene下存一個(gè)新的,保存時(shí)候需要寫gamefolder\游戲.png
----------------------------------------------------------------------------------------------------------------
用VNGE寫游戲的基本流程就是在場景png里添加人物和道具
在python腳本里實(shí)現(xiàn)邏輯和對(duì)話。
在場景添加人物(char)和道具(prop)之后,在scene helper里選create tag,這一步就是起一個(gè)名字,在python中可以用這個(gè)名字來調(diào)用這個(gè)道具或者人物,實(shí)際上是在這個(gè)東西下面加了一個(gè)節(jié)點(diǎn)。加載游戲的時(shí)候會(huì)注冊。任何修改都需要保存在png中,這樣啟動(dòng)游戲的時(shí)候才能起作用,并且找到這個(gè)物體。
游戲會(huì)給你一個(gè)基本的代碼框架,基本是一系列以game為參數(shù)的函數(shù),這些函數(shù)可以互相跳來跳去。其中對(duì)話部分的代碼非常簡單,看一下例子就能了解。
其他的一些需要摸索的有。
基本代碼有獲得人物
act=game.scenef_get_all_actors()['g1']? ? ##g1是tag時(shí)候給人物的名字。
獲得人物之后,就可以用VNActor里的方法和人物交互。
從json加載某個(gè)pose。這個(gè)不分ik或者fk。
看json例子就知道
pose1="""{"pose": {"hands": {"list": [1, 1], "__tuple__": true}, "fk_active": {"list": [false, false, false, false, false, false, false], "__tuple__": true}, "fk_set": {"10000": {"z": 0.000, "__Quat__": true, "y": 0.000, "x": 0.309, "w": 0.951}, "10001": {"z": 0.000, "__Quat__": true, "y": 0.000, "x": 0.161, "w": 0.987}, "10002": {"z": 0.000, "__Quat__": true, "y": 0.000, "x": 0.304, "w": 0.953}, "10003": {"z": 0.000, "__Quat__": true, "y": 0.000, "x": 0.154, "w": 0.988}, "10004": {"z": 0.000, "__Quat__": true, "y": 0.000, "x": 0.254, "w": 0.967}, "10005": {"z": 0.000, "__Quat__": true, "y": 0.000, "x": 0.241, "w": 0.971}, "10006": {"z": 0.000, "__Quat__": true, "y": 0.000, "x": 0.304, "w": 0.953}, "10007": {"z": 0.000, "__Quat__": true, "y": 0.000, "x": 0.212, "w": 0.977}, "10008": {"z": 0.000, "__Quat__": true, "y": 0.000, "x": 0.292, "w": 0.957}, "10009": {"z": 0.000, "__Quat__": true, "y": 0.000, "x": 0.269, "w": 0.963}, "10010": {"z": 0.000, "__Quat__": true, "y": 0.000, "x": 0.154, "w": 0.988}, "10011": {"z": 0.000, "__Quat__": true, "y": 0.000, "x": 0.214, "w": 0.977}, "10012": {"z": 0.000, "__Quat__": true, "y": 0.000, "x": 0.244, "w": 0.970}, "10013": {"z": 0.000, "__Quat__": true, "y": 0.000, "x": 0.170, "w": 0.986}, "10014": {"z": 0.000, "__Quat__": true, "y": 0.000, "x": 0.164, "w": 0.986}, "10015": {"z": 0.000, "__Quat__": true, "y": 0.000, "x": 0.116, "w": 0.993}, "10016": {"z": 0.000, "__Quat__": true, "y": 0.000, "x": 0.000, "w": 1.000}, "10017": {"z": 0.000, "__Quat__": true, "y": 0.000, "x": 0.381, "w": 0.924}, "10018": {"z": 0.000, "__Quat__": true, "y": 0.000, "x": 0.158, "w": 0.987}, "10019": {"z": 0.000, "__Quat__": true, "y": 0.000, "x": 0.000, "w": 1.000}}, "rotate_to": {"z": -0.000, "y": 0.000, "__Vector3__": true, "x": -0.000}, "anim_lp": false, "kinematic": 1, "ik_set": {"cf_J_LegLow01_L": {"list": [{"z": -5.286, "y": 2.778, "__Vector3__": true, "x": -2.877}], "__tuple__": true}, "cf_J_ArmUp00_R": {"list": [{"z": 2.594, "y": 2.161, "__Vector3__": true, "x": 1.187}], "__tuple__": true}, "cf_J_LegUp00_R": {"list": [{"z": -1.481, "y": 0.863, "__Vector3__": true, "x": 0.803}], "__tuple__": true}, "cf_J_Hand_L": {"list": [{"z": -1.691, "y": 2.281, "__Vector3__": true, "x": -0.324}, {"z": -0.000, "__Quat__": true, "y": 0.718, "x": -0.000, "w": -0.696}], "__tuple__": true}, "cf_J_ArmUp00_L": {"list": [{"z": 2.548, "y": 2.077, "__Vector3__": true, "x": -1.187}], "__tuple__": true}, "cf_J_Hand_R": {"list": [{"z": -1.744, "y": 2.283, "__Vector3__": true, "x": 0.220}, {"z": -0.001, "__Quat__": true, "y": -0.707, "x": 0.001, "w": -0.708}], "__tuple__": true}, "cf_J_Hips": {"list": [{"z": 0.000, "y": 0.741, "__Vector3__": true, "x": 0.000}], "__tuple__": true}, "cf_J_LegUp00_L": {"list": [{"z": -1.481, "y": 0.863, "__Vector3__": true, "x": -0.803}], "__tuple__": true}, "cf_J_Foot01_L": {"list": [{"z": -3.585, "y": 4.144, "__Vector3__": true, "x": 0.069}, {"z": 0.101, "__Quat__": true, "y": 0.498, "x": -0.861, "w": 0.027}], "__tuple__": true}, "cf_J_Foot01_R": {"list": [{"z": -3.113, "y": 4.031, "__Vector3__": true, "x": -0.156}, {"z": -0.024, "__Quat__": true, "y": -0.399, "x": -0.903, "w": 0.161}], "__tuple__": true}, "cf_J_ArmLow01_R": {"list": [{"z": -0.128, "y": 3.273, "__Vector3__": true, "x": 0.298}], "__tuple__": true}, "cf_J_LegLow01_R": {"list": [{"z": -5.293, "y": 3.862, "__Vector3__": true, "x": 2.161}], "__tuple__": true}, "cf_J_ArmLow01_L": {"list": [{"z": -0.178, "y": 3.106, "__Vector3__": true, "x": -0.509}], "__tuple__": true}}, "ik_active": {"list": [true, true, true, true, true], "__tuple__": true}, "anim_spd": 0.000, "face_to": 4, "anim": {"list": [0, 1, 17, 0.000], "__tuple__": true}, "anim_ptn": 0.000}, "tags": ["Base"]}"""
active中已經(jīng)指定了那些ik或者fk是激活狀態(tài),可以同時(shí)起效。
加載時(shí)需要用反序列化器,然后才能應(yīng)用于人物
from libjsoncoder import sceneDecoder
res = json.loads(pose, object_hook = sceneDecoder)
act.import_status(res['pose'])
鏡頭操作則是
game.move_camera(pos=(0.0,23, 0.0), distance=(0, 0,-27.0), rotate=(16.0, 196.0, 0), fov=23.0)
pos是鏡頭位置,distance是偏移量,rotate是旋轉(zhuǎn)角度,fov是可視范圍。