Unityでゲームを作っていると、かなり早い段階でぶつかるのが「他のスクリプトを操作したい問題」です。
たとえば、こんな場面ですね。
- プレイヤーがダメージを受けたら、HPスクリプトの値を減らしたい
- 敵を倒したら、ScoreManagerのスコアを増やしたい
- ボタンを押したら、別スクリプトの関数を実行したい
でも実際にやってみると、
GetComponentが何をしているのか分からないNullReferenceExceptionが出るpublicにしたのにアクセスできない- なんとなくコピペで動いているけど、仕組みが理解できていない
こんな状態になりやすいんですよね。
私もUnityを始めた頃、「変数はあるのに、なんで取得できないの…?」とかなり混乱しました。
特に“参照”という考え方は、最初は見えない仕組みなので、つまずきやすいポイントです。
ただ、この部分を理解できるようになると、Unityのコードが一気に読みやすくなります。
AI生成コードやチュートリアルも理解しやすくなりますし、「なぜこの書き方をするのか」が分かるようになるので、エラーにも強くなっていきます。
今回は、Unityで他のスクリプトを取得・操作する方法を、初心者が混乱しやすいポイントを整理しながらまとめていきます。
Unityで他のスクリプトを取得する仕組み
Unityで別スクリプトを操作するときに、まず理解しておきたいのが「参照」という考え方です。
ここが曖昧なままだと、GetComponent や Find をコピペで使えても、「なぜ動くのか」が分からず、少し複雑になるだけで詰まりやすくなります。
逆に、この仕組みを理解できると、スクリプト間のやり取りがかなりスッキリ見えるようになりますよ。
そもそも「参照」とは何か
Unityでは、他のスクリプトを操作するために、まず「そのスクリプトがどこにあるか」を知る必要があります。
たとえば、プレイヤーのHPを減らしたい場合を考えてみます。
いきなりこんなコードを書いても、Unityは「どのPlayerScriptのこと?」と判断できません。
hp -= 10;
そこで必要になるのが、“参照”です。
参照は、簡単にいうと「そのデータが存在している場所を指している情報」のことです。
よく住所に例えられます。
- データそのもの → 家
- 参照 → 家の住所
住所が分からないと家に行けないように、Unityでも「どのスクリプトを操作するか」が分からないとアクセスできません。
たとえば、次のコードです。
PlayerScript player;
これを見ると、「PlayerScriptを取得した!」と思いやすいのですが、実はまだ“空の箱”を用意しただけです。
この時点では、まだ何も入っていません。
なので、そのまま使うと NullReferenceException が発生します。
player.hp -= 10;
これは、存在しないものを操作しようとしている状態なんですね。
そのため、実際には次のような処理で「中身」を入れる必要があります。
player = GetComponent<PlayerScript>();
これで初めて、「このGameObjectについているPlayerScriptを使います」という参照が取得できます。
Unity初心者の頃は、
- 変数を宣言しただけ
- publicにしただけ
- 型を書いただけ
この状態で「取得できた」と思いやすいです。
でも実際には、“どの実体を指しているか”まで設定して初めて使えるようになります。
ここを理解すると、Unityのスクリプト参照がかなり見えやすくなりますよ 🙂
publicと[SerializeField]の違い
他のスクリプトからアクセスする話になると、必ず出てくるのが public です。
まずは役割をシンプルに整理してみましょう。
| 書き方 | Inspector表示 | 外部アクセス |
|---|---|---|
| public | 〇 | 〇 |
| [SerializeField] private | 〇 | × |
public は、「他のスクリプトから自由にアクセスできます」という意味です。
public int hp;
これなら、別スクリプトからこう書けます。
player.hp -= 10;
一方で、[SerializeField] は少し役割が違います。
[SerializeField] private int hp;
これは、「Inspectorには表示するけど、外部からは直接触らせない」という設定です。
初心者のうちは、全部publicにしたくなります。
私も最初は“とりあえずpublic祭り”でした(笑)
ただ、慣れてくると、必要以上にpublicを増やすと管理が大変になることが分かってきます。
たとえば、どこからでもHPを書き換えられる状態になると、
- いつ減ったのか分からない
- 想定外の値になる
- デバッグしにくい
こんな事故が起きやすくなります。
そのため、実務では「Inspectorで設定したいだけなら[SerializeField]」を使うケースがかなり多いです。
Inspector管理をさらに快適にしたい場合は、Odin Inspectorのような拡張ツールも便利です。
Odin Inspector
✅アセットストアでチェックする
Unityで別スクリプトを取得する4つの方法
Unityで他のスクリプトを操作する方法はいくつかありますが、実は「全部を同じ感覚で使わない」ことがかなり大切です。
初心者の頃は、動いた方法をずっと使い続けがちなんですよね。
でも実際には、
- 軽い方法
- 安全な方法
- 柔軟だけど重い方法
という違いがあります。
特に Find 系は便利なので乱用しやすいのですが、後から「なんか重い…」「参照切れた…」になりやすいポイントでもあります。
まずは「どの状況で何を使うのか」を整理して覚えるのがおすすめです。
Inspectorで直接アタッチする方法
まず最初に覚えたいのが、この方法です。
事前に「どのオブジェクトを使うか」が決まっているなら、これが一番安全で分かりやすいです。
例えば、PlayerManagerからPlayerHPを操作したい場合は、こんな感じで書きます。
public PlayerHP playerHP;
または、実務寄りに書くならこちらです。
[SerializeField] private PlayerHP playerHP;
すると、Inspectorに空欄が表示されます。
そこへ対象のGameObjectをドラッグ&ドロップすれば、参照設定が完了です。
この方法の良いところは、Unityエディタ上で「どのオブジェクトにつながっているか」が見えることです。
初心者がつまずきやすい“見えない参照”が、かなり分かりやすくなります。
しかも、検索処理をしないので軽いです。
そのため、実際の開発でもかなり多用されます。
特に以下のようなケースでは最優先で考えてOKです。
- UIとManagerの接続
- プレイヤーとHPバー
- 敵とステータス管理
- 事前配置されたオブジェクト同士
逆に、よくある失敗もあります。
- Inspector設定忘れ
- Prefab差し替え後にMissing
- 別Prefabを参照していた
「コードは合ってるのに動かない…」時は、かなりの確率でInspector参照漏れです(笑)
まずここを見るクセを付けると、デバッグがかなり早くなります。
GetComponentで取得する方法
GetComponent は、同じGameObjectについている別コンポーネントを取得する方法です。
たとえば、PlayerObjectに以下のスクリプトが付いているとします。
- PlayerMove
- PlayerHP
- PlayerAttack
この場合、PlayerMoveからPlayerHPを取得できます。
private PlayerHP playerHP;
void Start()
{
playerHP = GetComponent<PlayerHP>();
}
ここで初心者がかなり勘違いしやすいのですが、GetComponent はシーン全体検索ではありません。
「今このスクリプトが付いているGameObjectの中から探す」処理です。
なので、かなり軽いですし、Unityらしい書き方でもあります。
ただし、注意点もあります。
初心者の頃によくやってしまうのがこちらです。
void Update()
{
GetComponent<PlayerHP>();
}
これは毎フレーム取得処理をしています。
1回だけ取得すればいいのに、毎秒何十回も探している状態なんですね。
小規模なら問題ない場合もありますが、クセになると後で重くなりやすいです。
なので基本は、
- Awake
- Start
で一度取得して保存(キャッシュ)するのがおすすめです。
「同じオブジェクト内の別スクリプトを使いたい」なら、まずGetComponentを考えるくらいでちょうどいいですよ。
Find系で取得する方法
Unityには、シーン内を検索して取得する方法もあります。
代表的なのは以下ですね。
GameObject.Find("Player");
FindFirstObjectByType<PlayerHP>();
FindAnyObjectByType<PlayerHP>();
これは「今シーン内にあるオブジェクトを探して取得する」方法です。
事前にInspector設定をしなくても動くので、かなり便利に感じます。
ただ、その代わり検索コストがあります。
特に GameObject.Find は名前検索なので、
- オブジェクト名変更で壊れる
- スペルミスで失敗する
- nullになりやすい
という問題が起きやすいです。
さらに危険なのが、Update内での使用です。
void Update()
{
GameObject.Find("Player");
}
これは毎フレーム、シーン全体を探しています。
オブジェクト数が少ないうちは気づきにくいのですが、規模が大きくなると処理負荷が増えやすいです。
そのため、Find系は「本当に動的検索が必要な時だけ」に絞るのがおすすめです。
例えばこんなケースですね。
- 動的生成されたオブジェクトを探したい
- テスト用に一時取得したい
- シーンによって存在が変わる
逆に、固定オブジェクトならInspector参照のほうが安全です。
Singletonで取得する方法
GameManagerのように、「ゲーム全体で1つだけ存在するもの」を扱う時によく使われるのがSingletonです。
例えばこんな形ですね。
public class GameManager : MonoBehaviour
{
public static GameManager instance;
void Awake()
{
instance = this;
}
}
すると、どこからでもこう書けます。
GameManager.instance.score += 100;
かなり便利です。
ただ、便利すぎるので乱用されやすいんですよね。
初心者の頃は、「全部Singletonにすればいいじゃん!」となりがちです(笑)
でも実際には、依存関係が増えすぎると管理が難しくなります。
- どこから変更されたか分からない
- 修正時の影響範囲が読めない
- テストしにくい
こういう状態になりやすいです。
なので、まずは以下くらいに限定するのがおすすめです。
- GameManager
- AudioManager
- SceneManager系
「ゲーム全体で1つだけ必要な管理役」に絞ると、かなり使いやすくなります。
Unityで別スクリプトの変数・Bool・関数を操作する方法
ここまでで「参照を取得する方法」は見えてきたと思います。
次は、取得したスクリプトを実際にどう操作するのかを整理していきましょう。
Unityでは、参照を取得したあとに .(ドット演算子)を使って、中の変数や関数へアクセスします。
この部分が理解できると、
- HPを減らす
- スコアを加算する
- 攻撃処理を呼び出す
- ゲームオーバー判定を切り替える
といった“ゲームっぽい処理”が一気に作りやすくなります。
変数を書き換える方法
まず一番よく使うのが、別スクリプトの変数変更です。
例えば、PlayerHPスクリプトにHPがあるとします。
public int hp = 100;
そして別スクリプト側で参照を取得済みなら、こう書けます。
playerHP.hp -= 10;
これは「playerHPの中にあるhpを10減らす」という意味です。
ゲームではかなり頻繁に使います。
- ダメージ処理
- スコア加算
- 移動速度変更
- 残機管理
など、ほぼ毎回出てきます。
ただ、実務では「変数を直接触りすぎない」こともかなり大切です。
例えば、どこからでもHPを書き換えられる状態になると、
- 急にHPが0になる
- 回復タイミングが分からない
- デバッグが難しい
という状態になりやすいです。
そのため、中級者以降は「関数経由で変更する」ケースが増えていきます。
ただ、初心者のうちはまず「参照先の変数へアクセスできる感覚」を掴むことがかなり重要です。
データ管理をさらに強化したい場合は、保存システム系アセットもかなり便利です。
Easy Save
✅アセットストアでチェックする
Boolを取得・変更する方法
Boolは「true / false」で状態を管理するための型です。
Unityではかなり多用されます。
例えばこんな感じですね。
public bool isDead;
これを別スクリプト側から変更できます。
playerHP.isDead = true;
よく使われる用途はこちらです。
- 攻撃中か
- 死亡しているか
- ゲームオーバーか
- ジャンプ中か
- 会話中か
初心者が混乱しやすいのは、「Boolは状態フラグ」という感覚ですね。
例えば、
if(playerHP.isDead)
{
GameOver();
}
これは「もし死亡状態ならゲームオーバー実行」という意味です。
ちなみに、初心者の頃によく見るのがこちらです。
if(playerHP.isDead == true)
もちろん動きます。
ただ、Boolはもともとtrue/falseを返すので、慣れてくるとこちらのほうがシンプルです。
if(playerHP.isDead)
コード量が少ないだけで、かなり読みやすくなりますよ。
関数を呼び出す方法
Unityで他スクリプトを操作する中で、実は一番重要なのが「関数呼び出し」です。
例えば、PlayerHP側にこんな関数があるとします。
public void Damage(int damage)
{
hp -= damage;
}
これを別スクリプトから実行できます。
playerHP.Damage(10);
これはかなり実務寄りの書き方です。
なぜかというと、「HP変更ルール」をPlayerHP側へまとめられるからです。
例えば後から、
- 無敵時間
- 防御力計算
- ダメージエフェクト
- 死亡判定
を追加したくなった時でも、Damage関数だけ修正すれば済みます。
逆に、どこからでも直接 hp -= 10; をしていると、修正箇所がバラバラになりやすいです。
このあたりは、Unity初心者から中級者へ進むタイミングでかなり重要になる考え方ですね。

