0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

「VキャスのVCIで◯ine◯raftっぽいもの作る Advent Calendar 2024」12日目

Vキャス内で、穴を掘って、石を砕き、木を切って、組み合わせて武器を作って、何なら出てくる敵を倒して・・・
そんなことをやりたいなぁっていう試みを12月でできるところまで行こうというカレンダーの12日目です!

今日は装着した状態でも持ち運べるようにしていきます。

持ち物の概念をつくる その4

装着のコードも書いていくので今日はコード整理をメインにやっています。
手順は以下の通り。

① 追従コードを変更する
② 装着しているときと持っているときで追従オブジェクトを切り替える

さっそくやっていきます。

手順

① 追従コードを変更する

一昨日の時点では、CubeとCylinderを掴んだときだけに追従したら良いと思っていたのですが、
よくよく考えると手につけた状態では、Sphereに追従する必要がありました。
つまり場合によって3種類のオブジェクトのどれを追従するということがあり得るということです。

そこで、変数へのオブジェクトの格納の書き方や追従の書き方を整理します。

SubItems = {
    Cube = {item=vci.assets.GetTransform("Cube")},
    Cylinder = {item=vci.assets.GetTransform("Cylinder")},
    Sphere = {item=vci.assets.GetTransform("Sphere")},
    slot1 = {item=vci.assets.GetTransform("slot1")},
    slot2 = {item=vci.assets.GetTransform("slot2")},
    slot3 = {item=vci.assets.GetTransform("slot3")},
    slot4 = {item=vci.assets.GetTransform("slot4")},
    slot5 = {item=vci.assets.GetTransform("slot5")},
    slot6 = {item=vci.assets.GetTransform("slot6")},
    slot7 = {item=vci.assets.GetTransform("slot7")},
    slot8 = {item=vci.assets.GetTransform("slot8")},
    select = {item=vci.assets.GetTransform("select")},
    l_v = {item=vci.assets.GetTransform("l_v")}
}

宣言は全てのオブジェクトをまとめてにしました。
わざわざ変数を分けて記述が増えるのも良くないのでまとめてしまいます。

そして、CubeとCylinder、Sphereの3つのオブジェクトからの距離と角度を格納します。
サイズも直書きするより、元のサイズを取得しておいたほうが正確だしコードが減るので、変数内に格納しておきます。

for key, value in pairs(SubItems) do
    if key ~= "Cube" then
        SubItems[key].cubedist = SubItems[key].item.GetPosition() - SubItems.Cube.item.GetPosition()
        SubItems[key].cuberoat = Quaternion.Inverse(SubItems[key].item.GetRotation()) * SubItems.Cube.item.GetRotation()
    end
    if key ~= "Cylinder" then
        SubItems[key].cylinderdist = SubItems[key].item.GetPosition() - SubItems.Cylinder.item.GetPosition()
        SubItems[key].cylinderroat = Quaternion.Inverse(SubItems[key].item.GetRotation()) * SubItems.Cylinder.item.GetRotation()
    end
    if key ~= "Sphere" then
        SubItems[key].spheredist = SubItems[key].item.GetPosition() - SubItems.Sphere.item.GetPosition()
        SubItems[key].sphereroat = Quaternion.Inverse(SubItems[key].item.GetRotation()) * SubItems.Sphere.item.GetRotation()
    end
    SubItems[key].Scale = SubItems[key].item.GetLocalScale()
end
SubItems.Cube["roat"] = Quaternion.Inverse(SubItems.Cube.item.GetRotation())
SubItems.Cylinder["roat"] = Quaternion.Inverse(SubItems.Cylinder.item.GetRotation())
SubItems.Sphere["roat"] = Quaternion.Inverse(SubItems.Sphere.item.GetRotation())

変数を変えたので、それに従ってCubeとCylinderの追従コードの記述も更新。

if mode then
    local pos = SubItems.Cube.item.GetPosition()
    local roat = SubItems.Cube.item.GetRotation()
    for key, value in pairs(SubItems) do
        if key ~= "Cube" then
            local offset = roat * SubItems.Cube["roat"] * SubItems[key].cubedist
            local pos_d = pos + offset
            SubItems[key].item.SetPosition(pos_d)
            SubItems[key].item.SetRotation(roat * Quaternion.Inverse(SubItems[key].cuberoat))
        end
    end
