ユーザ用ツール

サイト用ツール


Language:

サイドバー

バーチャルキャスト公式Wiki

メニュー

Steam版

デバイス

アセット

配信

その他

リリース情報

デベロッパー向け


開発環境

GLB

vci:sample:gameapi:teleportgun

テレポートガン

対応バージョンは、UniVCI v0.35以降です。

銃で入り口のゲートと出口のゲートを発射し、接触すると互いにワープが出来るVCIです。

サンプルデータ

Unitypackage

コンポーネント設定

VCI Object

Sub Item 設定一覧 (クリックで展開)
VCI Sub Item 1 : GateRoot x2

CameraRoot
カメラの位置調整用のオブジェクト

VCI Sub Item 2 : ChangeGateBulletButton

VCI Sub Item 3 : Gun

VCI Sub Item 4 : GateBullet

VCIスクリプト

main.lua
----------------------------------------------------------
--- テレポートガン(ルーム限定)
--- 弾丸が当たった2点間をテレポートできるゲートが設置されます
----------------------------------------------------------
 
---ガンのオブジェクト名
local GUN_NAME = "Gun"
---弾丸のオブジェクト名
local BULLET_NAME = "GateBullet"
---弾丸変更ボタンのオブジェクト名
local CHANGE_GATE_BULLET_BUTTON = "ChangeGateBulletButton"
---撃ちだす弾丸のマテリアル
local NOW_GATE_COLOR_MATERIAL = "NowBulletColor"
---最大ゲート数
local MAX_GATE = 2
 
---ゲート2種の色定義
local GATE_COLOR = {
    Color.__new(1, 0.517647, 0.2392156) * 2,
    Color.__new(0.240566, 0.8085719, 1) * 2
}
 
---プレイヤー情報
local localPlayer = vci.vc.room.GetLocalPlayer()
local playerController = localPlayer.GetRoomPlayerController()
 
---@type ExportTransform[] ゲートオブジェクト
local gates = {}
for gateID = 1, MAX_GATE do
    gates[gateID] = {
        root = vci.assets.GetTransform("GateRoot" .. gateID),
        screen = vci.assets.GetTransform("ScreenRoot" .. gateID)
    }
    gates[gateID].screen.SetActive(false)
    vci.assets.material.SetColor("GateColor" .. gateID, GATE_COLOR[gateID])
end
 
---ガン
local gunRoot = vci.assets.GetTransform(GUN_NAME)
---発射位置
local shotPoint = vci.assets.GetTransform("ShotPoint")
---弾丸
local gateBullet = vci.assets.GetTransform(BULLET_NAME)
---現在設定されている弾丸のゲートID
local nowGateBulletID = 1
---弾丸のゲートID変更ボタン
local changeGateBulletButton = vci.assets.GetTransform(CHANGE_GATE_BULLET_BUTTON)
---ボタンのスナップ位置
local snapChangeGateBulletButton = vci.assets.GetTransform("SnapChangeGateBulletButton")
---弾丸の発射した方向
local shotForward = Vector3.__new(0, 0, 1)
vci.assets.material.SetColor(NOW_GATE_COLOR_MATERIAL, GATE_COLOR[nowGateBulletID])
 
---反対ゲートの風景を映すカメラ
local cameraRoot = vci.assets.GetTransform("CameraRoot")
---カメラAPIを適用するオブジェクト
local camera = vci.assets.GetTransform("Camera")
local photographyCamera = vci.cameraSystem.CreatePhotographyCamera(camera)
-- プレビュー描画
local previewTextureId = photographyCamera.GetCameraPreviewTextureId()
vci.assets.material.SetTexture("Screen", previewTextureId)
 
---ゲートが両方ともアクティブになっている
local isGateBothActive = false
---現在自分プレイヤーと一番近いゲートID
local closestGateID = 0
 
