【ロブロックスでプログラミング学習】ゲームの作り方!Part05 NPCの作り方

Roblox

敵モンスターNPCを作ろう!その1

前回までで基本的な戦闘システムを作ったので、これからはいろいろな種類のモンスターを作りながらプログラミングを学習していくよ。

敵モンスターNPCのモデリング

プログラミングの学習だけならダミーのNPCで十分なんだけど、プログラミング学習で1番大事なことは学習のモチベーションをキープすること。やっぱり自分でモンスターがデザインできた方が楽しいしモチベーションもアップするよ。(=゚ω゚)ノ

RobloxStudioでもモデリングはできるけど、モデリング専用の「Blender」っていうツールがあるからプログラミング学習ついでにモデリング学習もしてみよう♪

「Blender」の学習に興味なければ、「PLUGINS」>「BuildRig」からダミーが作れるから読み飛ばしてね。

Dummy

モデリング

Blenderを起動して、「File」>「New」>「General」

「Collection」の「Camera」「Light」を削除。

カメラとライトの削除

オブジェクトを選択して、「Add Modifier」からレベル3の「Subdivision」を追加。

SubdivisionSurface
Subdivision

オブジェクトの右クリックから「Shade Smooth」。

ShadeSmooth

オブジェクトを選択してZ軸方向にサイズ縮小([S]キー → [Z]キー)。左クリックで確定。

Z軸サイズ縮小

[Tab]キーで編集モードに切り替え。さらに[3]キーで面選択モードに切り替えて上面を選択。

上面選択

[E]キーで面の押し出し。左クリックで確定。

[E]キー上面押し出し

[S]キーで面のサイズ縮小。左クリックで確定。

[S]キー上面サイズ縮小

押し出しとサイズ縮小を繰り返して好みの形状に。

[E]キー[S]キー繰り返し

UV展開

テンキー[1]で視点を正面。キーボードの[2]キーで辺選択モードに切り替えて、オブジェクトの正面部分を囲うように[Shift]キーを押しながら辺を複数選択

全面辺選択

[Ctrl]+[E]キーから辺にMarkSeam(縫い目)。

MarkSeam

[A]キーでオブジェクトを全選択。[U]キーから[Unwrap]。

テクスチャーペイント

「Texture Paint」メニューに移り、「Texture Slots」の「+」から「Base Color」をAlphaのチェックを外してOK。

BaseColor

UV展開側に作ったBaseColorを適用。

MaterialBaseColor適用

UV展開側を好みの色でブラッシング。

顔はペイントはお好みで。symmetryをX軸方向に設定して目だけペイント。

今回はこんな感じにしたよ。

目のペイントおわり

テクスチャイメージをファイル保存してからPack。

Pack

Blenderからobjファイルのエクスポート

Fileメニューで「Save」してからobj形式でエクスポート。

Export

Blenderはここまで。

RobloxStudioにobjファイルのインポート

次はRobloxStudio に移って、Workspaceに「MeshPart」を追加。

MashPart追加

Propertiesの「MeshId」のフォルダアイコンをクリックして、さっきBlenderからエクスポートしたobjファイルを選択。

「ぷよいむ」があらわれた。

メッシュとテクスチャが読み込まれたら成功だよ!

NPCの設定

NPCのModelには最低限「HumanoidRootPart」っていう中心となる部品が必要なのと、頭上にNPCの名前ラベルを表示させたいから「Head」っていう部品も欲しいんだ。

今回は追加したMeshPartを「頭」にしちゃうよ。

MeshPartのPropertiesからNameを「Head」に変更。

次に「HumanoidRootPart」。Workspaceに「Part」を追加。

「Part」のPropertiesから「Name」を「HumanoidRootPart」に変更。

「Head」より小さめにスケーリング。

HumanoidRootPart

「Head」に「HumanoidRootPart」を埋め込みたいんだけど、Propertiesの「CanColide」のチェックを外すとぶつからずに重ねることができるよ。

HumanoidRootPart埋め込み

Moveを使って「HumanoidRootPart」がうまく「Head」に隠れたら、この2つをグループ化。

グループ化したら1つの「Model」ができたね。この「Model」のPropertiesの「Name」をキャラクターの名前に変えよう。ここでは「ぷよいむ」にするよ。

次にRobloxでは最低1つ以上のJoint(関節)がないとアニメーションをつけられないようだから「HumanoidRootPart」と「Head」をJointでつなぐよ。「HumanoidRootPart」の「+」から「Motor6D」を追加。

追加した「Motor6D」のPropertiesの「Part0」の右枠の空欄をクリックするとカーソルが選択アイコンに変わるからExplorerから「HumanoidRootPart」を選択しよう。「Part1」も同じように右枠の空欄をクリックしてから今度は「Head」を選択しよう。これで2つのパーツがJointでつながるんだ。

