質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

2回答

2415閲覧

Invoke()の使い方を教えてください

退会済みユーザー

退会済みユーザー

総合スコア0

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2021/04/14 00:56

編集2021/04/14 02:11

キャラが設定した位置に入ってから二秒後にブロックが現れるという状況を作りたいとおもっています。
最初はブロックが現れるということでSetActiveを罠用のコードに書いて、プレイヤーのコードで呼び出そうとしました。
直接呼び出そうとして Invoke("trap3.Trap3Activate",2f)のように書いていたのですが、これは調べているうちに間違いだとわかりました。

なので別の箇所に プレイヤーのコードで
void Trap3Invoke()
{
trap3.Trap3Activate();
}
と作り、

if (collision.gameObject.tag == "TrapSwitch3") { Invoke("Trap3Invoke", 2.0f); }

というコードを書いたのですが、うまくいきません。
原因を教えてほしく存じます。

画面は以下になります。

Switch3の位置
イメージ説明

2秒後に表示したいブロック
イメージ説明

コード全体は以下のとおりです。
罠のスイッチにはTrapSwitch3のタグがつけてあります。

罠用コード

using System.Collections; using System.Collections.Generic; using UnityEngine; public class Trap3 : MonoBehaviour { public GameObject Bricks_16; public GameObject Bricks_16_2; public GameObject Bricks_16_3; public GameObject Bricks_16_4; private void Start() { } public void Trap3Activate() { Debug.Log("罠3発動"); Bricks_16_2.SetActive(true); } } コード

プレイヤーコード

