対応バージョンは、UniVCI v0.35以降です。
バッジを装着すると、球が出現し、球を操作すると空中を自由に移動操作できるVCIです。
local player = vci.vc.room.GetLocalPlayer() local playerController = player.GetRoomPlayerController() -- ローカルプレイヤー以外では nil が返る local character = player.Character local my_chest local is_modeactive = false--ダミーの所有権を持っていてかつ装着されているか。これを有効状態のフラグにする local is_pre_modeactive = false--ダミーの所有権を持っていてかつ装着されているか。これを有効状態のフラグにする local is_controllergrabbing = false local is_subgrabbing = false local controller_root = vci.assets.GetTransform("controller_root") local attach_sub = vci.assets.GetTransform("attach_sub") local controller_model = vci.assets.GetTransform("controller_model") --はじめにモデルは見えなくする controller_model.SetActive(false) local is_onoffswitch = false -----制御関連 local initialYDiff = 0--基準リセットタイミングでのプレイヤー位置とコントローラの位置差分 local deltaAttachPos local deltaAttachRot local function toggleActivation() is_onoffswitch = not is_onoffswitch end --基準リセット local function recordInitialTransform() initialYDiff = controller_root.GetPosition().y - player.GetPosition().y end local function resetInitialPos() deltaAttachPos = controller_root.GetPosition() - player.GetPosition() local eular = player.GetRotation().eulerAngles deltaAttachRot = Quaternion.Inverse(Quaternion.Euler(0, eular.y, 0)) end -- Playerに対する相対的なCubeの位置の差分を取得 --- @return Vector3 local function getRelativeControllerYDifference() local currentPlayerToController = controller_root.GetPosition() - player.GetPosition() return currentPlayerToController.y - initialYDiff end local anitGravityCoef = -1 local moveCoef = 30 local breakCoef = 3 local breakThreshold = 0.1 --- @param force Vector3 --- @param forceMode string NOTE: ExportForceMode は現在比較可能でない local function FireAddForce(force, forceMode) if forceMode == "Impulse" then playerController.AddForce(force, vci.forceMode.Impulse) elseif forceMode == "Force" then playerController.AddForce(force, vci.forceMode.Force) end end local function flyByController() if not is_modeactive then return end if not is_onoffswitch then return end --local movedVector = getRelativeControllerYDifference() local movedY = getRelativeControllerYDifference() local anitGravity = anitGravityCoef * vci.vc.room.GetGravity() local force = anitGravity force = force + Vector3.up * movedY * moveCoef -- 雑に逆向きの力をかけてスライドを止める -- SetVelocityは効かない local velocity = playerController.GetVelocity() if velocity.sqrMagnitude > breakThreshold * breakThreshold then force = force -velocity * breakCoef end FireAddForce(force * playerController.GetMass(), "Force") end function Default_pop_pos() --コントローラ位置を自分の目の前に my_chest = character.GetBoneTransform("chest") if my_chest ~= nil then local pos = my_chest["position"] + player.GetForward()*0.5 controller_root.SetPosition(pos) recordInitialTransform() resetInitialPos() end end function CheckModeActive()--modeONOFF判定 is_pre_modeactive = is_modeactive--更新 if attach_sub.IsMine == true then if attach_sub.IsAttached == true then is_modeactive = true else is_modeactive = false end else is_modeactive = false end end local function attach() --位置調整 if is_controllergrabbing then return end --コントローラ掴み中は追従しない if is_modeactive == false then return end --装着してないときは追従しない if is_pre_modeactive == false and is_modeactive == true then return end --装着した瞬間のフレームは追従しない local rotation = Quaternion.LookRotation(controller_root.GetUp(), player.GetPosition() - controller_root.GetPosition()) rotation = Quaternion.Euler(0, rotation.eulerAngles.y, 0) if deltaAttachRot ==nil then return end if deltaAttachPos ==nil then return end controller_root.SetPosition(player.GetPosition() + player.GetRotation() * deltaAttachRot * deltaAttachPos) controller_root.SetRotation(rotation) end function onUse(use) if use == "controller_root" then --基準リセット recordInitialTransform() resetInitialPos() end if use == "attach_sub" then toggleActivation() end end function onGrab(target) if target == "controller_root" then is_controllergrabbing = true elseif "atttach_sub" then is_subgrabbing = true end --かつ装着してない時基準リセット --Default_pop_pos() end function onUngrab(target) if target == "controller_root" then is_controllergrabbing = false elseif "atttach_sub" then is_subgrabbing = false end end function update() my_chest = character.GetBoneTransform("chest") if is_pre_modeactive ~= is_modeactive then --未装着状態から装着状態,またはその逆へと切り替わった時 --基準位置のリセットを行う --コントローラ位置を自分の目の前に Default_pop_pos() --スイッチの状態も自動切り替え is_onoffswitch = is_modeactive elseif is_subgrabbing == true then Default_pop_pos() end --モデルの表示非表示切り替え if is_onoffswitch == true then controller_model.SetActive(true) else controller_model.SetActive(false) end CheckModeActive() flyByController() attach() end