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

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

新規登録して質問してみよう
ただいま回答率
85.37%
Unity

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

Q&A

解決済

1回答

2828閲覧

unityカメラの連続判定問題

Kirby2318

総合スコア69

Unity

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

0グッド

0クリップ

投稿2020/08/23 06:32

編集2020/08/27 08:28
コード ```~~今unityのカメラの扱いで様々な移動方法について、勉強しているときに。昔のゲームでAtari2600にH.E.R.Oというゲームがあったのですが、あのようにプレイヤーがカメラ外から移動したら、カメラを移動するプログラムを作成しました。 以下がそのコードです。~~

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Camera : MonoBehaviour
{
public SpriteRenderer player;

void Start() { player = GetComponent<SpriteRenderer>(); //レンダー取得 } void Update() { if (!player.isVisible) { transform.position += new Vector3(-18f, 0,transform.position.z); } }

}

テストということなので、プレイヤーが画面の左に移動したときだけの処理を書きました。 このまま実行すると以下のエラーが発生します。 There is no 'SpriteRenderer' attached to the "MainCamera" game object, but a script is trying to access it. You probably need to add a SpriteRenderer to the game object "MainCamera". Or your script needs to check if the component is attached before using it. ~~対象のレンダーがアタッチされていないとのことなので、ああ。なぁんだ。と思い、プレイヤーオブジェクトをカメラのスクリプトの欄にアタッチしても、変わりません。あれ?と思い、アタッチしているか再確認したら、ゲームを開始するとなしになってアタッチされていないと表示されることがわかったのです。プログラム自体にミスがあるのか確認するために、ゲーム起動中にアタッチすると、カメラがレンダーの対象を認識してくれて、プレイヤーが画面外に移動すると、しっかりとカメラが指定した座標を毎回移動してくれます。ただ、開始時にはこれが実現できません。これを何とかする方法がないのか、調べても全く分かりません。スクリプトから、アタッチする方法があるのかないのか、そもそも他の方法があるのかわかる方がいましたら教えてください。~~ 今修正したところ、以下のようなコードになり。画面にオブジェクトがいるのにもかかわらず、アップデートがずっとこのメソッドを呼び出し、カメラが変数の最大値の座標まで移動してしまいます。

using JetBrains.Annotations;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Camera : MonoBehaviour
{
public SpriteRenderer player ;

void Update() { if (!player.isVisible) { transform.position += new Vector3(-18f, 0,transform.position.z); } }

}

いろいろと試行錯誤を加えた結果、様々な関数を試しても、同じ挙動になることがわかりました。なお今は、以下のプログラムを組んである状態です。 ```ここに言語を入力 using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class Cam_1 : MonoBehaviour { public SpriteRenderer targetRenderer; // 判定したいオブジェクトのrendererへの参照 float x = 1; void Update() { if (targetRenderer.isVisible) { Debug.Log("画面に表示されてるよ"); } else { Invoke("CameraInvoke", 5f); Debug.Log("画面から消えたよ"); } } public void CameraInvoke() { Camera.main.transform.position += new Vector3(-18f, 0, 0); } }

毎回変に思っていたのが、プレイヤーのオブジェクトがスタート時にデバックログで一度消えたと表示された後に、画面に表示されるみたいです。もしかしたら、その一回の感知だけでカメラが連続的に移動する原因となっているみたいです。

改善を試みた結果。。。以下のスクリプトで以下の問題が発覚しました。![イメージ説明
肉眼では支障のないレベルですが、ゲーム開始時の2フレームの間にスプライトが表示されていないことがわかりました。
以下のことを試したけど、毎回同じ問題が発生します。
①カメラ判定を利用したほかの関数を利用した。
➁オブジェクトを再配置

以上のことを試したのですが、変化がないことからもしかしたらUnityの仕様かもしれません。お気づきかもしれませんが、問題を確認するために以下のプログラムを専用メソッドに入れ、Invokeを利用して呼び出しています。そうすると、カメラが指定した時間に-36Fの位置にいることがわかりました。つまり、最初の2フレームを判定してプログラムが実行されたのが原因だと考えられます。

Camera.main.transform.position += new Vector3(-18f, 0, 0);//最初の2フレームで二回も実行された?

どうすればいいのかわかりません。

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

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

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

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

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

guest

回答1

0

ベストアンサー

MainCameraにSpriteRendererが無いのにアクセスしようとしてエラーが出ています。
SpriteRendererはMainCameraにアタッチされているコンポーネントで間違いないのでしょうか?
プレイヤーオブジェクトにアタッチされているべきコンポーネントではないですか?

Start内の処理でMainCameraのSpriteRendererをplayerに設定していますが、その処理は必要ですか?
GetComponentの前後にDebug.Logを入れてplayerの変化をご自身で確認してください。

--- 追記 ---
Renderer.isVisibleはゲームビューだけではなくシーンビューに写っていてもTrueを返します。
シーンビューにplayerが写っていないか確認してください。

修正内容を取り違えていました。

MainCameraの表示領域とCanvasの領域が合っていないのではないでしょうか?
Unity 2D:Canvasをカメラの表示領域に合わせる

[ゲーム開始時の2フレームの対策案]
プレイヤーオブジェクト側にOnBecameVisible()の処理を追加してはどうでしょうか?
OnBecameVisibleはRenderer(SpriteRenderer)コンポーネントがアタッチされたオブジェクトが見えるようになったときに呼び出されます。
Renderer.OnBecameVisible()

C#

1プレイヤーオブジェクト側の処理。 2public class Hoge : MonoBehaviour 3{ 4 public bool isBecameVisible; 5 6 private void OnBecameVisible() 7 { 8 Debug.Log("OnBecameVisible"); 9 isBecameVisible = true; 10 } 11}

C#

1Cam_1の修正 2public class Cam_1 : MonoBehaviour 3{ 4 5 public SpriteRenderer targetRenderer; // 判定したいオブジェクトのrendererへの参照 6 float x = 1; 7 8 public Hoge player; // <--- 追加 ---> 9 10 void Update() 11 { 12 // <--- 追加 ---> 13 if (!player.isBecameVisible) 14 return; 15 // <------------> 16 17 if (targetRenderer.isVisible) 18 { 19 20 Debug.Log("画面に表示されてるよ"); 21 } 22 else 23 { 24 25 Invoke("CameraInvoke", 5f); 26 Debug.Log("画面から消えたよ"); 27 } 28 } 29 public void CameraInvoke() 30 { 31 Camera.main.transform.position += new Vector3(-18f, 0, 0); 32 } 33}

投稿2020/08/23 11:45

編集2020/08/27 11:25
cc_KH

総合スコア108

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

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

Kirby2318

2020/08/26 14:09 編集

GetComponentをなくしてしまっては、カメラが毎アップデート反応してしまいます。しかし、cc_KHさんのおっしゃる通り、GetComponentを使ってしまうと、アタッチしたオブジェクトが空になってしまいます。ゲーム開始時に空になるものの、ゲーム再生中にアタッチをすると求めている挙動をしっかりと取ってくれます。何としてでも、開始前にアタッチする方法はないのですか? もうないのであれば、別の関数を使うことを検討しています。
cc_KH

2020/08/26 15:22 編集

SpriteRenderer playerがinspectorで指定していされていればGetComponentする必要はありません。 指定されていなければスクリプトでGetComponentする必要があります。 しかし、player = GetComponent<SpriteRenderer>();と記述した場合はCamera(Kirby2318さんが作成したスクリプト)がアタッチされているオブジェクトからSpriteRendererコンポーネントを取得するという意味になります。 つまり、MainCameraオブジェクトからSpriteRendererコンポーネントを取得しようとして、MainCameraオブジェクトにSpriteRendererコンポーネントが存在しないためnullが返ってきているということです。
Kirby2318

2020/08/26 15:32

こうなりましたら、ほかの関数を試すしかないみたいですね。
cc_KH

2020/08/26 16:48

こちらではScene上のオブジェクトがどのような関係になっているかわかりませんが、実行前にMainCameraのInspectorでCameraコンポーネントのSpriteRenderer playerの部分にPlayerオブジェクト(名前不明)をドラッグしてセットしておくだけではダメなのでしょうか?
cc_KH

2020/08/26 17:54 編集

Kirby2318さんの過去の投稿を拝見し、ADHDであることを確認しました。 上記の私の説明で解決できない、理解できない場合はどのような説明の仕方であれば理解しやすいかをご返答いただければ可能な限り対応したいと思います。
Kirby2318

2020/08/27 06:49

暖かい対応を本当にありがとうございます。何が原因なのか判明したので、上記のほうで確認していただけると幸いです。
cc_KH

2020/08/27 07:55 編集

Cam_1スクリプトを確認しました。 下記のAとBのGetComponentの違いについては理解できますか? (A) targetRenderer = GetComponent<Renderer>(); (B) targetRenderer = obj.GetComponent<Renderer>(); // objは判定したいオブジェクト
Kirby2318

2020/08/27 08:11

(A)はtargetRenderer変数にRendererコンポーネントを取得している状態、 (B)はobjに付与されているRendererコンポーネントをtargetRenderer変数に代入している状態? あれ、それだと同じなのかな。。。あまり理解できていないかもしれないです。
cc_KH

2020/08/27 10:20

AとBの違いは"どのオブジェクト"のコンポーネントを取得するかという点です。 Aの場合は、Cam_1スクリプトがアタッチされているMainCameraオブジェクトのRenderer(SpriteRenderer)コンポーネントを取得します。 しかし、MainCameraオブジェクトにはRenderer(SpriteRenderer)コンポーネントはアタッチされていないためnullを返し、targetRendererはnullとなります。 Bの場合は、objオブジェクトにアタッチされているRenderer(SpriteRenderer)コンポーネントを取得します。 objオブジェクトにはRenderer(SpriteRenderer)コンポーネントがアタッチされているので、targetRendererにはobjオブジェクトのRenderer(SpriteRenderer)が入ります。 Cam_1はinspector上でtargetRendererにRenderer(SpriteRenderer)がセットされているのでStart内でGetComponent<Renderer>()をする必要はありません。 しかし、AのtargetRenderer = GetComponent<Renderer>();をしてしまったためにtargetRendererがnullになっていました。 私がStart内でGetComponentをする必要はないと書いた理由は理解できたでしょうか? Kirby2318さんのコメント(2020/08/26 23:09)の疑問についても解決したでしょうか?
Kirby2318

2020/08/27 11:00

理解しましたが、解決していません。上記に今現在の問題を記述しました。何をしてら、この問題に対処できるかわかりません。見える見えないの判定はデバック六から確認できるのですが、開始の時に2度もプレイヤーが見えない状態が発生しているので、プレイヤーが動ける前にカメラが先に-18F移動してしまい。結果的にまだプレイヤーがカメラの領域にないため、この連鎖が起こってしまい、カメラが猛スピードでマイナスの方向へと移動してしまいます。現時点でいろいろ試して、この問題を回避しようと試みているのですが、まだという感じです。
cc_KH

2020/08/27 11:25

ゲーム開始時の2フレームの対策案を追記しました。
Kirby2318

2020/08/27 11:55 編集

おおお、感心しました。まるで今までの苦労がなかったかのように、解決されました。onBecameVisibleにそんな特徴があったのは知らなかったです。本当にありがとうございます!!!前も、こうした関数だけで解決することがあったのですが、どうやったら自己解決するものですか?経験しかないのでしょうか?
cc_KH

2020/08/28 00:14

解決してよかったです。 自己解決する方法は、調べることと試すことだと思います。 1.不具合の原因をDebug.Logなどで特定する。 2.原因の解決策を検索する。 3.検索で見つけた情報をもとに修正し試す。 この工程の繰り返ししかないと私は思います。 ただし、どの工程もプログラムの基礎知識がなければ理解できないですから、まずは基礎をしっかりと勉強してください。 経験を積めばそれぞれの工程にかかる時間も短縮できますので、最初は大変だと思いますが頑張ってください。
Kirby2318

2020/08/28 15:50

頑張ります!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.37%

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

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

質問する

関連した質問