「値を直接触る」より、「役割を関数へまとめる」ほうが安全なケースはかなり多いです。
UnityでNullReferenceExceptionが出る原因
Unityで別スクリプトを扱い始めると、かなり高確率で遭遇するのがこちらです。
NullReferenceException: Object reference not set to an instance of an object
最初は「英語が怖い…」となりやすいんですが、意味をシンプルにすると、
「中身が入っていないものを使おうとしました」
これだけです。
Unity初心者の頃は、コードミスより“参照ミス”のほうが圧倒的に多いです。
なので、まずは「null = 空っぽ」という感覚を持っておくとかなり楽になります。
参照がnullになる原因
特によくある原因はこちらです。
- Inspectorで参照設定していない
- GetComponent対象が存在しない
- Findで取得失敗している
- Destroy済みオブジェクトを参照している
例えばこちら。
public PlayerHP playerHP;
void Start()
{
playerHP.hp -= 10;
}
これ自体は問題なさそうに見えます。
でも、InspectorでPlayerHPを設定していなければ、中身は空です。
つまり、Unity側から見るとこんな状態なんですね。
playerHP = null;
そのため、
playerHP.hp
へアクセスした瞬間にエラーになります。
ここで初心者が混乱しやすいのが、
- 変数は存在している
- コード補完も出る
のに、実際には中身が入っていないことです。
これはかなりUnity特有のつまずきポイントですね。
また、GetComponentでも同じことが起きます。
playerHP = GetComponent<PlayerHP>();
もし同じGameObjectにPlayerHPが付いていなければ、取得結果はnullになります。
つまり、「取得処理を書いた = 必ず取得成功」ではありません。
“対象が存在するか”まで含めて確認が必要です。
最初に確認すべきチェックリスト
NullReferenceExceptionが出た時、私はまずこの順番で確認しています。
- Inspector参照が入っているか
- GetComponent対象が存在するか
- Find対象の名前が合っているか
- Destroy後に触っていないか
- Consoleの行番号を確認する
特に初心者のうちは、「Consoleの行番号を見る」クセを付けるだけでかなり成長できます。
Unityはちゃんと“どの行で失敗したか”を教えてくれているんですよね。
例えば、
PlayerAttack.cs:35
と表示されていれば、35行目を見ればOKです。
最初はエラー全文を読む必要はありません。
まずは、
- どのスクリプトか
- 何行目か
ここだけ見られるようになると、かなり解決しやすくなります。
NullReferenceExceptionについては、こちらでも原因を詳しく整理しています。
Unity初心者におすすめの取得方法と使い分け
ここまで色々な取得方法を見てきましたが、初心者の頃は「結局どれを使えばいいの?」となりやすいですよね。
実際、Unityでは“動く方法”が複数あります。
ただ、開発が進むほど「後から管理しやすいか」がかなり重要になってきます。
特に最初のうちは、“書きやすさ”より“事故りにくさ”を優先したほうが成長しやすいです。
初心者はまずSerializeFieldを優先しよう
最初におすすめしたいのは、Inspectorで参照を設定する方法です。
[SerializeField] private PlayerHP playerHP;
これを使うと、Unityエディタ上で参照状態が見えます。
つまり、「何につながっているか」が視覚的に確認できるんですね。
これがかなり大きいです。
初心者の頃は、“コードの問題”なのか“参照漏れ”なのかを切り分けるのが難しいんですよね。
でもInspector参照なら、空欄かどうかを見ればすぐ分かります。
例えばこんな場面です。
- HPバーとPlayerHP
- UIボタンとGameManager
- 敵とステータス管理
- カメラとプレイヤー
こういう「事前に対象が決まっているもの」は、かなり相性がいいです。
逆に、初心者の頃にありがちなのが、“全部Findで取る”状態です。
もちろん動く場合もあります。
でも、後からシーンが大きくなると、
- 名前変更で壊れる
- 取得漏れが起きる
- null事故が増える
という問題がかなり出やすくなります。
なので最初は、「固定オブジェクトならInspector参照」がかなりおすすめです。
シリアライズやInspector表示については、こちらの記事もつながりが深いです。
慣れたらGetComponentを増やす
Unityに慣れてくると、GetComponentを使う場面がかなり増えてきます。
特に「同じGameObject内の役割分担」を作る時ですね。
例えば、PlayerObjectに
- 移動
- HP
- 攻撃
- アニメーション
を分けている場合、それぞれが連携する必要があります。
その時にGetComponentがかなり自然に使えます。
playerHP = GetComponent<PlayerHP>();
Unityは「GameObjectに機能を付け足す設計」が基本なので、GetComponentを理解すると“Unityらしい構造”がかなり見えてきます。
また、中級者以降は「キャッシュ」の感覚も重要になります。
つまり、一度取得した参照を保存して使い回す考え方ですね。
これができるようになると、パフォーマンスや設計の理解が一段深くなっていきます。
FindとSingletonは便利だが乱用注意
FindやSingletonは、本当に便利です。
特に初心者の頃は、「どこからでもアクセスできる!」という快感があります(笑)
ただ、便利なものほど使いすぎやすいんですよね。
例えばFindを多用すると、
- 名前変更で突然動かなくなる
- シーン依存が増える
- 取得ミスが見えにくい
という問題が出やすいです。
また、Singletonを増やしすぎると、今度は“何でもアクセスできる世界”になります。
すると、
- どこから変更されたか追えない
- 依存関係が複雑になる
- 修正時に別機能まで壊れる
という状態になりやすいです。
実際、Unity中級者あたりで一度「Singletonまみれ問題」を経験する人はかなり多い印象があります。
なので、まずはこのくらいの感覚がおすすめです。
| 状況 | おすすめ |
|---|---|
| 固定オブジェクト | Inspector参照 |
| 同一GameObject | GetComponent |
| 全体管理 | Singleton |
| 動的検索 | Find系 |