else
    local pos = SubItems.Cylinder.item.GetPosition()
    local roat = SubItems.Cylinder.item.GetRotation()
    for key, value in pairs(SubItems) do
        if key ~= "Cylinder" then
            local offset = roat * SubItems.Cylinder["roat"] * SubItems[key].cylinderdist
            local pos_d = pos + offset
            SubItems[key].item.SetPosition(pos_d)
            SubItems[key].item.SetRotation(roat * Quaternion.Inverse(SubItems[key].cylinderroat))
        end
    end
end

変数にまとめたので記述は短くてすむようになりました。

そして、ON/OFFの関数での拡大縮小も変数に格納したものを利用するように書き換えます。

function setON()
    for key, value in pairs(SubItems) do
        if key == "Cylinder" then
            SubItems[key].item.SetLocalScale(Vector3.__new(0.001,0.001,0.001))
        else
            SubItems[key].item.SetLocalScale(SubItems[key].Scale)
        end
    end
end

function setOFF()
    for key, value in pairs(SubItems) do
        if key == "Cylinder" or key == "Sphere" then
            SubItems[key].item.SetLocalScale(SubItems[key].Scale)
        else
            SubItems[key].item.SetLocalScale(Vector3.__new(0.001,0.001,0.001))
        end
    end
end

こちらも短くなりました。

② 装着しているときと持っているときで追従オブジェクトを切り替える

あとは、装着オブジェクトを装着しているときは、装着したオブジェクトを追従させ、CubeかCylinderを持っているときはそちらを追従するように切り替えるコードを書きます。

まず、CubeかCylinderを持っているとき、という状態を見る変数「grab」を作ります。
初期は掴んでないので、値はfalseとします。

grab = false

そして、オブジェクトを掴んだタイミングで掴んだフラグをONにします。
CubeもしくはCylinderをみ始め(onGrab関数が発火する)たら、掴んだ状態(grab = true)。

function onGrab(subItemName)
    if subItemName=="Cube" or subItemName=="Cylinder" then
        grab = true
    end
end

そして、CubeもしくはCylinderを掴み終え(onUnGrab関数が発火する)たら、掴んだ状態解除(grab = false)に切り替わる処理を書きます。

function onUngrab(subItemName)
    if subItemName=="Cube" or subItemName=="Cylinder" then
        grab = false
    end
end

これでgrabを見ると、掴んでいるかいないかわかるので、updateAllの処理に分岐を書きます。
grabがfalseの場合は、Sphere(装着オブジェクト)を追従するという記述です。

function updateAll()
    if grab == false then
        local pos = SubItems.Sphere.item.GetPosition()
        local roat = SubItems.Sphere.item.GetRotation()
        for key, value in pairs(SubItems) do
            if key ~= "Sphere" then
                local offset = roat * SubItems.Sphere["roat"] * SubItems[key].spheredist
                local pos_d = pos + offset
                SubItems[key].item.SetPosition(pos_d)
                SubItems[key].item.SetRotation(roat * Quaternion.Inverse(SubItems[key].sphereroat))
            end
        end
    else

最後のelseにCubeとCylinderの追従コードの記述をそのままくっつけて、これで完成です。
コードの全体は以下の通り。

SubItems = {
    Cube = {item=vci.assets.GetTransform("Cube")},
    Cylinder = {item=vci.assets.GetTransform("Cylinder")},
    Sphere = {item=vci.assets.GetTransform("Sphere")},
    slot1 = {item=vci.assets.GetTransform("slot1")},
    slot2 = {item=vci.assets.GetTransform("slot2")},
    slot3 = {item=vci.assets.GetTransform("slot3")},
    slot4 = {item=vci.assets.GetTransform("slot4")},
    slot5 = {item=vci.assets.GetTransform("slot5")},
    slot6 = {item=vci.assets.GetTransform("slot6")},
    slot7 = {item=vci.assets.GetTransform("slot7")},
    slot8 = {item=vci.assets.GetTransform("slot8")},
    select = {item=vci.assets.GetTransform("select")},
    l_v = {item=vci.assets.GetTransform("l_v")}
}
for key, value in pairs(SubItems) do
    if key ~= "Cube" then
        SubItems[key].cubedist = SubItems[key].item.GetPosition() - SubItems.Cube.item.GetPosition()
        SubItems[key].cuberoat = Quaternion.Inverse(SubItems[key].item.GetRotation()) * SubItems.Cube.item.GetRotation()
    end
    if key ~= "Cylinder" then
        SubItems[key].cylinderdist = SubItems[key].item.GetPosition() - SubItems.Cylinder.item.GetPosition()
        SubItems[key].cylinderroat = Quaternion.Inverse(SubItems[key].item.GetRotation()) * SubItems.Cylinder.item.GetRotation()
    end
    if key ~= "Sphere" then
        SubItems[key].spheredist = SubItems[key].item.GetPosition() - SubItems.Sphere.item.GetPosition()
        SubItems[key].sphereroat = Quaternion.Inverse(SubItems[key].item.GetRotation()) * SubItems.Sphere.item.GetRotation()
    end
    SubItems[key].Scale = SubItems[key].item.GetLocalScale()
