====== アンケートVCI(わんコメ対応) ====== **[[deliverytool/onecomme/plugin]]**でYouTube・ニコニコ生放送のコメントを受信してアクションを起こすVCIのサンプルです。 * 「#1」「#2」「#3」「#4」のいずれかの文字列を含むコメントを受信すると、投票結果がグラフに表示される * [[https://developer.virtualcast.jp/vci-docs/manual/osc/onecomme_osc/index.html|プラグインの仕様ドキュメント]] \\ === サンプルデータ === https://virtualcast.jp/products/a44c9225543e9a4ac63ec0171d5310f2566ab631710c3131cf70a82dea0608aa === Unitypackage === {{ vci:sample:oscapi:onecomme:questionnairevci.unitypackage |}} ===== コンポーネント設定 ===== VCI Object {{:vci:sample:oscapi:onecomme:que1.png?direct}} --> Sub Item 設定一覧 (クリックで展開) # VCI Sub Item : Questionnaire\\ {{:vci:sample:oscapi:onecomme:que2.png?direct}} VCI Sub Item : SwitchCollider\\ {{:vci:sample:oscapi:onecomme:que3.png?direct}} <-- ===== VCIスクリプト ===== local roomFlag local voteTbl = {} --投票を行った人のIDを管理するTbl local textZeroPos = 0.37 --0票の際のテキストのゼロ位置 local textSlide = -0.01 --1票入った際のテキストのスライド量 local barZeroScl = 0.006 --0票の際のバーのスケール量(チラリと見える量) local boradSclSide = 0.00057 --100票を超えた際のボードの拡大量 local board = vci.assets.GetTransform("BoardDummy") local bar = {} local voteText = {} for i = 1, 4 do bar[i] = vci.assets.GetTransform("BarDummy"..i) voteText[i] = vci.assets.GetTransform("VoteText"..i) end local switch = vci.assets.GetTransform("Switch") local switchCollider = vci.assets.GetTransform("SwitchCollider") local switchFlag = false local voteKey = {"#1","#2","#3","#4"} --四捨五入 --digit:四捨五入する桁数。 --10の位までを有効数字として四捨五入する場合は、1 --1の位までを有効数字として四捨五入する場合は、0 --0.1の位までを有効数字として四捨五入する場合は、-1 local function shiShaGoNyu(num, digit) num = num + 0.5*10^digit local reNum = math.floor(num/10^digit)*10^digit return reNum end local youtubeAdress1 = "/vc-official/onecomme/youtube/comment" local youtubeAdress2 = "/vc-official/onecomme/youtube/super" local niconicoAdress1 = "/vc-official/onecomme/niconico/comment" local niconicoAdress2 = "/vc-official/onecomme/niconico/gift" ----------------------------------------------- --わんコメプラグインを利用したアンケートシステム --わんコメで投票キーを受け取った場合、コメント内の先頭に近いキーを集計する --一度投票したら、次の回答は無効(次のアンケートが始まるまで) --VCIのオーナーが代表して処理 ----------------------------------------------- local function wankomeVote(content) if roomFlag then if switchFlag and vci.state.Get("OwnerID") == vci.vc.room.GetLocalPlayer().GetId() then --すでに回答しているかどうかのチェック local voteCheck = true local oscData = json.parse(content) for i = 1, #voteTbl do if oscData.userId == voteTbl[i] then voteCheck = false end end if voteCheck then --コメントに含まれる投票キーチェック local tbl = {} for i = 1, 4 do if string.find(oscData.comment, voteKey[i]) ~= nil then table.insert(tbl, {i, string.find(oscData.comment, voteKey[i])}) end end --一番先頭に近い投票キー以外を除外 while #tbl >= 2 do if tbl[1][2] <= tbl[2][2] then table.remove(tbl, 2) else table.remove(tbl, 1) end end --有効票があれば、投票加算処理 if #tbl ~= 0 then if vci.state.Get("VoteResult"..tbl[1][1]) ~= nil and vci.state.Get("VoteResultSum") ~= nil then local pre = vci.state.Get("VoteResult"..tbl[1][1]) vci.state.Set("VoteResult"..tbl[1][1], pre+1) local sum = vci.state.Get("VoteResultSum") vci.state.Set("VoteResultSum", sum+1) table.insert(voteTbl, oscData.userId) end end end end end end vci.osc.RegisterMethod(youtubeAdress1, wankomeVote, {ExportOscType.BlobAsUtf8}) vci.osc.RegisterMethod(youtubeAdress2, wankomeVote, {ExportOscType.BlobAsUtf8}) vci.osc.RegisterMethod(niconicoAdress1, wankomeVote, {ExportOscType.BlobAsUtf8}) --vci.osc.RegisterMethod(niconicoAdress2, wankomeHakushu, {ExportOscType.BlobAsUtf8}) --わんコメから集計されたアンケートデータのグラフ表示処理 local function graphUpdate() local boardSclSideMax = 100 if vci.state.Get("VoteResultSum", 0) ~= nil then for i = 1, 4 do if vci.state.Get("VoteResult"..i) ~= nil then local var = vci.state.Get("VoteResult"..i) if var == nil then var = 0 end --棒の更新 --0票の際は、少し棒が見えるように別個のスケールを適用 if var == 0 then bar[i].SetLocalScale(Vector3.__new(barZeroScl, 1, 1)) else bar[i].SetLocalScale(Vector3.__new(var*0.01, 1, 1)) end --テキスト位置の更新 voteText[i].SetLocalPosition(Vector3.__new(textZeroPos + textSlide*var, 0.27-0.18*(i-1), 0.003)) if boardSclSideMax < var then boardSclSideMax = var end --テキスト文章の更新 local text1 = vci.state.Get("VoteResult"..i)/vci.state.Get("VoteResultSum")*100 text1 = tostring(shiShaGoNyu(text1, -1)) if #text1 <= 2 then text1 = text1..".0" end if vci.state.Get("VoteResultSum") == 0 then vci.assets.SetText("VoteText"..i, "("..vci.state.Get("VoteResult"..i).."票)") else vci.assets.SetText("VoteText"..i, text1.."%
("..vci.state.Get("VoteResult"..i).."票)") end end end end --100票を超える棒がある場合、グラフ用紙も伸ばす if boardSclSideMax <= 100 then board.SetLocalScale(Vector3.one*0.1) else board.SetLocalScale(Vector3.__new(0.1+(boardSclSideMax-100)*boradSclSide, 0.1, 0.1)) end end --スイッチコライダーの追従処理 local function swColliderTransform() if switchCollider.IsMine then switchCollider.SetPosition(switch.GetPosition()) switchCollider.SetRotation(switch.GetRotation()) switchCollider.SetLocalScale(vci.assets.GetTransform("Questionnaire").GetLocalScale()*0.02) end end --投票受付、投票終了のテキスト更新処理 --投票受付開始の際には、投票を管理するVCIオーナーで、投票結果の初期化を行う。 local function voteSwitchTextUpdate() if vci.state.Get("SwitchState") ~= nil then if vci.state.Get("SwitchState") ~= switchFlag then if not(switchFlag) then vci.assets.SetText("SwitchText", "投票
終了") if vci.state.Get("OwnerID") == vci.vc.room.GetLocalPlayer().GetId() then voteTbl = {} for i = 1, 4 do vci.state.Set("VoteResult"..i, 0) end vci.state.Set("VoteResultSum", 0) end else vci.assets.SetText("SwitchText", "投票
受付") end switchFlag = vci.state.Get("SwitchState") end end end --初期化処理 --stateの初期化 local function initialize() --ルーム識別処理 --本VCIはルーム以外では動作しない if vci.vc.GetSpaceType() == ExportVcSpaceType.studio then roomFlag = false else roomFlag = true end if roomFlag and vci.assets.IsMine then if vci.state.Get("OwnerID") == nil then vci.state.Set("OwnerID", vci.vc.room.GetLocalPlayer().GetId()) vci.state.Set("SwitchState", false) for i = 1, 4 do vci.state.Set("VoteResult"..i, 0) end vci.state.Set("VoteResultSum", 0) elseif vci.state.Get("OwnerID") == vci.vc.room.GetLocalPlayer().GetId() then vci.state.Set("SwitchState", false) for i = 1, 4 do vci.state.Set("VoteResult"..i, 0) end vci.state.Set("VoteResultSum", 0) end end end initialize() function updateAll() --グラフの表示処理 graphUpdate() --スイッチコライダーの追従処理 swColliderTransform() --投票受付、投票終了のテキスト更新処理 voteSwitchTextUpdate() end function onUse(use) if use == "SwitchCollider" then if vci.state.Get("SwitchState") ~= nil then local tempFlag = vci.state.Get("SwitchState") vci.state.Set("SwitchState", not(tempFlag)) end end end