まずは「安全で見える方法」を優先すると、Unityの参照管理でかなり迷いにくくなりますよ。
まとめ|Unityのスクリプト参照は「取得方法の使い分け」が重要
Unityで他のスクリプトを操作するには、まず「参照を取得する」という考え方がかなり重要です。
最初は少しややこしく感じますが、ここを理解できると、
- HP管理
- UI制御
- 敵AI
- ゲームマネージャー
など、ゲーム全体の仕組みがかなり組みやすくなります。
今回のポイントを整理すると、こんな感じです。
| 状況 | おすすめ |
|---|---|
| 固定オブジェクト | Inspector参照 |
| 同じGameObject | GetComponent |
| 全体管理 | Singleton |
| 動的検索 | Find系 |
特に初心者のうちは、
- まずInspector参照
- 次にGetComponent
この順で慣れていくと、かなり混乱しにくいです。
逆に、FindやSingletonを最初から多用すると、「動くけど管理しづらいコード」になりやすいので注意ですね。
私自身、Unityを始めた頃は「GetComponentって結局何してるの…?」状態でした(笑)
でも、参照の仕組みを理解してからは、エラー原因やコードの意味がかなり見えやすくなりました。
特に最近は、AI生成コードを読む機会も増えています。
その時に、「なぜこの取得方法を使っているのか」が分かるだけでも、コード理解がかなり楽になります。
まずは、
- 参照とは何か
- nullとは何か
- どの取得方法を選ぶべきか
この3つを意識するだけでも、Unity開発はかなり進めやすくなりますよ。
さらにC#設計やUnityのコード理解を深めたい人は、こういった書籍もかなり参考になります。
Unityゲーム プログラミング・バイブル 2nd Generation
✅ Amazonでチェックする|✅ 楽天でチェックする
参考情報:
- Unity公式 GetComponent API
- Unity公式 MonoBehaviour API
よくある質問(FAQ)
- QGetComponentとFindはどちらを使うべき?
- A
基本的には、使えるならGetComponentのほうがおすすめです。
理由はシンプルで、
- 取得範囲が限定されている
- 軽い
- どこを参照しているか分かりやすい
からです。
特に、同じGameObject内のスクリプト取得なら、まずGetComponentを優先してOKです。
逆にFind系は、
- 動的生成されたオブジェクト
- シーンごとに存在が変わるもの
- 一時的な検索
など、“検索が必要な場面”に限定すると管理しやすくなります。
初心者の頃は「Findのほうが簡単」に感じやすいんですが、プロジェクトが大きくなるほど、Inspector参照やGetComponentの重要性がかなり見えてきます。
- Qpublicを使わないとアクセスできませんか?
- A
外部スクリプトから直接アクセスするなら、基本はpublicが必要です。
public int hp;これなら、別スクリプトからこう触れます。
playerHP.hp -= 10;ただ、最近のUnity開発では「全部publicにする」ケースは減っています。
例えばこちら。
[SerializeField] private int hp;これはInspector表示だけ許可して、外部アクセスは禁止する書き方です。
そして実際の変更は、関数経由で行います。
public void Damage(int damage) { hp -= damage; }こうすると、HP変更ルールを1か所へまとめやすくなります。
最初はpublic中心でも問題ありませんが、慣れてきたら「必要最小限だけ公開する」感覚を持てるとかなり実務寄りになりますよ。
- QなぜInspector参照が推奨されるのですか?
- A
一番大きい理由は、“見える”からです。
Unity初心者の頃は、コードだけで参照を追うのがかなり難しいんですよね。
でもInspector参照なら、
- 何につながっているか
- 参照が空かどうか
- 設定漏れがないか
をUnityエディタ上ですぐ確認できます。
さらに、Find系のような検索処理も不要です。
なので、
- 安全
- 軽い
- デバッグしやすい
というメリットがあります。
特に初心者の頃は、「コードの正しさ」より「参照漏れ」で止まるケースがかなり多いです。
そのため、まずはInspector参照中心で慣れていくと、Unityのスクリプト管理がかなり理解しやすくなります。











※当サイトはアフィリエイト広告を利用しています。リンクを経由して商品を購入された場合、当サイトに報酬が発生することがあります。
※本記事に記載しているAmazon商品情報(価格、在庫状況、割引、配送条件など)は、執筆時点のAmazon.co.jp上の情報に基づいています。
最新の価格・在庫・配送条件などの詳細は、Amazonの商品ページをご確認ください。