using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerManager : MonoBehaviour { //public変数 [Header("横方向速度")] public float xspeed = 8; [Header("ジャンプ力")] public float jumpPower = 1000; public GroundCheck ground;//GroundCheckを貼り付ける public GameManager gameManager;//GameManagerを貼り付ける public LayerMask blockLayer; public Traps trap1; public Trap2 trap2; public Trap3 trap3; //プライベート変数 private float speed; private bool isGround = false; Animator animator; bool isDead = false; public enum DIRECTION_TYPE { STOP, RIGHT, LEFT, } DIRECTION_TYPE direction = DIRECTION_TYPE.STOP; Rigidbody2D rigidbody2D; private void Start() { rigidbody2D = GetComponent<Rigidbody2D>(); animator = GetComponent<Animator>(); } void Update() { //接地判定を得る isGround = ground.IsGround(); float horizontalKey = Input.GetAxis("Horizontal"); if(horizontalKey == 0) { //止まっている direction = DIRECTION_TYPE.STOP; animator.SetBool("run", false); } else if (horizontalKey > 0) { //右向きに進む direction = DIRECTION_TYPE.RIGHT; animator.SetBool("run", true); } else if (horizontalKey < 0) { //左向きに進む direction = DIRECTION_TYPE.LEFT; animator.SetBool("run", true); } //スペースボタンでかつ接地していればジャンプ if (Input.GetKeyDown("space") && isGround) { //ジャンプ関数 Jump(); } //2秒遅れてブロック出現←説明文で書いたコード void OnTriggerEnter2D(Collider2D collision) { if (collision.gameObject.tag == "TrapSwitch3") { Invoke("Trap3Invoke", 2.0f); } } } private void FixedUpdate() { if(isDead) { return; } switch (direction) { case DIRECTION_TYPE.STOP: speed = 0; break; case DIRECTION_TYPE.RIGHT: speed = xspeed; transform.localScale = new Vector3(1, 1, 1); break; case DIRECTION_TYPE.LEFT: speed = -xspeed; transform.localScale = new Vector3(-1, 1, 1); break; } rigidbody2D.velocity = new Vector2(speed,rigidbody2D.velocity.y); } void Jump() { //上に力を加える rigidbody2D.AddForce(Vector2.up * jumpPower); } private void OnTriggerEnter2D(Collider2D collision) { if (isDead) { return; } if (collision.gameObject.tag == "Trap") { PlayerDie(); } if (collision.gameObject.tag == "Goal") { Debug.Log("ゴール"); gameManager.GameClear(); } if (collision.gameObject.tag == "TrapSwitch1") { Debug.Log("罠ジャンプ"); trap1.Trap1Activate(); } if (collision.gameObject.tag == "TrapSwitch2") { Debug.Log("罠2始動"); trap2.Trap2Activate(); } //Invoke発動のための関数←説明文で書いたコード void Trap3Invoke() { trap3.Trap3Activate(); } } private void PlayerDie() { isDead = true; rigidbody2D.velocity = new Vector2(0, 0); rigidbody2D.AddForce(Vector2.up * jumpPower); animator.Play("PlayerDie"); CapsuleCollider2D capsuleCollider2D = GetComponent<CapsuleCollider2D>(); Destroy(capsuleCollider2D); gameManager.GameOver(); } } コード

イメージ説明

void Start() { } void Update() { if (Input.GetKey(KeyCode.Space)) { samp.Move(); // Debug.Log(samp); Invoke("Vanish2", 1.5f); } } private void Vanish2() { samp.Vanish(); } } コード
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Sample : MonoBehaviour { public float xspeed; public float yspeed; public GameObject squ; public GameObject cir; public GameObject cup; Rigidbody2D rigidcir; Rigidbody2D rigidcup; Rigidbody2D rigidsqu; private void Start() { rigidcir = cir.GetComponent<Rigidbody2D>(); rigidsqu = squ.GetComponent<Rigidbody2D>(); rigidcup = cup.GetComponent<Rigidbody2D>(); } private void Update() { } public void Move()//これを呼び出したい { cir.transform.Translate(-xspeed, -yspeed, 0); squ.transform.Translate(-xspeed, yspeed, 0); // Debug.Log(squ); } public void Vanish() { cup.SetActive(false); } } コード
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Circle : MonoBehaviour { // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { } private void OnCollisionEnter2D(Collision2D collision) { if (collision.gameObject.tag == "Square") { Debug.Log("サークルとスクウェアが接触しました"); Debug.Log( collision); Debug.Log( gameObject); } } } コード

イメージ説明

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

YAmaGNZ

2021/04/14 01:06

OnTriggerEnter2Dの中にTrap3Invokeが定義してありますがあっていますか? また「うまくいきません」だけではなく、どうなるのか具体的に書いてください。 コンパイル時に○○というエラーが出るとか、実行時に△△というエラーになるとか、該当部分が呼ばれないとか
退会済みユーザー

退会済みユーザー

2021/04/14 01:16

最初はOnTriggerEnter2Dの中には入れてなかったのですが、これの中に入れないcollisionが定義されてないとしてエラーが出たので入れました。 「うまくいきせん」については説明が足らず申し訳ありません。 指定の箇所を通過しても何も起こらず、コンソールに「罠3発動」の文字も出ません。 Invoke("trap3.Trap3Activate",2f)と書いていたときはInvokeが呼び出せない、というエラー文は出ていたのですが。 あと、いつのまにか発動箇所のオブジェクトに乗るようになってしまいました・・・。Istriggerはオンにしているのですが。(図を追加しておきます)
hogefugapiyo

2021/04/14 01:38

OnTriggerEnter2Dが重複しているのでそこは直したほうがいいと思います trap3を追加する前にはtrap1やtrap2は動いてたんですよね?
退会済みユーザー

退会済みユーザー

2021/04/14 01:55 編集

trap1,2は今でも動作しています。 下の回答のところでも書いたのですが、Invoke がUpdateの中でしか動作しないようなのでUpdateの中にもっていったのですが、その中ではcollisionが定義されていないためエラーが発生し、改めてOnTriggerEnter2Dを書かないといけない、と考えたんです。
hogefugapiyo

2021/04/14 02:14

Unityの仕様上、Triggerに入ったときに呼ばれるのはクラス直下にあるOnTriggerEnter2Dのほうだと思います。(Update内のOnTriggerEnter2Dは呼ばれません) InvokeはUpdateの中でなくても動作します。なのでtrap1や2のところのほうにtrap3の処理もまとめると良いかと思います
退会済みユーザー

退会済みユーザー

2021/04/14 02:22

ありがとうございます。うまくいきました。 最初は if (collision.gameObject.tag == "TrapSwitch1") { Debug.Log("罠ジャンプ"); trap1.Trap1Activate(); } if (collision.gameObject.tag == "TrapSwitch2") { Debug.Log("罠2始動"); trap2.Trap2Activate(); } if (collision.gameObject.tag == "TrapSwitch3") { Invoke("Trap3Invoke", 2.0f); } というように並べて書いていたのですが・・・。 原因がなんだったのか、もう一度探ってみます。 ありがとうございました。
guest

回答2

0

既存のソースコードから変更点を少なく実装するとした場合

  1. OnTriggerEnter2Dを1つにまとめ、Trap3の処理もそこに記述
  2. Trap3Invokeはクラス直下に置く(スコープの関係)

でいけるんじゃないかと思います。

:余談:
ちなみに「2秒後」っていうのをTrap3側にやらせるという考え方もできます。そうするとTrap3側で秒数のコントロールができるので、2秒後に起動するものを作ったり10秒後に起動するものを作ったりがやりやすくなります。

cs

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class PlayerManager : MonoBehaviour { 6 7 //public変数 8 [Header("横方向速度")] public float xspeed = 8; 9 [Header("ジャンプ力")] public float jumpPower = 1000; 10 public GroundCheck ground;//GroundCheckを貼り付ける 11 public GameManager gameManager;//GameManagerを貼り付ける 12 public LayerMask blockLayer; 13 public Traps trap1; 14 public Trap2 trap2; 15 public Trap3 trap3; 16 17 //プライベート変数 18 private float speed; 19 private bool isGround = false; 20 Animator animator; 21 bool isDead = false; 22 23 public enum DIRECTION_TYPE { 24 STOP, 25 RIGHT, 26 LEFT, 27 } 28 29 DIRECTION_TYPE direction = DIRECTION_TYPE.STOP; 30 31 Rigidbody2D rigidbody2D; 32 33 private void Start() { 34 rigidbody2D = GetComponent<Rigidbody2D>(); 35 animator = GetComponent<Animator>(); 36 } 37 38 void Update() { 39 //接地判定を得る 40 isGround = ground.IsGround(); 41 42 float horizontalKey = Input.GetAxis("Horizontal"); 43 44 if (horizontalKey == 0) { 45 //止まっている 46 direction = DIRECTION_TYPE.STOP; 47 animator.SetBool("run", false); 48 49 } else if (horizontalKey > 0) { 50 //右向きに進む 51 direction = DIRECTION_TYPE.RIGHT; 52 animator.SetBool("run", true); 53 54 } else if (horizontalKey < 0) { 55 //左向きに進む 56 direction = DIRECTION_TYPE.LEFT; 57 animator.SetBool("run", true); 58 59 } 60 //スペースボタンでかつ接地していればジャンプ 61 if (Input.GetKeyDown("space") && isGround) { 62 //ジャンプ関数 63 Jump(); 64 } 65 66 } 67 68 69 private void FixedUpdate() { 70 if (isDead) { 71 return; 72 } 73 switch (direction) { 74 case DIRECTION_TYPE.STOP: 75 speed = 0; 76 break; 77 case DIRECTION_TYPE.RIGHT: 78 speed = xspeed; 79 transform.localScale = new Vector3(1, 1, 1); 80 break; 81 case DIRECTION_TYPE.LEFT: 82 speed = -xspeed; 83 transform.localScale = new Vector3(-1, 1, 1); 84 break; 85 86 } 87 rigidbody2D.velocity = new Vector2(speed, rigidbody2D.velocity.y); 88 } 89 90 void Jump() { 91 //上に力を加える 92 rigidbody2D.AddForce(Vector2.up * jumpPower); 93 } 94 95 private void OnTriggerEnter2D(Collider2D collision) { 96 if (isDead) { 97 return; 98 } 99 100 if (collision.gameObject.tag == "Trap") { 101 PlayerDie(); 102 103 } 104 105 if (collision.gameObject.tag == "Goal") { 106 Debug.Log("ゴール"); 107 gameManager.GameClear(); 108 } 109 110 if (collision.gameObject.tag == "TrapSwitch1") { 111 Debug.Log("罠ジャンプ"); 112 trap1.Trap1Activate(); 113 114 } 115 116 if (collision.gameObject.tag == "TrapSwitch2") { 117 Debug.Log("罠2始動"); 118 trap2.Trap2Activate(); 119 120 } 121 122 if (collision.gameObject.tag == "TrapSwitch3") { 123 Debug.Log("罠3が2秒後に始動"); 124 Invoke("Trap3Invoke", 2.0f); 125 } 126 } 127 128 //Invoke発動のための関数←説明文で書いたコード 129 void Trap3Invoke() { 130 Debug.Log("罠3始動"); 131 trap3.Trap3Activate(); 132 } 133 134 135 private void PlayerDie() { 136 isDead = true; 137 rigidbody2D.velocity = new Vector2(0, 0); 138 rigidbody2D.AddForce(Vector2.up * jumpPower); 139 animator.Play("PlayerDie"); 140 CapsuleCollider2D capsuleCollider2D = GetComponent<CapsuleCollider2D>(); 141 Destroy(capsuleCollider2D); 142 gameManager.GameOver(); 143 } 144 145} 146 147

投稿2021/04/14 02:25

hogefugapiyo

総合スコア3302

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

この回答で改善するかは分かりませんが、ソースを見ておかしいと思った部分を指摘します。

C#

1 2 void Update() 3 { 4 //接地判定を得る 5 isGround = ground.IsGround(); 6 7 float horizontalKey = Input.GetAxis("Horizontal"); 8 9 if(horizontalKey == 0) 10 { 11 //止まっている 12 direction = DIRECTION_TYPE.STOP; 13 animator.SetBool("run", false); 14 } 15 else if (horizontalKey > 0) 16 { 17 //右向きに進む 18 direction = DIRECTION_TYPE.RIGHT; 19 animator.SetBool("run", true); 20 } 21 else if (horizontalKey < 0) 22 { 23 //左向きに進む 24 direction = DIRECTION_TYPE.LEFT; 25 animator.SetBool("run", true); 26 } 27 //スペースボタンでかつ接地していればジャンプ 28 if (Input.GetKeyDown("space") && isGround) 29 { 30 //ジャンプ関数 31 Jump(); 32 } 33 34 //2秒遅れてブロック出現←説明文で書いたコード 35 void OnTriggerEnter2D(Collider2D collision) 36 { 37 if (collision.gameObject.tag == "TrapSwitch3") 38 { 39 Invoke("Trap3Invoke", 2.0f); 40 } 41 } 42 } 43

C#

1 private void OnTriggerEnter2D(Collider2D collision) 2 { 3 if (isDead) 4 { 5 return; 6 } 7 8 if (collision.gameObject.tag == "Trap") 9 { 10 PlayerDie(); 11 } 12 13 if (collision.gameObject.tag == "Goal") 14 { 15 Debug.Log("ゴール"); 16 gameManager.GameClear(); 17 } 18 19 if (collision.gameObject.tag == "TrapSwitch1") 20 { 21 Debug.Log("罠ジャンプ"); 22 trap1.Trap1Activate(); 23 } 24 25 if (collision.gameObject.tag == "TrapSwitch2") 26 { 27 Debug.Log("罠2始動"); 28 trap2.Trap2Activate(); 29 } 30 31 //Invoke発動のための関数←説明文で書いたコード 32 void Trap3Invoke() 33 { 34 trap3.Trap3Activate(); 35 } 36 } 37

OnTriggerEnter2DがUpdateの中とPlayerManagerクラスのプライベートメソッドの2箇所で定義されています。
実際に呼ばれるのはPlayerManagerクラスのプライベートメソッドのほうになります。
この為、Invokeを実行しようとしているOnTriggerEnter2Dのほうは実行されません。

また、Trap3InvokeもPlayerManagerクラスのプライベートメソッドの内部で定義されています。
OnTriggerEnter2Dの中で定義するとOnTriggerEnter2Dの中でのみ有効となります。
そして、定義だけなので当然実行されません。

このことから、スコープについて理解されていないように思えます。

投稿2021/04/14 01:34

YAmaGNZ

総合スコア10268

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2021/04/14 01:45

やっぱりOnTriggerEnter2Dが二箇所あるのはおかしいのですね。 最初は if (collision.gameObject.tag == "TrapSwitch2") { Debug.Log("罠2始動"); trap2.Trap2Activate(); } if (collision.gameObject.tag == "TrapSwitch3") { Invoke("Trap3Invoke", 2.0f); } のように並べて書いていましたが、Invokeを使えるのはUpdate関数の中だけのようでしたので、まるごとそっちに持っていったんです。この場合どうすればよいのでしょうか。
YAmaGNZ

2021/04/14 01:50

公式リファレンスにStartから呼び出すような記載がありましたが、InvokeがUpdate関数内でしか呼べないというのはどこの情報でしょうか?
退会済みユーザー

退会済みユーザー

2021/04/14 02:05

別のプロジェクトで自分で試しました。 質問のところに追加しておきます。
YAmaGNZ

2021/04/14 02:11

追記されたソースは何なのでしょうか? InvokeをUpdate内で呼んでいるだけであって、「Invokeを使えるのはUpdate関数の中だけ」ということにはなりません。
退会済みユーザー

退会済みユーザー

2021/04/14 02:17

すみません。たしかにStart関数の中でも動きました。Start関数の方に移動させてみます。
YAmaGNZ

2021/04/14 02:19

違います。動かしたいタイミングで呼ぶべきです。 貴方が理解しなくてはならないのは、関数や変数の定義する場所によってどこから使えるのかなどスコープについてです。
退会済みユーザー

退会済みユーザー

2021/04/14 02:30

そのあたりの理解が足りてないことはわかりました。 勉強しておきます。 不勉強で申し訳ありません。 教えていただき、ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問