---全ユーザーで毎フレーム呼ばれる
function updateAll()
    --自分と各ゲートの距離を測定
    local playerPos = localPlayer.GetPosition()
    local gateDistances = {}
    for gateID = 1, #gates do
        local gatePos = gates[gateID].root.GetPosition()
        local distanceForward = gatePos - playerPos
        distanceForward.y = distanceForward.y / 4
        gateDistances[gateID] = Vector3.Distance(distanceForward, Vector3.zero)
    end
 
    --ゲートに近づいた場合、反対のゲートにテレポートする
    for gateID = 1, #gates do
        if gateDistances[gateID] < 0.5 then
            --反対のゲートに移動する
            local exitGateID = gateID + 1
            if exitGateID > 2 then
                exitGateID = 1
            end
            local exitGatePos = gates[exitGateID].root.GetPosition()
            local exitGateRot = gates[exitGateID].root.GetRotation()
            --反対ゲートへ移動後のプレイヤーの方向を計算
            local playerRot = localPlayer.GetRotation()
            local enterGateRot = gates[gateID].root.GetRotation()
            local resultRot = Quaternion.Euler(0, (exitGateRot.eulerAngles.y - enterGateRot.eulerAngles.y) + playerRot.eulerAngles.y + 180, 0)
            playerController.TeleportTo(exitGatePos + (exitGateRot * Vector3.__new(0, 0, 1)), resultRot)
        end
    end
 
    --二つのゲートが出現している場合、近いゲートから反対ゲートの風景を映し出す(非同期)
    if isGateBothActive then
        if (gateDistances[1] < gateDistances[2]) and (closestGateID ~= 1) then
            cameraRoot.SetPosition(gates[2].root.GetPosition())
            cameraRoot.SetRotation(gates[2].root.GetRotation())
            gates[2].screen.SetActive(false)
            gates[1].screen.SetActive(true)
            closestGateID = 1
        elseif (gateDistances[2] < gateDistances[1]) and (closestGateID ~= 2) then
            cameraRoot.SetPosition(gates[1].root.GetPosition())
            cameraRoot.SetRotation(gates[1].root.GetRotation())
            gates[1].screen.SetActive(false)
            gates[2].screen.SetActive(true)
            closestGateID = 2
        end
    else
        --二つのゲートが出現しているかチェック(出現中はゲートのスケールが1になっている状態とする)
        if (gates[1].root.GetLocalScale().x > 0.5) and (gates[2].root.GetLocalScale().x > 0.5) then
            isGateBothActive = true
        end
    end
 
    --弾丸変更ボタンをスナップ
    if gunRoot.IsMine then
        changeGateBulletButton.SetPosition(snapChangeGateBulletButton.GetPosition())
    end
end
 
---[SubItemの所有権&Use状態]アイテムをグラッブしてグリップボタンを押すと呼ばれる。
---@param use string @押されたアイテムのSubItem名
function onUse(use)
    --ガンから弾丸を発射
    if use == GUN_NAME then
        gateBullet._ALL_SetActive(true)
        gateBullet.SetPosition(shotPoint.GetPosition())
        gateBullet.SetRotation(shotPoint.GetRotation())
        shotForward = shotPoint.GetForward()
        gateBullet.SetVelocity(shotForward * 30)
    end
 
    --弾丸のゲートID変更(非同期)
    if use == CHANGE_GATE_BULLET_BUTTON then
        nowGateBulletID = nowGateBulletID + 1
        if nowGateBulletID > MAX_GATE then
            nowGateBulletID = 1
        end
        vci.assets.material.SetColor(NOW_GATE_COLOR_MATERIAL, GATE_COLOR[nowGateBulletID])
    end
end
 
---[SubItemの所有権]アイテムにCollider(not Trigger)が接触したときに呼ばれる。
---@param item string @SubItem名
---@param hit string @Collider名
function onCollisionEnter(item, hit)
    --弾丸が何かしらのコライダーに当たった場合、ゲート発生
    if item == BULLET_NAME then
        --弾丸の発射方向から、逆方向かつ水平のベクトルを取得
        local lookForward = shotForward * -1
        lookForward.y = 0
        lookForward = lookForward.normalized
        --弾丸のTransformからゲートの出現位置を設定
        local bulletPos = gateBullet.GetPosition()
        local gatePos = bulletPos + (lookForward * 0.5) + Vector3.__new(0, -0.5, 0)
        local gateRot = Quaternion.LookRotation(lookForward)
        gates[nowGateBulletID].root.SetPosition(gatePos)
        gates[nowGateBulletID].root.SetRotation(gateRot)
        gates[nowGateBulletID].root.SetLocalScale(Vector3.__new(1, 1, 1))
        --弾丸を非アクティブ化
        gateBullet._ALL_SetActive(false)
    end
end
vci/sample/gameapi/teleportgun.txt · 最終更新: 2023/05/09 13:24 by pastatto

ページ用ツール