「スクリプトBで毎フレーム、スクリプトAのオブジェクトをチェックする」とした場合、スクリプト間の実行順制御が問題になります。
単に解決するなら「スクリプトBの処理をスクリプトAより後に実行させる」ために、スクリプトBのUpdate
をLateUpdate
に変えて解決する方法もあります。
さらに発展的な解決方法として、C#の Event を活用して、HitGameObjectが変わったことをを通知する方法はどうでしょうか。こちらは学習コストに見合ったより良い実装スキルが身につくと思いますので是非チャレンジしてみてください。
デリゲート(Delegate)やイベント(Event)とは【C#】
http://kan-kikuchi.hatenablog.com/entry/Delegate
(Event の説明は結構ページの半分以上スクロールしたところにあります。そこまで読み飛ばしてもいいと思いますが、Delegate は Event の基礎になるので出来れば上から読んでいくのもいいと思います。)
Eventの仕組みを使うと「処理すべきタイミングを知ってる側」と「処理したい内容を知ってる側」を分けられることが利点として挙げられると思います。
Eventを使った方法を質問のお話に直して考えた場合、例えば
- スクリプトAが「Rayがオブジェクトにヒットした」というイベントを発行して
- スクリプトBがスクリプトAのイベントを受け取れるようにする
といった実装になるかなと思います。
以下に参考例のコードを示します。
csharp
1
2// スクリプトA(マウスと被ったオブジェクトをイベントとして公開する)
3
4public delegate void OnMouseHitEventHanlder(GameObject hitObject);
5
6public event OnMouseHitEventHanlder OnMouseHit;
7
8public GameObject HitGameObject;
9
10void Update()
11{
12 var hitObject = GetOnMouseHitGameObject();
13
14 HandleOnMouseHit(hitObject);
15
16 HitGameObject = hitObject;
17}
18
19void HandleOnMouseHit(GameObject hitObject)
20{
21 if (hitObject != null)
22 {
23 Debug.LogFormat("hit with {0}", hitObject);
24 // イベントを発行
25 OnMouseHit?.Invoke(hitObject);
26 }
27}
28
29GameObject GetOnMouseHitGameObject()
30{
31 var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
32 return Physics.Raycast(ray, out var hitObject)
33 ? hitObject.collider.gameObject
34 : null
35 ;
36}
37
csharp
1
2// スクリプトB(スクリプトAのイベントに反応して処理を実行する)
3
4void Start()
5{
6 A.OnMouseHit += OnMouseHitAction;
7}
8
9void OnDestroy()
10{
11 A.OnMouseHit -= OnMouseHitAction;
12}
13
14void OnMouseHitAction(GameObject hitObject)
15{
16 Debug.Log(hitObject.name);
17 audioSource.PlayOneShot(audioClip);
18}