end
SubItems.Cube["roat"] = Quaternion.Inverse(SubItems.Cube.item.GetRotation())
SubItems.Cylinder["roat"] = Quaternion.Inverse(SubItems.Cylinder.item.GetRotation())
SubItems.Sphere["roat"] = Quaternion.Inverse(SubItems.Sphere.item.GetRotation())

function setON()
    for key, value in pairs(SubItems) do
        if key == "Cylinder" then
            SubItems[key].item.SetLocalScale(Vector3.__new(0.001,0.001,0.001))
        else
            SubItems[key].item.SetLocalScale(SubItems[key].Scale)
        end
    end
end

function setOFF()
    for key, value in pairs(SubItems) do
        if key == "Cylinder" or key == "Sphere" then
            SubItems[key].item.SetLocalScale(SubItems[key].Scale)
        else
            SubItems[key].item.SetLocalScale(Vector3.__new(0.001,0.001,0.001))
        end
    end
end

mode = true
grab = false
setON()

function updateAll()
    if grab == false then
        local pos = SubItems.Sphere.item.GetPosition()
        local roat = SubItems.Sphere.item.GetRotation()
        for key, value in pairs(SubItems) do
            if key ~= "Sphere" then
                local offset = roat * SubItems.Sphere["roat"] * SubItems[key].spheredist
                local pos_d = pos + offset
                SubItems[key].item.SetPosition(pos_d)
                SubItems[key].item.SetRotation(roat * Quaternion.Inverse(SubItems[key].sphereroat))
            end
        end
    elseif mode then
        local pos = SubItems.Cube.item.GetPosition()
        local roat = SubItems.Cube.item.GetRotation()
        for key, value in pairs(SubItems) do
            if key ~= "Cube" then
                local offset = roat * SubItems.Cube["roat"] * SubItems[key].cubedist
                local pos_d = pos + offset
                SubItems[key].item.SetPosition(pos_d)
                SubItems[key].item.SetRotation(roat * Quaternion.Inverse(SubItems[key].cuberoat))
            end
        end
    else
        local pos = SubItems.Cylinder.item.GetPosition()
        local roat = SubItems.Cylinder.item.GetRotation()
        for key, value in pairs(SubItems) do
            if key ~= "Cylinder" then
                local offset = roat * SubItems.Cylinder["roat"] * SubItems[key].cylinderdist
                local pos_d = pos + offset
                SubItems[key].item.SetPosition(pos_d)
                SubItems[key].item.SetRotation(roat * Quaternion.Inverse(SubItems[key].cylinderroat))
            end
        end
    end
end

function onGrab(subItemName)
    if subItemName=="Cube" or subItemName=="Cylinder" then
        grab = true
    end
end

function onUngrab(subItemName)
    if subItemName=="Cube" or subItemName=="Cylinder" then
        grab = false
    end
end

function onUnuse(subItemName)
    if subItemName == "l_v" and mode==true then
        mode = false
        setOFF()
    elseif subItemName == "Cylinder" and mode==false then
        mode = true
        setON()
    end
end

おわりに

今日までで、やっと情報表示板を持ち運び、そして手につけて追従させられるようになりました。
20241212224905_1.jpg

明日はやっと、もともとやりたかったアイテムの所有ということをこの情報表示版に実装していきます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?