Roblox開発 Tipsメモ
Partの CanQuery
がtrueだと、RayCastが当たる。
CanCollide
がtrueの時はCanQueryは暗黙的にtrue(StudioのUIにそもそも表示されない)。
CanTouch
はRayCastが当たるかどうかに無関係。
Soundを立体音響にするには、SoundがPart直下の子オブジェクトになっていないといけない。
※Modelの子オブジェクトだと立体音響にならない
Rolox Studioでソロプレイ中、 Shift + P
でスクリーンショットモードになる。
UIが非表示になり、WASDキーで自由に動ける。
プレースの太陽と月を表示するかどうかは、Skyオブジェクトの CelestialBodiesShown
で変更できる。
HttpService:JSONDecode
をすると配列で返ってくる。つまり data.output
みたいにKey名を指定しても取れない。
しかし、さらにもう一度 HttpService:JSONDecode
を重ねると、Dictionary型になるので data.output
で値をとれる!
SoundはFolder内なら複数入れて再生できるが、Partには複数入れると再生できなくなる。
以下のようにするのはOK
RobloxのLuaでは goto
文は使えない
サーバースクリプトでのプレイヤー参加時処理覚書
local Players = game:GetService("Players")
local function initializePlayer(player)
-- 初期化処理
end
for _, player in Players:GetPlayers() do
initializePlayer(player)
end
Players.PlayerAdded:Connect(initializePlayer)
ドッスンTween覚書
local TweenService = game:GetService("TweenService")
local dossun = script.Parent:WaitForChild("Dossun")
local height = script.Parent:GetAttribute("Height")
local upTime = script.Parent:GetAttribute("UpTime")
local downTime = script.Parent:GetAttribute("DownTime")
local awaitTime = script.Parent:GetAttribute("AwaitTime")
local upPosition = dossun.Position + Vector3.new(0, height, 0) -- 上昇後の位置
local downPosition = dossun.Position -- 元の位置(下降後の位置)
local upTweenInfo = TweenInfo.new(upTime, Enum.EasingStyle.Linear, Enum.EasingDirection.Out) -- 上昇のTween情報
local downTweenInfo = TweenInfo.new(downTime, Enum.EasingStyle.Linear, Enum.EasingDirection.Out) -- 下降のTween情報
local upTween = TweenService:Create(dossun, upTweenInfo, {Position = upPosition})
local downTween = TweenService:Create(dossun, downTweenInfo, {Position = downPosition})
while true do
upTween:Play() -- 上昇開始
upTween.Completed:Wait() -- 上昇が完了するまで待つ
downTween:Play() -- 下降開始
downTween.Completed:Wait() -- 下降が完了するまで待つ
wait(awaitTime) -- 3秒間停止
end
ModuleScriptは StarterPlayerScripts
などのローカル環境に作成して配置することもできる。
そうすることで、LocalScript間でModuleScript内のグローバル変数を共有することが可能に。
RunService.Stepped
を使えば、毎フレームの物理演算前に処理をすることが出来、引数のstepで前フレームからの秒数を取得できる。
local RunService = game:GetService("RunService")
local RATE_PER_SECOND = 2
RunService.Stepped:Connect(function(time, step)
local increment = RATE_PER_SECOND * step
end)
サーバースクリプトでToolsをBackpackに入れる際、CharacterAddedを待たないと正常に動作しない。
--- local functions ---
local function setSpeedCoil(player)
player.CharacterAdded:Wait()
local coilInBackpack = player.Backpack:FindFirstChild("Speed Coil")
if coilInBackpack then
return
end
local speedCoil = ServerStorage:WaitForChild("Speed Coil")
if speedCoil then
local coilClone = speedCoil:Clone()
coilClone.Parent = player.Backpack
end
end
--- player added ---
for _, player in Players:GetPlayers() do
setSpeedCoil(player)
end
Players.PlayerAdded:Connect(function(player)
setSpeedCoil(player)
end)
SetFavoriteや
FriendInviteのコード
local success, errorMessage = pcall(function()
local ExperienceInviteOptions = Instance.new("ExperienceInviteOptions")
ExperienceInviteOptions.PromptMessage = "Enjoy the quiz with your FRIENDS!"
SocialService:PromptGameInvite(player, ExperienceInviteOptions)
end)
はローカルスクリプトでしか動作しない。
{
["key1"] = value1,
["key2"] = value2
}
という形式のテーブルからKeyを指定して行を削除したい場合は
table["key1"] = nil
という風にnilを入れることで、削除される。
player.CharacterAdded:Wait()
を使う際は、すでにCharacterがあったら永遠に待ち続けてしまうため
if not player.Character then
player.CharacterAdded:Wait()
end
と書くように注意
AvatarEditorService:GetFavorite()
を利用するには、 AvatarEditorService:PromptAllowInventoryReadAccess()
でユーザーにアクセス許可を求め、OKしてもらう必要がある。
BillboardGuiの大きさが距離によって変わらないようにするには
SizeのScaleを変更してOffsetは0にする
AudioDeviceOutputをPlayer参加時にPlayer配下に追加する場合、少し待ってから追加しないと正常に動作しない(2024年5月22日時点)
Humanoidアニメーションは、ローカルで動作させてもサーバーで動きが同期される
Humanoidをprintすると以下のエラーが出るのでしないように(2024年6月4日時点)
自分の環境のみで他のプレイヤーを透明にしたい場合、ローカルスクリプトで他のプレイヤーを透明化処理する
local function SetDisplayOtherPlayer(player, active)
local transparency = 0
if active then
transparency = 0
else
transparency = 1
end
if player ~= LocalPlayer then
local character = player.Character
if character then
for _, part in ipairs(character:GetDescendants()) do
if part:IsA("BasePart") then
part.Transparency = transparency
if part:FindFirstChildOfClass("Decal") then
part:FindFirstChildOfClass("Decal").Transparency = transparency
end
elseif part:IsA("Decal") or part:IsA("Texture") then
part.Transparency = transparency
end
end
end
end
end
ローカルスクリプトで、KnitのServiceに定義したClient関数を呼ぶときは、promiseとして返ってくるので必ずawait()する
local result, value = AnythingService:GetSomething():await()
if result then
print(value)
end
OrderedDataStore覚書
local DataStoreService = game:GetService("DataStoreService")
local SomethingStore = DataStoreService:GetOrderedDataStore("SomethingStore")
--- local functions ---
local function SetStore(userId, value)
local success, errorMessage = pcall(function()
SomethingStore:SetAsync(userId, value)
end)
if not success then
print(errorMessage)
end
end
local function GetStore(userId)
local success, val = pcall(function()
return SomethingStore:GetAsync(userId)
end)
if success then
if val == nil then
SetStore(userId, 0)
val = 0
end
return val
end
end
local function ResetStore(userId)
local success, removedVal = pcall(function()
return SomethingStore:RemoveAsync(userId)
end)
if success then
warn("UserId:" .. userId .. "SomethingStore has been removed.")
end
end
local function GetTopRanking(topNum)
local isAscending = false
local pageSize = topNum
local pages = SomethingStore:GetSortedAsync(isAscending, pageSize)
local topScores = pages:GetCurrentPage()
return topScores
end
1000以上の数値を*K表記にする
function FormatNumber(value)
if value >= 1000 then
local kValue = value / 1000
return string.format("%gK", kValue)
else
return tostring(value)
end
end
SurfaceGuiをUIとして機能させるには、StarterGui内に入れて、 Adornee
プロパティにくっつけたいPartを指定する。
NPCをアニメーションさせるときは、HumanoidRootPartのAnchoredをtrueにした方が安定する。
Backpack内のToolの強制Equip/Unequip
--- flags ---
local equipingTool
--- local functions ---
local function SetEnableTools(active)
local humanoid = LocalPlayer.Character:FindFirstChildOfClass("Humanoid")
if humanoid then
if active then
if equipingTool then
humanoid:EquipTool(equipingTool)
end
equipingTool = nil
else
equipingTool = LocalPlayer.Character:FindFirstChildWhichIsA("Tool")
if equipingTool then
humanoid:UnequipTools()
end
end
end
end
アセットのサムネイルを画像として使う
rbxthumb://type=Asset&id=ASSETID&w=150&h=150
upperTorsoのローカル座標系で、offset位置、rotation回転させる
local offset = CFrame.new(0, -0.1, 0.6)
local rotation = CFrame.fromEulerAnglesYXZ(math.rad(30), math.rad(90), 0)
object.CFrame = upperTorso.CFrame * offset * rotation
オブジェクトがDestroyされた時のイベント
Instance.Destroying
debug.tracebackは、その時点に到達するまでに呼び出された関数をさかのぼって表示してくれる。
HTTP POSTリクエスト覚書
local success, result = pcall(function()
print("sending...")
local response = HttpService:RequestAsync({
Url = "ここにエンドポイントをいれる",
Method = "POST",
Headers = {
["Content-Type"] = "application/json",
},
Body = jsonString,
})
return response
end)
if success then
if result.Success then
print("Status code:", result.StatusCode, result.StatusMessage)
print(result.Body)
else
print("The request failed:", result.StatusCode, result.StatusMessage)
end
else
warn(result)
end
Promise.all
はどれか一つrejectされたら即座にrejectされてしまうが、Promise.allSettled
はすべてのPromiseが完了するまで待つ
サーバーの最後の一人が抜けた後1~2秒でサーバーは閉じてしまう。
BindToCloseをつかうことで、30秒ほど猶予が出来る。
以下をコードの最初に記述することで、Studio外の本番環境では動作しないようにできる
if not game["Run Service"]:IsStudio() then return end
WeldConstraintでくっつけたPartについて、
PartをPosition変更で動かしたらそのPartだけが動いてWeldされているPartは動かず、
PartをCFrame変更で動かしたらPartに追従してWeldされているPartも動く
C#でいうところの
var hoge = boolean ? "true" : "false"
はLuaでは
local hoge = boolean and "true" or "false"
と書ける
HumanoidRootPartにPartをWeldする場合、Masslessにしないとその重さに振り回される
Player.LoadCharacter
を実行すると以下の順でイベントが実行される
- Player.Characterセット
- Player.CharacterAddedが発火
- Player.Changedが "Character "の値で発火
- キャラクターの外観が初期化される
- Player.CharacterAppearanceLoadedが発火
- Character.ParentがDataModelに設定
- キャラクターのリグが構築され、キャラクターがスケールする
- キャラクターがスポーン位置に移動する
- LoadCharacterがreturnされる
Roblox開発のテーブル操作
Copy code
table1 = {1, 2, 3}
table2 = table1
table.remove(table2, 1)
上記のようにすると、table2を操作するとtable1にも影響が出てしまう。
理由
table2 = table1 とすると、table2はtable1の参照を持つことになります。つまり、どちらかのテーブルを変更すると、もう片方のテーブルにも同じ変更が反映される。
解決策
table1をコピーしてからtable2に代入することで、独立したテーブルとして操作できる。
Copy code
-- 元のテーブル
table1 = {1, 2, 3}
-- コピー用の新しいテーブルを作成
table2 = {}
-- table1の要素をtable2にコピー
for i, v in ipairs(table1) do
table2[i] = v
end
-- table2から最初の要素を削除
table.remove(table2, 1)
-- 結果確認
print(table1[1]) -- 出力: 1
print(table2[1]) -- 出力: 2
結果
table2から最初の要素を削除しても、table1には影響しません。
table1は元のままの内容を保持します。
table2は変更された内容を持ちます。
所属するグループや自分のアカウントに保存したAnimationを、別のグループに複製したいとき
- RigBuilder でRigをつくる
- Animation Editor ウィンドウを開いてRigを選択し、Import > From Roblox でグループからAnimationを選択
- キーフレームが読み込めたら、Publish to Roblox で複製したいグループに保存
一意な文字列を作成する
HttpService:GenerateGUID()
Motor6Dの制約(謎)
このようにしてWeldConstraintとMotor6Dを組み合わせると、動作が破綻する
全部Motor6Dにしてもダメでした
複数Motorの回転はダメっぽい?
▼
原因はMassだった
Masslessにすることで解消
Modelの大きさを変えずに、Scaleを1にするボタンがある