次にNPCにはもう1つ大事なものがあって「Humanoid」っていう属性をつけてあげる必要があるよ。「Humanoid」には歩く速度、ジャンプ力、体力とか、キャラクターに必要ないろんな設定があるんだ。

モデルの「+」から「Humanoid」を追加。

Humanoid追加

これで敵モンスターのモデルは完成!

あとはプログラミングで動かしてみよう♪

プレイヤーを追いかけるプログラミング

敵モンスターのモデルの「+」から「Script」を追加。

local npc = script.Parent
local hrpOfNPC = npc:WaitForChild("HumanoidRootPart")

while wait(1) do
  local plrs = game.Players:GetPlayers()
  local closestHRP

  for i, plr in pairs(plrs) do
    if plr.Character and plr.Character:FindFirstChild("HumanoidRootPart")  then
      local hrp = plr.Character.HumanoidRootPart 
      local betweenDistance = (hrpOfNPC.Position - hrp.Position).Magnitude
      
      if closestHRP == nil then
        closestHRP = hrp
      elseif betweenDistance < (hrpOfNPC.Position - closestHRP.Position).Magnitude then
        closestHRP = hrp
      end
      
    end
  end

  if closestHRP then 
    npc.Humanoid:MoveTo(closestHRP.Position) 		
  end
end

ひとつずつ見ていこう。

local npc = script.Parent

この「script.Parent」は、このスクリプトの親なので、敵モンスターのモデルを「npc」っていう変数でアクセスできるようにしてるよ。

local hrpOfNPC = npc:WaitForChild("HumanoidRootPart")

ここは、NPCの「HumanoidRootPart」を「hrpOfNPC」っていう変数でアクセスできるようにしているよ。

while wait(1) do

ここは最後の「end」までの処理を1秒ごとに繰り返す書き方だよ。

次にWhile文の繰り返し処理を見ていこう。

local plrs = game.Players:GetPlayers()

ここは、ゲームにログインしているプレイヤーたちを取得して「plrs」っていう変数でアクセスできるようにしているよ。

local closestHRP

ここは、あとで何回もアクセスしたいから変数だけ用意しているんだね。

for i, plr in pairs(plrs) do

ここは、For文も繰り返し処理の書き方だね。ゲームにログインしているプレイヤーたちをひとりずつ取り出して「plr」っていう変数に入れて、人数分繰り返しているよ。

次にFor文の繰り返し処理を見ていこう。

if plr.Character and plr.Character:FindFirstChild("HumanoidRootPart")  then

ここは、取り出したプレイヤーが「キャラクター」かつ「HumanoidRootPart」を持っているか確認しているよ。確認しないで「HumanoidRootPart」にアクセスすると、なかった場合エラーになっちゃうんだ。

local hrp = plr.Character.HumanoidRootPart

ここは、「HumanoidRootPart」があることがわかったら、「hrp」っていう変数でアクセスできるようにしているよ。

local betweenDistance = (hrpOfNPC.Position - hrp.Position).Magnitude

ここは、敵モンスターの「HumanoidRootPart」の座標とゲームにログインしているプレイヤーのうちのひとりの「HumanoidRootPart」の座標の差の大きさを「betweenDistance」っていう変数でアクセスできるようにしているよ。

if closestHRP == nil then

ここは、あらかじめ用意していた「closestHRP」変数が空のとき、初回のループのときだけ空のはずだから初回は必ず「closestHRP = hrp」を実行するよ。あらかじめ用意しておいた「closestHRP」変数にゲームにログインしているプレイヤーのうちのひとりの「HumanoidRootPart」を格納しているよ。

elseif betweenDistance < (hrpOfNPC.Position - closestHRP.Position).Magnitude then

ここは、2回目以降のループ処理になるね。今回の敵NPCとプレイヤーの座標の差が前回の差より小さいときだけ「closestHRP」変数を上書き更新しているね。これで敵NPCは一番近くにいるプレイヤーの座標が取得できるようになるんだ。

ゲームにログインしているプレイヤー数分のFor文が終わったら、

npc.Humanoid:MoveTo(closestHRP.Position)

これで、このNPCを一番近く人いるプレイヤーの座標へ移動させているよ。

それじゃあ。実際にテストしてみよう。

追跡

プレイヤーを追いかけてくれば成功だよ!

NPCのHumanoidのPropertiesに「WalkSpeed」っていう設定があるから、その数値をいじって追跡スピードを調整してみてね^^

次回はこの敵NPCがプレイヤーを攻撃するプログラミングをしてみるよ!

それじゃ~またね~。(@^^)/~~~

コメント

タイトルとURLをコピーしました